/* ═══════════════════════════════════════════════════════════════════
   GLAMMBOX 2026 — RADIO
   The station is a stage, not a page of cards. One full-bleed opening
   image (film + living surface), one promise, one primary action, then
   the catalogue as editorial rows.
   Loads AFTER tokens.css and system.css. Uses only tokens.
   ─────────────────────────────────────────────────────────────────── */

/* ══ 1 · THE STAGE ════════════════════════════════════════════════ */
.rd-stage{
  position:relative;
  /* header.top is sticky and takes 85 px of flow, so a 100svh hero ends
     85 px past the fold. Subtract it, and stop padding for a bar that is
     already occupying its own space. */
  min-height:calc(100svh - var(--top-h));
  display:grid;
  grid-template-columns:minmax(0,1fr);
  grid-template-rows:1fr auto;
  align-items:end;
  padding:var(--s-6) var(--gutter) var(--s-6);
  isolation:isolate;
  overflow:clip;
  background:#07080A;
}
.rd-stage-gl,
.rd-stage video{
  position:absolute;inset:0;z-index:-3;
  width:100%;height:100%;display:block;
  object-fit:cover;
}
/* the film carries the page: grade it, do not bury it */
.rd-stage video{filter:contrast(1.12) saturate(.86) brightness(1.06)}
/* FOG PASS · 2026-09-17 — same veil as the home hero, same reduction.
   The liquid field is screened over the film; at .5 it was lifting the
   blacks into haze. At .22 it reads as a moving sheen on the material
   and the film keeps its own contrast. The 2026-09-17 scrim below is
   untouched: a darker backplate only raises the contrast it guards. */
.rd-stage-gl{
  z-index:-2;opacity:.22;mix-blend-mode:screen;
  background:radial-gradient(120% 90% at 50% 32%,#14171D 0%,#07080A 64%);
}
.rd-stage-gl[data-liquid="off"]{
  background:
    radial-gradient(78% 58% at 24% 20%,rgba(232,95,44,.20),transparent 62%),
    radial-gradient(120% 90% at 50% 34%,#151A22 0%,#07080A 66%);
}
/* HERO SCRIM · rebuilt 2026-09-17, same defect and same method as the
   /websites hero. The vertical gradient fell to .04-.06 alpha across
   26-46% of the stage — which is exactly the band the lede occupies at
   390px (measured: the copy box sits at y360-471 of an 844px stage).
   Backdrop luminance under that box measured max 192 with a worst-pixel
   contrast of 1.08:1 against the bone type on the phone and 2.31:1 on
   desktop. The film still breathes in the top quarter; from 38% down it
   is properly held back, so the brightest crowd frame in the loop still
   clears AA under the copy. */
.rd-stage::after{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:
    /* 2026-09-17, second pass: the 09-17 rebuild above was measured on
       the phone, where it holds (worst frame 11.5:1). On the desktop it
       did not — RADIO's headline is enormous and its box starts at 30%
       of an 814px stage, which is inside the .16->.50 ramp, and the
       worst frame of the loop came out at 5.38:1 against --gb-bone. The
       22% and 38% stops move; the 0% stop does not, so the top of the
       frame still opens the page. */
    linear-gradient(180deg,
      rgba(7,8,10,.66) 0%,
      rgba(7,8,10,.44) 22%,
      rgba(7,8,10,.74) 38%,
      rgba(7,8,10,.88) 54%,
      rgba(7,8,10,.94) 74%,
      rgba(7,8,10,.97) 100%),
    linear-gradient(90deg,rgba(7,8,10,.70) 0%,rgba(7,8,10,.40) 54%,rgba(7,8,10,.20) 100%);
}
/* the phone gets the least room between the type and the brightest part
   of the frame, so it holds the film back a step harder and stops
   lifting its brightness */
@media (max-width:768px){
  .rd-stage::after{
    background:
      linear-gradient(180deg,
        rgba(7,8,10,.70) 0%,
        rgba(7,8,10,.28) 18%,
        rgba(7,8,10,.74) 34%,
        rgba(7,8,10,.91) 50%,
        rgba(7,8,10,.96) 72%,
        rgba(7,8,10,.98) 100%),
      linear-gradient(90deg,rgba(7,8,10,.62) 0%,rgba(7,8,10,.38) 60%,rgba(7,8,10,.24) 100%);
  }
  .rd-stage video{filter:contrast(1.1) saturate(.86) brightness(.94)}
}
.rd-ident{max-width:min(56rem,100%);min-width:0;align-self:end}
.rd-ident .gb-kicker{margin:0 0 var(--s-4)}
.rd-stage h1{
  font-size:clamp(3.6rem,min(14vw,17svh),11.5rem);
  font-weight:620;
  line-height:.88;
  letter-spacing:var(--tr-mega);
  margin:0 0 var(--s-5);
  text-wrap:balance;
}
.rd-stage h1 em{
  font-family:var(--f-serif);font-style:italic;font-weight:400;
  letter-spacing:-.01em;
}
.rd-lede{max-width:46ch;margin:0 0 var(--s-6)}
.rd-stage .plays{margin:0 0 var(--s-5)}

/* the meter: five bars, the only literal "radio" flourish on the page */
.rd-meter{display:flex;align-items:flex-end;gap:3px;height:1.5rem}
.rd-meter i{
  display:block;width:2px;background:var(--gb-ember);border-radius:1px;
  animation:rdBar 1.5s var(--e-inout) infinite;transform-origin:bottom;
}
.rd-meter i:nth-child(1){height:.55rem;animation-delay:0s}
.rd-meter i:nth-child(2){height:1.4rem;animation-delay:.19s}
.rd-meter i:nth-child(3){height:.85rem;animation-delay:.38s}
.rd-meter i:nth-child(4){height:1.15rem;animation-delay:.11s}
.rd-meter i:nth-child(5){height:.6rem;animation-delay:.3s}
@keyframes rdBar{0%,100%{transform:scaleY(.32);opacity:.55}50%{transform:scaleY(1);opacity:1}}
@media (prefers-reduced-motion:reduce){.rd-meter i{animation:none;opacity:.8}}

.rd-stage-foot{
  min-width:0;
  display:flex;align-items:flex-end;justify-content:space-between;gap:var(--s-5);
  padding-top:var(--s-5);margin-top:var(--s-6);
  border-top:1px solid var(--gb-line);
  font-family:var(--f-mono);font-size:.66rem;letter-spacing:.2em;text-transform:uppercase;
  color:var(--gb-mute);
}
.rd-stage-foot a{color:var(--gb-bone-soft);text-decoration:none;display:inline-flex;align-items:center;min-height:44px}
.rd-stage-foot a:hover{color:var(--gb-ember)}
.rd-stage-foot .rd-live{display:flex;align-items:center;gap:.6rem;color:var(--gb-bone-soft)}

@media (max-width:768px){
  .rd-stage h1{font-size:clamp(3.2rem,min(22vw,11svh),6rem)}
  .rd-stage-foot{flex-direction:column;align-items:flex-start;gap:var(--s-3)}
}

/* ══ 2 · THE PROMISE ══════════════════════════════════════════════ */
.rd-promise{
  position:relative;z-index:var(--z-page);
  background:var(--gb-black);
  border-top:1px solid var(--gb-line);
  padding:var(--s-7) var(--gutter) var(--s-6);
}
.rd-promise-in{width:var(--shell-narrow);margin-inline:auto}
.rd-promise p{
  margin:0;color:var(--gb-bone-soft);
  font-size:clamp(1.05rem,1.9vw,1.32rem);line-height:1.6;
  max-width:62ch;
}
.rd-promise p em{font-family:var(--f-serif);font-style:italic;color:var(--gb-bone)}
.rd-facts{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(9rem,1fr));
  gap:var(--s-5);margin-top:var(--s-7);
}
.rd-fact{border-top:1px solid var(--gb-line);padding-top:var(--s-4)}
.rd-fact b{
  display:block;font-family:var(--f-display);font-weight:600;
  font-size:clamp(1.9rem,3.6vw,2.9rem);letter-spacing:-.03em;line-height:1;
  color:var(--gb-bone);
}
.rd-fact span{
  display:block;margin-top:.45rem;
  font-family:var(--f-mono);font-size:.64rem;letter-spacing:.2em;text-transform:uppercase;
  color:var(--gb-mute);
}

/* ══ 3 · THE BAND (now playing) ═══════════════════════════════════ */
.billboard-band{
  position:relative;z-index:var(--z-page);
  margin:0!important;
  padding:var(--s-4) var(--gutter)!important;
  background:var(--gb-ink);
  border-block:1px solid var(--gb-line)!important;
  display:flex;align-items:center;justify-content:space-between;
  gap:var(--s-4);flex-wrap:wrap;
}
.billboard-band .kicker{margin:0;color:var(--gb-bone)!important}

/* ══ 4 · THE CATALOGUE ════════════════════════════════════════════ */
.room-radio main > .rd-rows,
.room-radio .rd-rows{position:relative;z-index:var(--z-page);background:var(--gb-black)}

.room-radio .row{
  padding-top:var(--s-6)!important;
  padding-bottom:var(--s-4)!important;
  border-top:1px solid var(--gb-line-soft);
}
.room-radio .row > .kicker{color:var(--gb-ember)!important}
.room-radio .row h2{
  font-family:var(--f-display)!important;
  font-size:clamp(1.6rem,3.1vw,2.5rem)!important;
  font-weight:580!important;
  letter-spacing:-.028em!important;
  line-height:1.06!important;
  max-width:26ch;
  color:var(--gb-bone)!important;
}

/* the stations rail reads as a filmstrip, not as a row of boxes */
.room-radio .nf-tile{border-radius:var(--r-md)!important;overflow:hidden}
.room-radio .nf-tile b{
  font-family:var(--f-display)!important;font-weight:600!important;
  letter-spacing:-.02em!important;
}
.room-radio .nf-tile em{
  font-family:var(--f-text)!important;font-style:normal!important;
  color:var(--gb-dim)!important;
}

.rd-section-head{
  display:flex;align-items:baseline;justify-content:space-between;
  gap:var(--s-4);flex-wrap:wrap;
  padding:var(--s-8) var(--gutter) var(--s-4);
}
.rd-section-head h2{
  margin:0;font-family:var(--f-display);font-weight:580;
  font-size:clamp(1.5rem,2.8vw,2.2rem);letter-spacing:-.028em;color:var(--gb-bone);
}

/* ── THE STATIONS: full-bleed frames, not chips inside cards ───────
   V1 centred a glass pill with a border and a blurred backdrop on top
   of every thumbnail, and ringed each tile in its genre colour. That is
   three cheap moves stacked: a chip, in a card, in a glow. The frame is
   the card now; the name sits on the material, bottom-left, on a scrim. */
.room-radio .stations-pick .nf-tile,
.room-radio .stations-pick .nf-tile.session,
.room-radio .stations-pick .nf-tile.session[data-edition]{
  border:0!important;border-radius:var(--r-md)!important;
  background:var(--gb-ink)!important;
  box-shadow:none!important;
  overflow:hidden;
  transition:transform var(--d-md) var(--e-out),box-shadow var(--d-md) var(--e-out);
}
.room-radio .stations-pick .nf-tile.session video,
.room-radio .stations-pick .nf-tile.session img{
  filter:saturate(.92) contrast(1.06)!important;
  transition:transform var(--d-lg) var(--e-out);
}
.room-radio .stations-pick .nf-tile:hover{transform:translateY(-3px)}
.room-radio .stations-pick .nf-tile:hover video,
.room-radio .stations-pick .nf-tile:hover img{transform:scale(1.035)}
.room-radio .stations-pick .nf-tile::after{
  content:"";position:absolute;inset:auto 0 0 0;height:62%;z-index:1;pointer-events:none;
  background:linear-gradient(180deg,transparent,rgba(6,7,9,.86));
}
.room-radio .stations-pick .nf-tile.session b,
.room-radio .stations-pick .nf-tile.session[data-edition] b{
  position:absolute!important;left:0!important;right:0!important;
  top:auto!important;bottom:1.85rem!important;transform:none!important;
  max-width:none!important;text-align:left!important;
  padding:0 .85rem!important;margin:0!important;
  background:none!important;border:0!important;border-radius:0!important;
  backdrop-filter:none!important;-webkit-backdrop-filter:none!important;
  box-shadow:none!important;text-shadow:0 2px 18px rgba(0,0,0,.8)!important;
  font-family:var(--f-display)!important;font-weight:620!important;
  font-size:clamp(1.05rem,1.8vw,1.42rem)!important;line-height:1!important;
  letter-spacing:-.03em!important;color:var(--gb-bone)!important;
}
.room-radio .stations-pick .nf-tile.session em{
  position:absolute!important;left:0;right:0;bottom:0;z-index:2;
  padding:0 .85rem .8rem!important;
  font-family:var(--f-mono)!important;font-style:normal!important;
  font-size:.6rem!important;letter-spacing:.14em!important;text-transform:uppercase;
  color:var(--gb-dim)!important;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  background:none!important;border:0!important;
}
/* the one accent: an ember hairline on the tile you are pointing at */
.room-radio .stations-pick .nf-tile:hover::before,
.room-radio .stations-pick .nf-tile:focus-visible::before{
  content:"";position:absolute;inset:0;z-index:3;pointer-events:none;
  box-shadow:inset 0 0 0 1px var(--gb-ember);border-radius:var(--r-md);
}

/* one accent on the page: the genre marks stop shouting */
.room-radio [data-edition]{--edition:var(--gb-ember)}
.room-radio .rail-title .rail-name{color:var(--gb-bone)!important}
.room-radio .row > .genre{color:var(--gb-ember)!important}

/* rails: let the last card peek instead of dying at the gutter */
.room-radio .nf-track,
.room-radio .rail{padding-right:var(--gutter)}

/* ── ROUND 4: the catalogue stops fighting the covers ──────────────
   Three things were on top of every album cover at once: a gradient
   fade at each rail edge (which greyed out the first letter of every
   title), a pair of glass chevrons, and a play disc. The artwork is the
   product; the chrome comes off it. */

/* the edge fades are gone — they ate the first letter of every title */
.room-radio .rail-wrap.has-overflow::before,
.room-radio .rail-wrap.has-overflow::after,
.room-radio .rail-wrap.has-overflow:not(.at-end)::after,
.room-radio .rail-wrap.has-overflow:not(.at-start)::before{
  content:none!important;display:none!important;background:none!important;
}

/* the chevrons move off the artwork and sit above the rail, on the right */
.room-radio .rail-wrap{position:relative;padding-top:3.4rem}
.room-radio .rail-arrow{
  top:.2rem!important;bottom:auto!important;transform:none!important;
  width:2.75rem!important;height:2.75rem!important;
  border:1px solid var(--gb-line-strong)!important;
  background:transparent!important;backdrop-filter:none!important;
  box-shadow:none!important;
}
.room-radio .rail-arrow-prev{left:auto!important;right:3.35rem!important}
.room-radio .rail-arrow-next{right:.35rem!important}
.room-radio .rail-arrow:hover{
  transform:none!important;
  border-color:var(--gb-ember)!important;background:rgba(232,95,44,.10)!important;
}
.room-radio .rail-arrow span{border-color:var(--gb-bone)!important}

/* one accent: the per-genre corner washes and neon rules are retired */
.room-radio .row[data-edition]{background:none!important}
.room-radio .row[data-edition]::before{
  width:2.6rem!important;height:1px!important;
  background:var(--gb-ember)!important;box-shadow:none!important;
  margin-bottom:var(--s-4)!important;
}
.room-radio .row .genre{
  font-family:var(--f-display)!important;font-weight:620!important;
  font-size:clamp(1.15rem,2vw,1.5rem)!important;letter-spacing:.14em!important;
  text-transform:uppercase;color:var(--gb-ember)!important;text-shadow:none!important;
}
.room-radio .row .genre small{
  font-family:var(--f-mono)!important;color:var(--gb-mute)!important;letter-spacing:.2em!important;
}

/* covers: no frame, no glass, the art fills its own edge */
.room-radio .poster,
.room-radio .nf-feat{border:0!important;border-radius:var(--r-sm)!important;overflow:hidden}
.room-radio .poster img{border-radius:var(--r-sm)}
.room-radio .poster .go{opacity:0;transition:opacity var(--d-sm) var(--e-out)}
.room-radio .poster a:hover .go,
.room-radio .poster a:focus-visible .go{opacity:1}

/* captions: two lines are allowed, nothing is cut mid-word */
.room-radio .stations-pick .nf-tile.session em{
  white-space:normal!important;overflow:visible!important;text-overflow:clip!important;
  display:-webkit-box!important;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  overflow:hidden!important;line-height:1.35!important;
}
.room-radio .poster figcaption strong,
.room-radio .poster figcaption{overflow:visible;text-overflow:clip;white-space:normal}

/* the rails stop reserving empty height for cards that are not there */
.room-radio .scroller{min-height:0!important;padding-bottom:var(--s-3)!important}

/* ── ROUND 5: the fixed player is furniture, so the page allows for it ─ */
:root{--dock-h:4.5rem}
.room-radio .rd-stage{padding-bottom:calc(var(--s-6) + var(--dock-h))}
.room-radio main{padding-bottom:var(--dock-h)}

/* station tiles at phone width: the frame was 95 px tall, so the genre
   name sat on top of its own caption. Below 900 px the type lives under
   the image, where there is room for it. */
@media (max-width:900px){
  .room-radio .stations-pick .nf-tile.session{display:block;padding-bottom:.15rem}
  .room-radio .stations-pick .nf-tile.session video,
  .room-radio .stations-pick .nf-tile.session img{aspect-ratio:4/3!important}
  .room-radio .stations-pick .nf-tile::after{height:46%}
  .room-radio .stations-pick .nf-tile.session b,
  .room-radio .stations-pick .nf-tile.session[data-edition] b{
    position:static!important;padding:.6rem .7rem .1rem!important;
    font-size:1rem!important;text-shadow:none!important;
    left:auto!important;right:auto!important;bottom:auto!important;
  }
  .room-radio .stations-pick .nf-tile.session em{
    position:static!important;padding:0 .7rem .7rem!important;
    -webkit-line-clamp:2;font-size:.56rem!important;
  }
}


/* ── ROUND 6 ───────────────────────────────────────────────────────
   Album frames lose the last of their chrome, portrait art stops being
   letterboxed, and the station grid fits its own tiles. */
.room-radio .poster,
.room-radio .poster a,
.room-radio .poster figure,
.room-radio .nf-feat,
.room-radio .nf-feat.sq{border:0!important;box-shadow:none!important}

/* ── ROUND 7 — 2026-09-07: covers are Pat's art, never cropped ──────
   Every still on disk under assets/covers/ is a 16:9 frame — a few
   <img> tags still carry a stale height="640" from an old square era,
   and forcing aspect-ratio:1/1 + object-fit:cover on top of that was
   silently guillotining the top and bottom off real album art. The
   frame now matches the art's own shape on a dark plate: contain never
   crops, cover only would if a still ever lands a hair off 16/9 (a few
   do, at 640×341/357). Tiles are bigger and a fixed scrim sits over
   every cover so the catalogue reads darker, not just the chapters. */
.room-radio .poster:not(.mix):not([data-series]),
.room-radio .nf-feat{
  flex-basis:min(23rem,76vw)!important;width:min(23rem,76vw)!important;
}
.room-radio .poster img,
.room-radio .poster video,
.room-radio .nf-feat img,
.room-radio .nf-feat video{
  aspect-ratio:16/9!important;
  object-fit:contain!important;object-position:center!important;
  background:#05070a!important;
  filter:brightness(.95) saturate(.94);
}
.room-radio .poster a{position:relative}
.room-radio .poster a::after{
  content:"";position:absolute;inset:.4rem;z-index:1;pointer-events:none;
  background:linear-gradient(180deg,rgba(4,5,7,0) 66%,rgba(4,5,7,.5) 100%);
}
.room-radio .stations-pick .nf-track{
  grid-template-columns:repeat(auto-fit,minmax(13rem,1fr))!important;
  display:grid;gap:2px!important;
}
@media (max-width:900px){
  .room-radio .stations-pick .nf-track{
    grid-template-columns:repeat(2,minmax(0,1fr))!important;gap:2px!important;
  }
}
.room-radio footer{padding-top:var(--s-7)!important}

/* ── ROUND 8 — 2026-09-07: four cinematic chapters ───────────────────
   Every third genre (Bollywood, Country, Reggae, R&B) gets a full-bleed
   chapter — its own film edge to edge, a numbered kicker, the row's own
   headline moved up, one play action — sitting directly above its
   untouched shelf. The other nine genres stay plain shelves. Escapes
   the .page 4vw gutter with the standard breakout: width:100vw plus a
   negative margin computed from the *content* box the chapter sits in,
   which cancels out to exactly -1 × that gutter (see README §… this is
   only correct because .page is itself full-viewport with no ancestor
   padding of its own — verified at 390 and 1440, zero overflow). */
.rd-chapter{
  position:relative;
  width:100vw;
  margin-left:calc(50% - 50vw);
  min-height:68vh;
  display:flex;
  overflow:clip;
  isolation:isolate;
  background:var(--gb-black);
  scroll-margin-top:8.4rem;
}
.rd-chapter video{
  position:absolute;inset:0;z-index:-2;
  width:100%;height:100%;display:block;
  object-fit:cover;object-position:center;
  filter:contrast(1.03) saturate(.96) brightness(1.16);
}
.rd-chapter::after{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
}
.rd-chapter-in{
  position:relative;z-index:1;
  display:flex;flex-direction:column;gap:var(--s-4);
  width:100%;max-width:1440px;margin-inline:auto;
  padding:var(--s-7) 4vw var(--s-7);
}
.rd-chapter-in > *{max-width:34rem}
.rd-chapter-in .gb-eyebrow-num{margin:0}
.rd-chapter-in h2{
  margin:0;font-family:var(--f-display);font-weight:600;
  font-size:var(--t-xl);letter-spacing:var(--tr-head);line-height:1.02;
  color:var(--gb-bone);text-wrap:balance;
  text-shadow:0 2px 28px rgba(4,5,7,.75);
}
.rd-chapter-in .plays{margin:0}

/* composition 1 of 4 — copy low, left (Bollywood) */
.rd-chapter--left{align-items:flex-end}
.rd-chapter--left .rd-chapter-in{align-items:flex-start;text-align:left}
.rd-chapter--left::after{
  background:
    linear-gradient(180deg,rgba(5,6,8,.04) 0%,rgba(5,6,8,.16) 52%,rgba(5,6,8,.72) 100%),
    linear-gradient(90deg,rgba(5,6,8,.62) 0%,rgba(5,6,8,.1) 44%,transparent 70%);
}

/* composition 2 of 4 — copy low, right (Country) */
.rd-chapter--right{align-items:flex-end}
.rd-chapter--right .rd-chapter-in{align-items:flex-end;text-align:right}
.rd-chapter--right::after{
  background:
    linear-gradient(180deg,rgba(5,6,8,.04) 0%,rgba(5,6,8,.16) 52%,rgba(5,6,8,.72) 100%),
    linear-gradient(270deg,rgba(5,6,8,.62) 0%,rgba(5,6,8,.1) 44%,transparent 70%);
}

/* composition 3 of 4 — copy low, centred (Reggae) — the darkest source
   plate, so the veil stays lightest here and the video filter (above)
   carries most of the lift */
.rd-chapter--center{align-items:flex-end}
.rd-chapter--center .rd-chapter-in{align-items:center;text-align:center}
.rd-chapter--center::after{
  background:linear-gradient(180deg,rgba(5,6,8,.02) 0%,rgba(5,6,8,.14) 46%,rgba(5,6,8,.68) 100%);
}
.rd-chapter--center video{filter:contrast(1) saturate(1.02) brightness(1.32)}

/* composition 4 of 4 — copy vertically centred, left (R&B) */
.rd-chapter--mid{align-items:center}
.rd-chapter--mid .rd-chapter-in{align-items:flex-start;text-align:left}
.rd-chapter--mid::after{
  background:
    linear-gradient(90deg,rgba(5,6,8,.7) 0%,rgba(5,6,8,.16) 52%,transparent 78%),
    linear-gradient(180deg,rgba(5,6,8,.3) 0%,transparent 26%,transparent 74%,rgba(5,6,8,.4) 100%);
}

@media (max-width:768px){
  .rd-chapter{min-height:56vh}
  .rd-chapter-in{padding:var(--s-6) 5vw var(--s-6)}
  .rd-chapter-in h2{font-size:clamp(1.7rem,7.4vw,2.6rem)}
  .rd-chapter-in > *{max-width:none}
  /* phone stays one honest column: right/centre compositions read as
     ragged or clipped-feeling at 390px, so they fold to left-aligned */
  .rd-chapter--right .rd-chapter-in,
  .rd-chapter--center .rd-chapter-in{align-items:flex-start;text-align:left}
}

/* README §2, "no cheap cards": the Sounds section (still `hidden`)
   seeds a 1px box round a heading and two lines in radio.html's own
   inline <style>. Overridden here, in radio.css, with higher
   specificity rather than touching that block. */
.room-radio .sound-card,
.room-radio .nf-empty-shelf{
  border:0!important;
  background:var(--gb-ink)!important;
  border-radius:var(--r-md)!important;
}

/* ── ROUND 9 — 2026-09-07: the Pat-words pass ────────────────────────
   Kills the dead voids (a real fact strip under the promise line, a
   quiet serif pull-quote where the page used to go silent between the
   stations grid and the catalogue), retires the orange eyebrow-as-label
   on all twelve rows in favour of a monochrome act heading at three
   scales, splits the twelve identical shelves into rail / pair / grid
   rhythms, fixes a real caption-overlap bug on the stations grid at
   in-between widths, and ends the page on a different film than the
   hero opened on. */

/* the promise section gets a reason for its height: three facts already
   asserted in the copy above them, not invented catalogue numbers */
.rd-promise-in .rd-facts{margin-top:var(--s-6)}

/* the second void: a quiet serif line, no border, no card — the one
   editorial accent this page spends it on */
.rd-pull-section{
  position:relative;z-index:var(--z-page);
  background:var(--gb-black);
  border-top:1px solid var(--gb-line-soft);
  padding:var(--s-7) var(--gutter);
  display:flex;justify-content:center;
}
.rd-pull{
  margin:0;max-width:36ch;text-align:center;
  font-family:var(--f-serif);font-style:italic;font-weight:400;
  font-size:clamp(1.5rem,3.4vw,2.5rem);line-height:1.44;
  letter-spacing:-.01em;color:var(--gb-bone);
  border:0;background:none;
}

/* the eyebrow becomes the act heading: monochrome, large, tight-tracked
   like every other piece of display type on this system. The ember
   hairline above it (.row[data-edition]::before) stays as the one
   accent — a rule, not a label colour. */
.room-radio .row .genre{
  font-family:var(--f-display)!important;font-weight:640!important;
  letter-spacing:var(--tr-head)!important;text-transform:uppercase!important;
  color:var(--gb-bone)!important;text-shadow:none!important;
  font-size:clamp(1.7rem,3.6vw,2.5rem)!important;line-height:1.02!important;
}
.room-radio .row .genre small{color:var(--gb-mute)!important}

/* the descriptive h2, where one exists, drops to a supporting caption
   under the act heading instead of competing with it */
.room-radio .row h2{
  font-size:clamp(1rem,1.4vw,1.22rem)!important;
  font-weight:460!important;letter-spacing:-.008em!important;
  color:var(--gb-bone-soft)!important;max-width:44ch;
  margin-top:.4rem!important;
}

/* three headline scales down the page: the NEW wall is the loudest,
   ROCK and BEATS the next register down, everything else at the base
   size above, and the four shelves sitting under their own chapter
   (bollywood/country/reggae/rnb) quietest of all — the chapter already
   made the entrance. */
.room-radio .row.row--xl .genre{font-size:clamp(2.4rem,5.8vw,4.6rem)!important}
.room-radio .row.row--lg .genre{font-size:clamp(2rem,4.4vw,3.3rem)!important}
.room-radio .row.row--sm .genre{
  font-size:clamp(1.05rem,1.8vw,1.32rem)!important;
  color:var(--gb-bone-soft)!important;font-weight:560!important;
}

/* rail rows get the biggest covers on the page — NEW and the two
   longest catalogues (ROCK, BEATS) read as a real drag rail, not a
   strip of thumbnails */
.room-radio .row.row--xl .poster:not(.mix):not([data-series]),
.room-radio .row.row--lg .poster:not(.mix):not([data-series]),
.room-radio .row.row--xl .poster.mix,
.room-radio .row.row--lg .poster.mix{
  flex-basis:min(30rem,82vw)!important;width:min(30rem,82vw)!important;
}

/* pair rows: the genres that only ever had two albums stop pretending
   to be a scroll rail and sit as a two-up editorial spread instead.
   No scrollWidth beyond clientWidth here, so assets/motion.js's own
   overflow check hides the rail arrows on its own — nothing to wire. */
.room-radio .row.row--pair .scroller{
  display:grid!important;grid-template-columns:repeat(2,minmax(0,1fr))!important;
  gap:var(--s-5)!important;overflow:visible!important;
}
/* RETIRED 2026-09-17 (compress pass): the two-up grid, its one-column
   phone form and the per-card width that went with it. Every album
   scroller on this page is a rail now — see COMPRESS PASS at the foot of
   this file for why, and for the measurements. */

/* grid rows: a dense wrap instead of a rail — same covers, a different
   rhythm, still every one of them on the page */
.room-radio .row.row--grid .scroller{
  display:grid!important;
  grid-template-columns:repeat(auto-fit,minmax(11rem,1fr))!important;
  gap:var(--s-4)!important;overflow:visible!important;
}
/* RETIRED 2026-09-17 (compress pass): the dense-wrap card width. Same
   reason as the two-up grid above — this row is a rail now. */

/* ── the closing chapter: a different film than the hero, the wordmark,
   one action back into the catalogue ─────────────────────────────── */
.rd-chapter--close{
  align-items:center;justify-content:center;min-height:70vh;
}
.rd-chapter--close .rd-chapter-in{
  align-items:center;text-align:center;max-width:none;
  padding:var(--s-7) 5vw;
}
.rd-chapter--close .rd-chapter-in > *{max-width:none}
.rd-chapter--close::after{
  background:radial-gradient(120% 90% at 50% 42%,rgba(5,6,8,.22) 0%,rgba(5,6,8,.76) 100%);
}
.rd-close-word{
  margin:0;font-family:var(--f-display);font-weight:640;
  font-size:clamp(2.6rem,7.2vw,6.4rem);line-height:.94;
  letter-spacing:var(--tr-mega);color:var(--gb-bone);
  text-wrap:balance;text-shadow:0 2px 32px rgba(4,5,7,.7);
}
.rd-chapter--close .plays{justify-content:center}

/* the stations grid: a real bug, not a taste call — at 900–1300px the
   caption line wrapped to two lines and climbed over the genre name.
   One line, always, with room reserved so it never touches "b". */
.room-radio .stations-pick .nf-tile.session em{
  -webkit-line-clamp:1!important;white-space:nowrap!important;
}
.room-radio .stations-pick .nf-tile.session b,
.room-radio .stations-pick .nf-tile.session[data-edition] b{
  bottom:2.15rem!important;
}
@media (min-width:901px){
  .room-radio .stations-pick .nf-track{
    grid-template-columns:repeat(auto-fit,minmax(15rem,1fr))!important;
  }
}

/* FINISH PASS · 2026-09-07 — station captions were hard-clipped mid-word:
   an earlier round forced text-overflow:clip on the one-line caption, so
   "Country roots, carried by a rap de" just stopped. The line still holds
   to one line; it now ends on an ellipsis like a truncated line should. */
.room-radio .stations-pick .nf-tile.session em{
  text-overflow:ellipsis!important;
}

/* CLAUDINE BOX — on-air band, 2026-09-09: a proper box with her poster
   instead of a bare ghost link, so the DJ is one obvious click away
   from the moment the station loads. */
.rd-claudine-box{
  display:flex;align-items:center;gap:.65rem;
  padding:.4rem .95rem .4rem .4rem;border-radius:var(--r-pill);
  border:1px solid var(--gb-line);background:rgba(239,235,227,.03);
  min-height:44px;
  transition:border-color var(--d-sm) var(--e-out),background var(--d-sm) var(--e-out),transform var(--d-sm) var(--e-out);
}
.rd-claudine-box img{
  width:46px;height:46px;border-radius:50%;object-fit:cover;object-position:50% 18%;flex:0 0 auto;
}
.rd-claudine-box span{display:flex;flex-direction:column;line-height:1.18;gap:.1rem}
.rd-claudine-box b{font-family:var(--f-display)!important;font-size:.9rem!important;font-weight:600!important;color:var(--gb-bone)!important}
.rd-claudine-box em{font-style:normal;font-family:var(--f-mono);font-size:.6rem;letter-spacing:.08em;text-transform:uppercase;color:var(--gb-mute)}
.rd-claudine-box:hover,.rd-claudine-box:focus-visible{border-color:var(--gb-ember);background:rgba(239,235,227,.07);transform:translateY(-2px)}

/* ═══════════════════════════════════════════════════════════════════
   SHORTS · 2026-09-17 — the vertical clips move in with the albums
   Every genre that has Shorts on the channel leads its album rail with
   them: a phone-shaped 9:16 card, a silent loop cut from the house
   master, and a tap that opens the real Short in a player centred on the
   page.
   Later the same evening (Pat, live): they stopped getting a strip of
   their own and moved INSIDE the genre's album scroller — a portrait
   card among the covers, the way a channel page mixes them. The
   `.shorts-strip` wrapper no longer exists; card sizing now lives in the
   COMPRESS PASS at the foot of this file, tied to the album card width.
   What stays here is the card itself: frame, poster, preview, scrim,
   glyph, stamp, caption — none of which cared which rail it sat in.
   ─────────────────────────────────────────────────────────────────── */
.short-card .short-open{
  display:block;text-decoration:none;color:inherit;
  border-radius:var(--r-md);outline-offset:3px;
}
.short-frame{
  display:block;position:relative;aspect-ratio:9/16;width:100%;
  border-radius:var(--r-md);overflow:hidden;background:#101218;
  border:1px solid var(--gb-line);
  transition:border-color var(--d-sm) var(--e-out),transform var(--d-sm) var(--e-out);
}
.short-frame > img,
.short-frame > video{
  position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;object-position:center;display:block;margin:0;
  border-radius:inherit;
}
.short-frame > video{opacity:0;transition:opacity .28s var(--e-out)}
.short-card[data-short-state="playing"] .short-frame > video{opacity:1}
.short-scrim{
  position:absolute;inset:auto 0 0 0;height:42%;pointer-events:none;
  background:linear-gradient(180deg,transparent,rgba(5,6,9,.72));
}
.short-glyph{
  position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  width:2.6rem;height:2.6rem;border-radius:50%;
  display:grid;place-items:center;color:var(--gb-bone);
  background:rgba(8,10,16,.52);border:1px solid rgba(239,235,227,.34);
  backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);
  transition:background var(--d-sm) var(--e-out),transform var(--d-sm) var(--e-out);
}
.short-glyph svg{width:1.15rem;height:1.15rem}
.short-stamp{
  position:absolute;right:.45rem;bottom:.45rem;
  font-family:var(--f-mono);font-size:.6rem;letter-spacing:.08em;
  color:var(--gb-bone);background:rgba(6,8,12,.66);
  padding:.14rem .38rem;border-radius:var(--r-sm);
}
.short-open:hover .short-frame,
.short-open:focus-visible .short-frame{border-color:var(--gb-ember);transform:translateY(-3px)}
.short-open:hover .short-glyph{background:rgba(232,95,44,.82);transform:translate(-50%,-50%) scale(1.06)}
.short-card figcaption{
  display:block;padding:.55rem .1rem 0;
}
.short-card figcaption strong{
  display:block;font-family:var(--f-display);font-weight:580;
  font-size:.84rem;line-height:1.2;color:var(--gb-bone);
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
}
.short-card figcaption em{
  display:block;font-style:normal;font-family:var(--f-mono);
  font-size:.58rem;letter-spacing:.14em;text-transform:uppercase;
  color:var(--gb-mute);margin-top:.22rem;
}
@media (prefers-reduced-motion:reduce){
  .short-frame > video{display:none}
  .short-open:hover .short-frame{transform:none}
}

/* THE PLAYER — a 9:16 stage, sound on, because the tap asked for it */
.short-lb{
  position:fixed;inset:0;width:100%;height:100%;max-width:none;max-height:none;
  margin:0;padding:0;border:0;background:transparent;overflow:hidden;
  opacity:0;transition:opacity .2s var(--e-out);
  z-index:calc(var(--z-chrome) + 40);
}
.short-lb[data-open="true"]{opacity:1}
.short-lb::backdrop{background:rgba(3,4,7,.88)}
.short-lb-veil{position:absolute;inset:0;background:rgba(3,4,7,.9)}
.short-lb-stage{
  position:relative;height:100%;width:100%;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:.75rem;padding:max(1rem,env(safe-area-inset-top)) 1rem 1.2rem;
}
.short-lb-frame{
  position:relative;aspect-ratio:9/16;
  height:min(84vh,calc((100vw - 2rem) * 16 / 9));
  width:auto;max-width:calc(100vw - 2rem);
  border-radius:var(--r-md);overflow:hidden;background:#000;
  box-shadow:0 30px 80px rgba(0,0,0,.6);
}
.short-lb-frame iframe{position:absolute;inset:0;width:100%;height:100%;border:0;display:block}
.short-lb-title{
  margin:0;max-width:min(38rem,90vw);text-align:center;
  font-family:var(--f-mono);font-size:.68rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--gb-bone-soft);
}
.short-lb-close{
  position:absolute;top:max(.7rem,env(safe-area-inset-top));right:.7rem;z-index:3;
  width:44px;height:44px;min-width:44px;min-height:44px;padding:0;
  display:grid;place-items:center;cursor:pointer;
  border:1px solid rgba(239,235,227,.3);border-radius:50%;
  background:rgba(8,10,16,.72);color:var(--gb-bone);
  backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);
}
.short-lb-close svg{width:1.1rem;height:1.1rem}
.short-lb-close:hover,.short-lb-close:focus-visible{border-color:var(--gb-bone);background:rgba(8,10,16,.95)}
html.short-lb-open{overflow:hidden!important}
html.short-lb-open body{padding-right:var(--gb-sbw,0px)}

/* ═══════════════════════════════════════════════════════════════════
   RAIL AFFORDANCES AT PHONE WIDTH · 2026-09-17
   Measured at 390x844 before this block: on the NEW, ROCK, BOLLYWOOD,
   COUNTRY, LOFI, BEATS, REGGAE and R&B rails the first card ended
   EXACTLY on the rail's right edge — peek 0 px. A rail that shows one
   card and no sliver of the next does not look like a rail; it looks
   like a single large cover with a stray chevron above it. Two fixes,
   both only on the phone:
     1. the card gives back ~8vw so the next one always peeks;
     2. the rail can be dragged with a thumb again.
   (2) restores the obvious gesture: the arrows above the rail were the
   only way to move it, because an earlier round set overflow-x:hidden
   on every radio rail. Vertical panning is kept, so the page still
   scrolls normally when the finger starts on a cover.
   ─────────────────────────────────────────────────────────────────── */
@media (max-width:900px){
  .room-radio .radio-deck .scroller{
    overflow-x:auto!important;overflow-y:hidden!important;
    touch-action:pan-x pan-y!important;
    -webkit-overflow-scrolling:touch;
    scrollbar-width:none;
  }
  .room-radio .radio-deck .scroller::-webkit-scrollbar{display:none;width:0;height:0}
}
/* THE ACTUAL CAUSE of peek 0: nothing on this site ever reset the user
   agent's own `figure { margin-inline: 40px }`, so every album card
   carried 80 px of dead space no stylesheet had asked for. Card 289 px
   + 80 px of UA margin + an 18 px gap is 387 px — one pixel under a
   390 px phone, which is why each rail showed exactly one cover and
   nothing after it.
   2026-09-17, compress pass: the reset comes out of the phone media
   query. Measured at 1440 it was still costing 80 px per card there —
   the ROCK rail's scrollWidth was 400 px wider than the sum of its six
   cards and their gaps — so the desktop was paying for it too. */
.room-radio .radio-deck .scroller > figure{margin:0!important}
/* RETIRED 2026-09-17 (compress pass): the 74vw phone card, the
   overflow-x:visible escape for the two-up/grid rows, and their
   width:100% cards. All three assumed a layout where an album scroller
   might not be a rail and a Short lived outside it. Both assumptions are
   gone: one card width, one rail, Shorts inside. */

/* ═══════════════════════════════════════════════════════════════════
   SINGLES RAILS ARE RAILS IN EVERY GENRE · 2026-09-17
   row--pair and row--grid turn "the scroller" into a CSS grid so two or
   five ALBUM covers sit as an editorial spread instead of pretending to
   be a drag rail. The selector said `.scroller` — every scroller in the
   section — so it also caught the Spotify SINGLES rail underneath, which
   is not two covers but forty-seven. On a 390px phone that grid is one
   column, and the result was measured on the live page:

     country-rap  47 singles as a grid  = 11,114 px
     caliente     42 singles as a grid  = 10,322 px
     gypsy        20 singles as a grid  =  5,126 px

   26,562 px of a 51,708 px page — 60% of the radio page — for three
   genres, while REGGAE renders its 46 singles as a 212 px rail and BEATS
   its 38 in 250 px. That is the "endless empty scroll" in the eyes-on
   pass, and it is also what pushed the capture past Chrome's full-page
   limit and produced the ~1,500 px white tail.

   The grid belongs to the album rail only. Singles rails ([data-sp-rail])
   and Shorts strips stay horizontal rails, like every other genre.
   ─────────────────────────────────────────────────────────────────── */
.room-radio .row.row--pair .scroller[data-sp-rail],
.room-radio .row.row--grid .scroller[data-sp-rail]{
  display:flex!important;
  grid-template-columns:none!important;
  gap:1.15rem!important;
  overflow-x:auto!important;overflow-y:hidden!important;
}
.room-radio .row.row--pair .scroller[data-sp-rail] > .poster,
.room-radio .row.row--grid .scroller[data-sp-rail] > .poster{
  flex:0 0 auto!important;
}
@media (max-width:900px){
  .room-radio .row.row--pair .scroller[data-sp-rail] > .poster,
  .room-radio .row.row--grid .scroller[data-sp-rail] > .poster{
    flex-basis:74vw!important;width:74vw!important;
  }
}
@media (min-width:901px){
  .room-radio .row.row--pair .scroller[data-sp-rail] > .poster,
  .room-radio .row.row--grid .scroller[data-sp-rail] > .poster{
    flex-basis:11rem!important;width:11rem!important;
  }
}

/* ═══════════════════════════════════════════════════════════════════
   COMPRESS PASS · 2026-09-17 — Pat, live: "it's too long when I'm going
   down… Make the cards smaller so we see much more, everything a bit
   smaller, we see more of the scroller left and right."

   Measured before this pass, /radio at 390px: the first card in a genre
   rail was 172px wide inside a 359px scroller, so ONE album filled the
   phone with no peek at all, and nine of twelve rails had a scrollWidth
   equal to their clientWidth — a rail that cannot be scrolled and shows
   nothing beyond its first card is not a rail. Three genres (Italian,
   Caliente, Gypsy) and Country Rap were not rails at all: they were CSS
   grids, one album per line on a phone, 1245-1858px of page each.

   One card size for the whole catalogue, every album row a real rail,
   and the Shorts riding in the same rail as the covers.
   ─────────────────────────────────────────────────────────────────── */
.room-radio .rd-rows{
  /* the one card width on this page. 40vw on a phone puts two covers plus
     a clear third-card peek inside the rail; 15rem on a desktop puts five
     across with the sixth showing. */
  --rd-card:min(15rem,40vw);
  --rd-gap:.95rem;
}

/* the rail itself: the row already pays the page gutter, so the scroller
   stops paying it a second time. That 5.5vw of doubled inset was 43px of
   a 390px phone spent on nothing. */
.room-radio .rd-rows .scroller{
  gap:var(--rd-gap)!important;
  padding-left:0!important;padding-right:0!important;
  padding-top:.15rem!important;padding-bottom:var(--s-3)!important;
  align-items:flex-start!important;
}

/* every album card, every row kind, one width */
.room-radio .rd-rows .poster,
.room-radio .rd-rows .poster.mix,
.room-radio .row.row--xl .poster.mix,
.room-radio .row.row--lg .poster.mix,
.room-radio .row.row--xl .poster:not(.mix):not([data-series]),
.room-radio .row.row--lg .poster:not(.mix):not([data-series]){
  flex:0 0 var(--rd-card)!important;width:var(--rd-card)!important;
}

/* the two-up spread and the dense grid become rails like everything else.
   They were the page's two longest sections on a phone, and a grid cannot
   hold a 9:16 Short next to a 16:9 cover without one of them lying about
   its shape. */
.room-radio .row.row--pair .scroller,
.room-radio .row.row--grid .scroller{
  display:flex!important;grid-template-columns:none!important;
  gap:var(--rd-gap)!important;overflow-x:hidden!important;overflow-y:hidden!important;
}
.room-radio .row.row--pair .scroller > .poster,
.room-radio .row.row--grid .scroller > .poster{
  flex:0 0 var(--rd-card)!important;width:var(--rd-card)!important;
}

/* captions ride the smaller card: still two lines, still nothing clipped
   mid-word, just sized for a 15rem cover instead of a 32rem one */
.room-radio .rd-rows .poster figcaption{margin-top:.4rem!important}
.room-radio .rd-rows .poster figcaption strong{
  font-family:var(--f-display)!important;font-weight:580!important;
  font-size:.82rem!important;line-height:1.2!important;letter-spacing:-.01em!important;
  display:-webkit-box!important;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden!important;
}
.room-radio .rd-rows .poster figcaption em{
  font-size:.66rem!important;line-height:1.3!important;margin-top:.14rem!important;
  display:-webkit-box!important;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden!important;
}
.room-radio .rd-rows .poster figcaption .series,
.room-radio .rd-rows .poster figcaption .meta{display:none!important}

/* ── the Short, in the album rail ─────────────────────────────────
   A portrait card among landscape covers: narrower than a cover so the
   two read as one strip rather than one card towering over the rest,
   and top-aligned with them. This is the variation Pat asked for — the
   thing that is playing while the covers sit still. */
.room-radio .rd-rows .scroller > .short-card{
  flex:0 0 calc(var(--rd-card) * .66)!important;
  width:calc(var(--rd-card) * .66)!important;
  scroll-snap-align:start;margin:0;position:relative;
}
.room-radio .rd-rows .scroller > .short-card figcaption{padding:.4rem .1rem 0}
.room-radio .rd-rows .scroller > .short-card figcaption strong{font-size:.76rem}
.room-radio .rd-rows .scroller > .short-card figcaption em{font-size:.55rem}
.room-radio .rd-rows .scroller > .short-card .short-glyph{
  width:2rem;height:2rem;
}
.room-radio .rd-rows .scroller > .short-card .short-glyph svg{width:.9rem;height:.9rem}

/* ── vertical: the page stops spending a screen on every seam ─────── */
.room-radio .row{
  padding-top:var(--s-4)!important;
  padding-bottom:var(--s-2)!important;
}
.room-radio .rd-rows .rail-head{
  padding-top:0!important;padding-bottom:.3rem!important;margin-bottom:0!important;
}
.room-radio .row[data-edition]::before{margin-bottom:var(--s-2)!important}
.room-radio .row .genre{margin-bottom:.2rem!important}
.room-radio .row.row--xl .genre{font-size:clamp(1.6rem,3.6vw,2.4rem)!important}
.room-radio .row.row--lg .genre{font-size:clamp(1.45rem,3vw,2rem)!important}

/* the chapter interludes keep their film and their one play action — they
   are the genre's entrance, not copy — but they stop being 68vh of it. */
.rd-chapter{min-height:26vh!important}
.rd-chapter-in{padding:var(--s-5) 4vw!important;gap:var(--s-3)!important}
.rd-chapter-in h2{font-size:clamp(1.3rem,2.6vw,1.9rem)!important;line-height:1.06!important}
.rd-chapter--close{min-height:34vh!important}
.rd-chapter--close .rd-chapter-in{padding:var(--s-6) 5vw!important}
.rd-close-word{font-size:clamp(2rem,5vw,4rem)!important}

/* the rail arrows and the edge fades follow the smaller cards in */
.room-radio .rail-wrap.has-overflow:not(.at-end)::after,
.room-radio .rail-wrap.has-overflow:not(.at-start)::before{width:2.2rem}

