/* BroadcastZero listener styles — premium, warm, restrained. */
* { margin: 0; padding: 0; box-sizing: border-box; }
:root {
  --env-bg: #101113;
  --env-accent: #e8a84c;
  --ink: #e9e6df;
  --ink-dim: #9a968c;
  --panel: #16171b;
  --line: #2a2c32;
}
html, body { height: 100%; }
body {
  background:
    radial-gradient(120% 90% at 50% -10%, color-mix(in srgb, var(--env-accent) 7%, transparent), transparent 60%),
    var(--env-bg);
  color: var(--ink);
  font-family: "Helvetica Neue", Helvetica, Arial, system-ui, sans-serif;
  min-height: 100dvh;
  display: flex; flex-direction: column;
  transition: background 0.8s ease;
  overflow-x: hidden;
}
body.rx-light { color: #26282b; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }

/* ---------- 18+ ---------- */
#age-note {
  position: fixed; inset: 0; z-index: 90;
  display: grid; place-items: center;
  background: rgba(6,6,8,0.82);
  backdrop-filter: blur(6px);
  transition: opacity 0.9s ease;
  pointer-events: none;
}
.age-inner {
  text-align: center; max-width: 520px; padding: 40px;
  border: 1px solid #3a3325; border-radius: 14px;
  background: #141210;
  box-shadow: 0 30px 80px rgba(0,0,0,0.5);
}
.age-mark {
  display: inline-grid; place-items: center;
  width: 74px; height: 74px; border-radius: 50%;
  border: 3px solid #e8542e; color: #e8542e;
  font-size: 26px; font-weight: 800; margin-bottom: 18px;
}
.age-inner p { color: #cfc9bc; line-height: 1.55; font-size: 15px; }
#age-note.minify { opacity: 0; }
#age-badge {
  position: fixed; right: 14px; bottom: 46px; z-index: 60;
  font-size: 11px; font-weight: 700; letter-spacing: 0.4px;
  color: #b0552f; border: 1.5px solid #7a3c22; border-radius: 999px;
  padding: 3px 9px; opacity: 0; transition: opacity 0.8s;
  pointer-events: none;
}
#age-badge { opacity: 0.75; }

/* ---------- boot ---------- */
#boot {
  position: fixed; inset: 0; z-index: 80;
  display: grid; place-items: center; gap: 0;
  background: #0a0b0d;
  overflow: hidden;
  transition: opacity 0.65s ease;
}
/* the whole station playing at once behind the logo, knocked well back so the mark stays the brightest thing */
#boot-wall {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  opacity: 0; transition: opacity 1.4s ease; z-index: 0;
}
#boot-wall.show { opacity: 0.34; }
#boot::after {                                   /* pool of dark under the logo, so nothing competes with it */
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: radial-gradient(58% 52% at 50% 44%, rgba(8, 9, 11, 0.62), rgba(8, 9, 11, 0.9) 72%);
}
.boot-logo, #boot-btn { position: relative; z-index: 2; }
#boot.gone { opacity: 0; pointer-events: none; }
.boot-logo { text-align: center; }
.boot-mark { width: clamp(150px, 22vh, 230px); height: auto; opacity: 0.96; border-radius: 50%; }
.boot-word {
  /* sized off the viewport so all thirteen letters stay on one line, phone or desktop */
  font-size: clamp(24px, 7.9vw, 116px); letter-spacing: 0.05em; font-weight: 300;
  margin-top: clamp(14px, 2.4vh, 30px); color: #ddd8cc; white-space: nowrap;
  animation: boot-word-in 1.15s cubic-bezier(0.22, 0.75, 0.25, 1) 0.15s both;
}
@keyframes boot-word-in {
  from { opacity: 0; transform: translateY(14px); letter-spacing: 0.16em; }
  to   { opacity: 1; transform: none; letter-spacing: 0.05em; }
}
.boot-word b { font-weight: 800; color: var(--env-accent); }
.boot-sub {
  margin-top: clamp(8px, 1.4vh, 14px); font-size: clamp(9px, 1.15vw, 13px);
  letter-spacing: 0.42em; color: #5c5950;
}
#fs-btn .fs-out { display: none; }
body.is-fullscreen #fs-btn .fs-in { display: none; }
body.is-fullscreen #fs-btn .fs-out { display: block; }
body.is-fullscreen #fs-btn { color: var(--env-accent); }
#boot-btn {
  margin-top: clamp(26px, 4.5vh, 44px);
  padding: clamp(18px, 2.6vh, 26px) clamp(64px, 9vw, 120px);
  border-radius: 999px;
  border: 2px solid #6a6250; color: #efe8d6; letter-spacing: 5px;
  font-size: clamp(17px, 1.6vw, 23px); font-weight: 700;
  transition: all 0.25s;
  justify-self: center;
  box-shadow: 0 0 0 rgba(0,0,0,0);
}
#boot-btn { position: relative; overflow: hidden; display: inline-flex; align-items: center;
  gap: clamp(10px, 1.4vw, 16px); background: rgba(16, 15, 13, 0.5);
  animation: pwr-breathe 3.4s ease-in-out 1.2s infinite; }
.pwr-lamp {                                      /* the standby lamp on the front of a receiver */
  width: clamp(9px, 1.1vw, 12px); height: clamp(9px, 1.1vw, 12px); border-radius: 50%; flex: none;
  background: var(--env-accent); animation: pwr-lamp 3.4s ease-in-out 1.2s infinite;
}
#boot-btn::after {                               /* a slow glint travelling across the face */
  content: ""; position: absolute; top: 0; bottom: 0; width: 45%;
  background: linear-gradient(100deg, transparent, rgba(255, 245, 225, 0.13), transparent);
  transform: translateX(-180%); animation: pwr-glint 5.2s ease-in-out 2s infinite;
}
@keyframes pwr-breathe {
  0%, 100% { box-shadow: 0 0 0 rgba(0,0,0,0), 0 0 22px -8px color-mix(in srgb, var(--env-accent) 40%, transparent); border-color: #6a6250; }
  50% { box-shadow: 0 0 0 rgba(0,0,0,0), 0 0 40px -4px color-mix(in srgb, var(--env-accent) 55%, transparent);
        border-color: color-mix(in srgb, var(--env-accent) 60%, #6a6250); }
}
@keyframes pwr-lamp {
  0%, 100% { opacity: 0.45; box-shadow: 0 0 6px color-mix(in srgb, var(--env-accent) 50%, transparent); }
  50% { opacity: 1; box-shadow: 0 0 16px color-mix(in srgb, var(--env-accent) 85%, transparent); }
}
@keyframes pwr-glint { 0%, 62% { transform: translateX(-180%); } 88%, 100% { transform: translateX(320%); } }
#boot-btn:hover, #boot-btn:focus-visible {
  border-color: var(--env-accent); color: #14130f; transform: scale(1.04);
  background: var(--env-accent);
  box-shadow: 0 0 54px color-mix(in srgb, var(--env-accent) 45%, transparent);
  animation-play-state: paused;
}
#boot-btn:hover .pwr-lamp, #boot-btn:focus-visible .pwr-lamp {
  background: #14130f; opacity: 1; box-shadow: none; animation: none;
}
#boot-btn:active { transform: scale(0.99); }
#boot.booting .boot-logo { animation: bz-hum 1.1s ease forwards; }
#boot.booting #boot-btn { opacity: 0; }
@keyframes bz-hum {
  0% { transform: scale(1); filter: brightness(1); }
  35% { transform: scale(1.03); filter: brightness(1.6); }
  100% { transform: scale(0.98); filter: brightness(0.4); opacity: 0.2; }
}

/* ---------- station ambient background ---------- */
#stage-bg { position: fixed; inset: 0; z-index: -2; pointer-events: none; }
#stage-bg video {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; opacity: 0; transition: opacity 2.4s cubic-bezier(0.4, 0, 0.2, 1);
}
#stage-bg video.show { opacity: 0.8; }
body.light-env #stage-bg video.show { opacity: 0.55; }
#bg-tint {
  position: absolute; inset: 0;
  background:
    linear-gradient(180deg, rgba(8,9,11,0.72), rgba(8,9,11,0.45) 40%, rgba(8,9,11,0.78));
}
body.light-env #bg-tint {
  background: linear-gradient(180deg, rgba(238,238,240,0.7), rgba(238,238,240,0.45) 40%, rgba(238,238,240,0.78));
}

/* ---------- top bar ---------- */
#topbar {
  display: flex; align-items: center; gap: 18px; flex-wrap: wrap;
  padding: 14px clamp(14px, 3vw, 30px);
}
.brand { display: flex; align-items: center; gap: 12px; }
/* the logo IS a record: it sits still so the name stays readable, and turns one revolution on cue */
.brand-disc {
  width: 52px; height: 52px; flex: none; border-radius: 50%; display: block;
  filter: drop-shadow(0 5px 9px rgba(0, 0, 0, 0.65));
}
.brand-disc.turn { animation: disc-spin 1.8s linear; }          /* 33 1/3 rpm, one turn */
.brand:hover .brand-disc { animation: disc-spin 1.8s linear; }
@keyframes disc-spin { to { transform: rotate(360deg); } }
.brand-word { letter-spacing: 3px; font-size: 13px; font-weight: 300; opacity: 0.9; }
.brand-word b { font-weight: 800; color: var(--env-accent); }
.mode-tabs {
  display: flex; border: 1px solid var(--line); border-radius: 999px;
  overflow: hidden; margin-left: 8px;
  flex: none;                      /* the tuner switch is the main control: it never gets squeezed out */
}
.mode-tab {
  padding: 11px 28px; font-size: 15px; letter-spacing: 1.2px; color: var(--ink-dim);
  transition: all 0.2s; font-weight: 600;
}
.mode-tab.on { background: var(--env-accent); color: #131313; font-weight: 700; }
.top-actions { margin-left: auto; display: flex; align-items: center; gap: 6px; }
#freq-chip { font-size: 14px; color: var(--ink-dim); letter-spacing: 0.5px; margin-right: 8px; white-space: nowrap; }
.icon-btn {
  width: 50px; height: 50px; border-radius: 12px; display: grid; place-items: center;
  color: var(--ink-dim); transition: all 0.2s;
}
.icon-btn:hover { color: var(--env-accent); background: rgba(255,255,255,0.04); }
.icon-btn svg { width: 27px; height: 27px; }

/* ---------- stage ---------- */
#stage {
  flex: 1; display: flex; flex-direction: column; align-items: center;
  padding: 8px clamp(10px, 3vw, 30px) 20px; gap: 20px;
}
#receiver-wrap {
  width: min(960px, 100%);
  position: relative;
}
#receiver-wrap::after {           /* grounded shadow without a filter on the
                                     animating subtree (repaint-storm killer) */
  content: ''; position: absolute; left: 10%; right: 10%; bottom: -3%;
  height: 9%; border-radius: 50%;
  background: radial-gradient(50% 50% at 50% 50%, rgba(0,0,0,0.8), rgba(0,0,0,0.35) 55%, transparent 72%);
  z-index: -1; pointer-events: none;
}
#receiver-wrap::before {          /* soft vignette seats the radio over busy video */
  content: ''; position: absolute; left: -6%; right: -6%; top: -8%; bottom: -10%;
  border-radius: 24px;
  background: radial-gradient(60% 62% at 50% 48%, rgba(0,0,0,0.34), transparent 74%);
  z-index: -1; pointer-events: none;
}
.receiver { position: relative; user-select: none; margin: 0 auto;
  width: var(--rx-w, 100%); max-width: 100%; }
.rx-art { width: 100%; display: block; pointer-events: none; }
.rx-layer { position: absolute; inset: 0; }
.receiver.powered-off .rx-art { filter: brightness(0.62) saturate(0.75); transition: filter 0.6s; }
.rx-art { transition: filter 0.6s; }

/* knobs */
.rx-knob {
  position: absolute; aspect-ratio: 1; border-radius: 50%;
  z-index: 5; pointer-events: none;
}
.rx-knobhit {
  position: absolute; border-radius: 50%; cursor: grab; z-index: 6;
  transition: box-shadow 0.2s;
}
.rx-knobhit:hover { box-shadow: 0 0 0 2px color-mix(in srgb, var(--env-accent) 55%, transparent), 0 0 18px color-mix(in srgb, var(--env-accent) 25%, transparent); }
.rx-knobhit:active { cursor: grabbing; }

/* buttons */
.rx-btn {
  position: absolute; z-index: 4; border-radius: 6px;
  transition: background 0.15s, box-shadow 0.2s;
}
.rx-btn.round { border-radius: 50%; }
.rx-btn:hover { box-shadow: inset 0 0 0 1.5px color-mix(in srgb, var(--env-accent) 60%, transparent); }
.rx-btn.pressed { background: rgba(0,0,0,0.28); transform: translateY(1px); }

/* leds */
.rx-led {
  position: absolute; border-radius: 50%; background: #222; z-index: 4;
  transition: all 0.3s; transform: translateZ(0);
}
.rx-led.on { background: var(--c); box-shadow: 0 0 8px var(--c), 0 0 2px var(--c); }

/* analog needle */
.rx-needle {
  position: absolute; width: 2.5px; z-index: 3;
  transition: left 0.14s linear;
}
.rx-rneedle {
  position: absolute; height: 2.5px; z-index: 3;
  transform-origin: 0 50%; border-radius: 2px;
}
.rx-rneedle.meter { transition: none; }

/* led row meter */
.rx-ledrow { position: absolute; display: flex; gap: 3px; z-index: 3; }
.rx-ledrow i { flex: 1; border-radius: 2px; background: rgba(255,255,255,0.05); }
.rx-ledrow i.on { background: var(--c); box-shadow: 0 0 5px var(--c); }

/* ---------- screens ---------- */
.rx-screen {
  position: absolute; z-index: 2; overflow: hidden;
  contain: layout paint style;
  color: var(--ink); font-variant-numeric: tabular-nums;
  display: flex; flex-direction: column; justify-content: center;
  padding: 2.2% 3%;
  container-type: inline-size;
}
.rx-screen.off * { display: none !important; }
.rx-screen.glow { text-shadow: 0 0 12px color-mix(in srgb, var(--accent) 60%, transparent); }
.scr-top { display: flex; align-items: center; justify-content: space-between; font-size: 3.2cqw; letter-spacing: 0.15em; opacity: 0.9; }
.scr-badge { font-weight: 700; }
.scr-mini { font-size: 2.8cqw; opacity: 0.85; letter-spacing: 0.1em; }
.scr-freq-big { font-size: 13cqw; font-weight: 200; text-align: center; line-height: 1.05; }
.scr-freq-big.slim { font-size: 11cqw; text-align: left; }
.scr-freq-big small { font-size: 4cqw; margin-left: 1.5cqw; opacity: 0.7; }
.scr-stn { text-align: center; font-size: 4.2cqw; letter-spacing: 0.06em; font-weight: 600; }
.scr-seg { display: flex; justify-content: center; margin: 1cqw 0; }
.scr-seg svg { height: 16cqw; max-height: 100%; }
.scr-seg-dark svg { height: 20cqw; }
.scr-line { border-top: 1px solid color-mix(in srgb, var(--ink) 30%, transparent); margin: 1.5cqw 0; }
.scr-marquee {
  overflow: hidden; white-space: nowrap; font-size: 3.6cqw;
  letter-spacing: 0.08em; opacity: 0.92; display: flex;
  /* Inside a flex column with no room left, a flex child with no basis collapses to nothing —
     which is how six of the sets ended up with their scrolling line clipped away entirely.
     flex:none stops it being squeezed and the min-height guarantees a line box whatever the
     screen is doing; both are in em so they follow the container-query font size. */
  flex: none; line-height: 1.35; min-height: 1.35em; align-items: center;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
}
.scr-marquee span { animation: scr-scroll 14s linear infinite; padding-right: 2em; will-change: transform; }
.scr-marquee.static { justify-content: center; animation: none; }
@keyframes scr-scroll { from { transform: translateX(0); } to { transform: translateX(-100%); } }
.scr-acq { text-align: center; font-size: 3.6cqw; letter-spacing: 0.35em; opacity: 0.85; animation: scr-blink 1.2s steps(2) infinite; }
@keyframes scr-blink { 50% { opacity: 0.25; } }
.scr-vol {
  position: absolute; right: 4%; bottom: 6%; font-size: 3.4cqw;
  letter-spacing: 0.15em; border: 1px solid color-mix(in srgb, var(--ink) 45%, transparent);
  padding: 0.6cqw 1.6cqw; border-radius: 4px; background: rgba(0,0,0,0.25);
}
.bars { display: inline-flex; align-items: flex-end; gap: 1.5px; height: 3.4cqw; }
.bars i { width: 3px; display: block; border-radius: 1px; }
.bars.vert { flex-direction: column; align-items: stretch; height: auto; width: 2.4cqw; gap: 1.5px; }
.bars.vert i { width: 100%; height: 1.4cqw; }
.scr-sig { display: inline-flex; align-items: center; gap: 1.4cqw; font-size: 2.2cqw; text-align: left; }
.scr-presets { display: flex; gap: 1.4%; margin-top: 2cqw; }
.scr-presets button {
  flex: 1; font-size: 2.7cqw; padding: 1.6cqw 0; border-radius: 5px;
  background: rgba(255,255,255,0.06); color: var(--ink); letter-spacing: 0.05em;
}
.scr-presets button.on { background: color-mix(in srgb, var(--accent) 30%, transparent); box-shadow: inset 0 0 0 1px var(--accent); }
.scr-row { display: flex; align-items: center; gap: 3%; justify-content: space-between; }
.scr-sub { text-align: center; margin-top: 1cqw; }
.scr-sub.tiny { font-size: 2.6cqw; }
.scr-vfd-row { display: flex; align-items: center; gap: 2.4cqw; }
.scr-word { font-size: 3cqw; letter-spacing: 0.2em; opacity: 0.9; }
.scr-word.right { margin-left: auto; }
.style-lcd-light { color: var(--ink); }
.dot { display: inline-block; width: 1.4cqw; height: 1.4cqw; border-radius: 50%; background: #39d98a; }

/* ---------- now playing ---------- */
#np {
  display: flex; align-items: center; gap: 18px;
  width: min(960px, 100%);
  background: color-mix(in srgb, var(--panel) 80%, transparent);
  border: 1px solid var(--line); border-radius: 16px;
  padding: 16px 22px;
}
body.rx-light-env #np { background: rgba(255,255,255,0.6); }
#np-art { position: relative; width: 112px; height: 112px; flex: none; border-radius: 6px; overflow: hidden;
  background: #111; box-shadow: 6px 6px 0 color-mix(in srgb, var(--st-color, var(--env-accent)) 80%, #000); cursor: pointer;
  transition: transform 0.25s ease, box-shadow 0.25s ease; }
#np-art:hover { transform: translate(-2px, -2px); box-shadow: 8px 8px 0 color-mix(in srgb, var(--st-color, var(--env-accent)) 80%, #000); }
#np-art img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
#np-art #np-logo { padding: 22px; object-fit: contain; background: color-mix(in srgb, var(--panel) 90%, #000); }
#np-art .slide { opacity: 0; transition: opacity 1.4s ease; transform: scale(1.02); }
#np-art .slide.show { opacity: 1; animation: np-burns 9s ease-in-out forwards; }
#np-art.has-art #np-logo { opacity: 0; }
@keyframes np-burns { from { transform: scale(1.02); } to { transform: scale(1.1); } }
.np-plate { position: absolute; left: 0; right: 0; bottom: 0; height: 3px; background: var(--st-color, var(--env-accent)); opacity: 0; }
#np-art.has-art .np-plate { opacity: 1; }
/* flex:1 is what makes this column take the room that is left rather than only as much as its
   longest line wants. Without it a long title simply widened the panel and never overflowed,
   so the marquee had nothing to walk. */
.np-txt { display: flex; flex-direction: column; gap: 3px; min-width: 0; flex: 1 1 0; }
#np-station { font-weight: 800; letter-spacing: 0.6px; font-size: 18px; }
#np-track { color: var(--ink); font-size: 16px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; opacity: 0.85; }
#np-tag { color: color-mix(in srgb, var(--env-accent) 80%, var(--ink-dim)); font-size: 12.5px; font-style: italic; }

/* ---------- station rail ---------- */
#station-rail {
  display: flex; gap: 10px; flex-wrap: wrap; justify-content: center;
  width: min(960px, 100%);
}
.stn-chip {
  display: flex; align-items: center; gap: 9px;
  border: 1px solid var(--line); border-radius: 999px;
  padding: 7px 16px 7px 8px; font-size: 12.5px; letter-spacing: 0.4px;
  color: var(--ink-dim); transition: all 0.2s; background: rgba(0,0,0,0.15);
}
.stn-chip img { width: 26px; height: 26px; border-radius: 50%; }
.stn-chip:hover { border-color: var(--c); color: var(--ink); box-shadow: 0 0 16px color-mix(in srgb, var(--c) 25%, transparent); }

/* ---------- panels ---------- */
#panel-backdrop {
  position: fixed; inset: 0; z-index: 70; background: rgba(5,6,8,0.6);
  backdrop-filter: blur(4px); opacity: 0; pointer-events: none; transition: opacity 0.3s;
  display: grid; place-items: center;
}
#panel-backdrop.open { opacity: 1; pointer-events: auto; }
.panel {
  width: min(680px, 94vw); max-height: 84dvh; overflow: auto;
  background: var(--panel); border: 1px solid var(--line); border-radius: 18px;
  transform: translateY(14px); opacity: 0; pointer-events: none; transition: all 0.3s;
  display: none; color: var(--ink);
}
.panel.open { display: block; transform: none; opacity: 1; pointer-events: auto; }
.panel header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 18px 22px; border-bottom: 1px solid var(--line);
  position: sticky; top: 0; background: var(--panel); z-index: 2;
}
.panel h2 { font-size: 16px; font-weight: 600; letter-spacing: 0.5px; }
.panel-close { color: var(--ink-dim); font-size: 15px; }
.panel-body { padding: 20px 22px; display: flex; flex-direction: column; gap: 16px; }
#model-list { padding: 18px; display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.model-card {
  display: flex; flex-direction: column; gap: 10px; padding: 14px;
  border: 1.5px solid var(--line); border-radius: 14px; text-align: left;
  transition: all 0.2s; background: rgba(0,0,0,0.2);
}
.model-card img { width: 100%; object-fit: contain; aspect-ratio: 2.1; }
.model-card b { font-size: 13.5px; letter-spacing: 0.4px; display: block; }
.model-card small { color: var(--ink-dim); font-size: 11.5px; }
.model-card.on { border-color: var(--env-accent); box-shadow: 0 0 20px color-mix(in srgb, var(--env-accent) 20%, transparent); }
.set-row { display: flex; align-items: center; justify-content: space-between; gap: 20px; }
.set-row > span { display: flex; flex-direction: column; gap: 3px; font-size: 14px; }
.set-row small { color: var(--ink-dim); font-size: 12px; }
.set-row select {
  background: #1e2025; color: var(--ink); border: 1px solid var(--line);
  border-radius: 8px; padding: 8px 12px; font: inherit;
}
.ghost-btn { border: 1px solid var(--line); border-radius: 8px; padding: 8px 18px; font-size: 13px; }
.ghost-btn.danger { color: #e8542e; border-color: #5c2c1e; }
.solid-btn {
  background: var(--env-accent); color: #131313; font-weight: 700;
  border-radius: 10px; padding: 11px; letter-spacing: 1px; font-size: 13.5px;
}
.set-note { font-size: 12px; color: var(--ink-dim); line-height: 1.5; }
.set-note b { color: var(--ink); font-weight: 700; }

/* ---------- how this works ---------- */
.help-body { font-size: 13.5px; line-height: 1.55; color: var(--ink-dim); }
.help-lede { color: var(--ink); font-size: 14.5px; line-height: 1.5; padding-bottom: 4px; }
.help-body h3 {
  color: var(--env-accent); font-size: 10.5px; letter-spacing: 2.4px; font-weight: 800;
  text-transform: uppercase; margin-top: 6px; padding-top: 14px; border-top: 1px solid var(--line);
}
.help-body ul { list-style: none; display: flex; flex-direction: column; gap: 7px; }
.help-body li { padding-left: 15px; position: relative; }
.help-body li::before { content: ''; position: absolute; left: 0; top: 8px; width: 5px; height: 5px; border-radius: 50%; background: var(--line); }
.help-body b { color: var(--ink); font-weight: 700; }
.help-foot { font-size: 11.5px; color: #5f5d57; padding-top: 12px; border-top: 1px solid var(--line); }

.kbd-help { border-top: 1px solid var(--line); padding-top: 14px; }
.kbd-help h3 { font-size: 12px; letter-spacing: 1.5px; color: var(--ink-dim); margin-bottom: 8px; }
.kbd-help table { font-size: 12.5px; color: var(--ink-dim); border-spacing: 0 4px; }
.kbd-help td:first-child { color: var(--ink); padding-right: 22px; font-weight: 600; }

/* ---------- visualizer ---------- */
#vis-wrap {
  position: fixed; right: 16px; top: 70px; z-index: 65;
  width: min(420px, 92vw); height: 300px;
  background: #0b0c0f; border: 1px solid var(--line); border-radius: 14px;
  overflow: hidden; display: none; flex-direction: column;
  box-shadow: 0 24px 60px rgba(0,0,0,0.5);
}
#vis-wrap.open { display: flex; }
#vis-wrap.full { inset: 0; width: auto; height: auto; border-radius: 0; }
#vis-bar {
  display: flex; align-items: center; justify-content: space-between;
  padding: 8px 12px; font-size: 10.5px; letter-spacing: 2px; color: var(--ink-dim);
}
#vis-bar button { color: var(--ink-dim); font-size: 11px; padding: 3px 9px; border-radius: 6px; }
#vis-bar button.on { color: var(--env-accent); background: rgba(255,255,255,0.06); }
#vis-wrap canvas { flex: 1; width: 100%; }

/* ---------- OLD SCHOOL: the visual engine in its own little window ---------- */
#os-win {
  position: fixed; right: 18px; top: 84px; z-index: 70;
  width: min(540px, 92vw); height: min(390px, 62vh);
  display: none; flex-direction: column;
  background: #06070a; border: 1px solid var(--line); border-radius: 10px;
  box-shadow: 0 28px 70px rgba(0,0,0,0.62), inset 0 0 0 1px rgba(255,255,255,0.03);
  overflow: hidden; touch-action: none;
}
#os-win.open { display: flex; }
#os-bar {
  display: flex; align-items: center; gap: 9px; flex: none;
  padding: 7px 8px 7px 11px;
  background: linear-gradient(180deg, #191b20, #101216);
  border-bottom: 1px solid #000; cursor: grab; user-select: none;
}
#os-bar:active { cursor: grabbing; }
.os-logo {
  width: 10px; height: 10px; border-radius: 2px; flex: none; background: var(--env-accent);
  box-shadow: 0 0 0 2px #0b0c0f, 0 0 10px color-mix(in srgb, var(--env-accent) 55%, transparent);
}
.os-name { font-size: 10.5px; letter-spacing: 3px; font-weight: 800; color: #cfcabd; flex: none; }
.os-preset {
  font-size: 9.5px; letter-spacing: 2px; color: var(--env-accent); opacity: 0.92;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
}
.os-btns { margin-left: auto; display: flex; gap: 2px; align-items: center; flex: none; }
.os-btns button {
  width: 26px; height: 22px; border-radius: 4px; color: #8e8a80; font-size: 12px;
  line-height: 1; display: grid; place-items: center; transition: all 0.15s;
}
.os-btns button[data-os="auto"], .os-btns button[data-os="pal"] { width: auto; min-width: 34px; padding: 0 7px; font-size: 9px; letter-spacing: 1.5px; font-weight: 700; }
.os-btns button[data-os="pal"] { color: var(--env-accent); }
.os-btns button:hover { color: var(--ink); background: rgba(255,255,255,0.08); }
.os-btns button.on { color: #121212; background: var(--env-accent); }
.os-screen { position: relative; flex: 1; min-height: 0; background: #06070a; }
.os-screen canvas { display: block; width: 100%; height: 100%; }
/* the tube: scan lines and a little corner shade, drawn over the maths */
.os-screen::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background:
    repeating-linear-gradient(180deg, rgba(0,0,0,0.20) 0 1px, transparent 1px 3px),
    radial-gradient(120% 120% at 50% 50%, transparent 52%, rgba(0,0,0,0.55));
  mix-blend-mode: multiply;
}
body.fx-off .os-screen::after { display: none; }
#os-status {
  display: flex; align-items: center; gap: 10px; flex: none; padding: 5px 10px;
  font-size: 9.5px; letter-spacing: 1.6px; color: #6f6c64;
  background: #0a0b0e; border-top: 1px solid #15171c;
}
.os-db { color: var(--env-accent); min-width: 56px; }
.os-meter { flex: 1; height: 4px; background: #15171c; border-radius: 2px; overflow: hidden; }
.os-meter i { display: block; height: 100%; width: 0; background: var(--env-accent); transition: width 0.1s linear; }
.os-rule, .os-idx { flex: none; }
.os-grip {
  position: absolute; right: 0; bottom: 0; width: 16px; height: 16px; cursor: nwse-resize;
  background: linear-gradient(135deg, transparent 48%, #3a3d45 48% 56%, transparent 56% 70%, #3a3d45 70% 78%, transparent 78%);
}
/* blown up, by either road: the real thing or wide mode */
#os-win:fullscreen, #os-win.wide-fs-el {
  inset: 0; left: 0; top: 0; right: 0; bottom: 0;
  width: auto; height: auto; max-width: none; border-radius: 0; border: 0; z-index: 200;
}
#os-win:fullscreen .os-grip, #os-win.wide-fs-el .os-grip { display: none; }

/* the button that opens it, sat with the tuners */
.os-open {
  display: inline-flex; align-items: center; gap: 7px; height: 38px; padding: 0 13px;
  border: 1px solid var(--line); border-radius: 999px; color: var(--ink-dim);
  font-size: 10.5px; letter-spacing: 2.2px; font-weight: 700; white-space: nowrap; transition: all 0.2s;
}
.os-open svg { width: 18px; height: 18px; flex: none; }
.os-open:hover, .os-open.on { color: var(--env-accent); border-color: color-mix(in srgb, var(--env-accent) 55%, var(--line)); }
.os-open.on { background: color-mix(in srgb, var(--env-accent) 12%, transparent); }
/* the shuffle label grows a countdown when it is running, so the pill must not jump about */
.os-open.shuf .sh-lbl { min-width: 62px; text-align: left; }
.os-open.shuf.on .sh-lbl { min-width: 96px; }

/* ---------- wide mode: what full screen means where the browser has no Fullscreen API ---------- */
/* a sliver of extra height is what lets a phone roll its own bars out of the way */
body.wide-fs { min-height: calc(100dvh + 2px); }
body.wide-fs #foot, body.wide-fs #age-badge { display: none; }
body.wide-fs #topbar { padding-top: max(4px, env(safe-area-inset-top)); padding-bottom: 4px; }
body.wide-fs #stage { padding-top: 2px; }

/* ---------- toast & footer ---------- */
#toast {
  position: fixed; left: 50%; bottom: 60px; transform: translate(-50%, 16px);
  background: #22242a; border: 1px solid var(--line); color: var(--ink);
  padding: 10px 20px; border-radius: 999px; font-size: 13px;
  opacity: 0; pointer-events: none; transition: all 0.3s; z-index: 75;
}
#toast.show { opacity: 1; transform: translate(-50%, 0); }
#foot {
  display: flex; gap: 8px; justify-content: center; padding: 10px;
  font-size: 10.5px; color: #55534d; letter-spacing: 0.4px;
}

/* between a laptop and a phone the bar carries a lot: the name and the frequency go first,
   since the set itself already shows both */
@media (max-width: 1480px) {
  #topbar { gap: 12px; }
  .brand-word { display: none; }
  #freq-chip { display: none; }
  .icon-btn { width: 42px; height: 42px; }
  .icon-btn svg { width: 23px; height: 23px; }
}

/* ---------- responsive ---------- */
@media (max-width: 760px) {
  #topbar { flex-wrap: wrap; gap: 10px; }
  .brand-word { display: none; }
  .mode-tabs { order: 3; width: 100%; justify-content: stretch; }
  .mode-tab { flex: 1; text-align: center; }
  #freq-chip { display: none; }
  #model-list { grid-template-columns: 1fr; }
  #np { padding: 10px 14px; }
  #vis-wrap { right: 8px; left: 8px; width: auto; }
  /* on a phone the window is a sheet off the bottom: no dragging, no hunting for a corner */
  #os-win { left: 6px; right: 6px; bottom: 6px; top: auto; width: auto; height: 64vh; }
  .os-open { height: 32px; padding: 0 10px; gap: 5px; font-size: 9px; letter-spacing: 1.4px; }
  .os-open svg { width: 15px; height: 15px; }
}

/* side volume rocker (receivers without a volume knob) */
.rx-sidevol {
  position: absolute; right: -1.6%; top: 22%; width: 3%; height: 42%;
  border-radius: 6px; cursor: ns-resize; z-index: 6;
  background: rgba(0,0,0,0.10); overflow: hidden;
  display: flex; align-items: flex-end;
  opacity: 0; transition: opacity 0.25s;
}
.receiver:hover .rx-sidevol { opacity: 1; }
.rx-sidevol i {
  display: block; width: 100%;
  background: color-mix(in srgb, var(--env-accent) 70%, transparent);
}

.rx-meterclip { position: absolute; overflow: hidden; z-index: 3; pointer-events: none; }
.rx-meterclip .rx-rneedle { height: 2px; }

/* expanded touch hit-areas (invisible) */
.rx-btn::after {
  content: ''; position: absolute; inset: -12px;
}
@media (pointer: coarse) {
  .rx-btn::after { inset: -16px; }
}

/* light environments (white receivers) */
body.light-env {
  --ink: #26282b; --ink-dim: #5a5d63; --panel: #f2f2f4; --line: #d5d7db;
}
body.light-env .boot-word, body.light-env .brand-word { color: #33363b; }
body.light-env .icon-btn:hover { background: rgba(0,0,0,0.05); }
body.light-env .stn-chip { background: rgba(255,255,255,0.55); }
body.light-env #np { background: #2a2c31; --ink: #e9e6df; --ink-dim: #9a968c; color: #e9e6df; }
body.light-env #np-station { color: #e9e6df; }
body.light-env #foot { color: #8e9095; }

/* horizontal slider (fader) caps cut from the art */
.rx-slidehit { position: absolute; z-index: 6; cursor: ew-resize; }
.rx-slidehit:hover { box-shadow: inset 0 0 0 1.5px color-mix(in srgb, var(--env-accent) 45%, transparent); border-radius: 6px; }
.rx-slidecap { position: absolute; z-index: 5; pointer-events: none; transition: left 0.05s linear; }

/* ---------- background FX — compositor-only: transform/opacity, no blend modes over video ---------- */
:root { --fx-k: 1; }
#stage-bg video.show { animation: bg-drift 46s ease-in-out infinite alternate; will-change: transform; }
@keyframes bg-drift { from { transform: scale(1.04) translate(-0.6%, 0.3%); } to { transform: scale(1.12) translate(0.8%, -0.6%); } }
#bg-grain {
  position: absolute; inset: -12%; pointer-events: none;
  background: url("/static/brand/grain.png") 0 0 / 128px 128px;
  opacity: calc(0.2 * var(--fx-k)); animation: bg-grain 0.8s steps(4) infinite; will-change: transform;
}
@keyframes bg-grain { 0% { transform: translate(0,0); } 25% { transform: translate(-3%,2%); } 50% { transform: translate(2%,-3%); } 75% { transform: translate(-2%,-2%); } 100% { transform: translate(3%,3%); } }
#bg-dots {                          /* static halftone: print texture, painted once */
  position: absolute; inset: 0; pointer-events: none; opacity: calc(0.5 * var(--fx-k));
  background: radial-gradient(circle, rgba(0,0,0,0.55) 0.8px, transparent 1.3px) 0 0 / 4px 4px;
}
#bg-pulse {
  position: absolute; inset: 0; pointer-events: none; opacity: 0; will-change: opacity;
  background: radial-gradient(55% 48% at 50% 58%, color-mix(in srgb, var(--st-color, var(--env-accent)) 38%, transparent), transparent 70%);
}
#bg-tint { background: radial-gradient(120% 100% at 50% 42%, rgba(8,9,11,0.12), rgba(8,9,11,0.62)),
  linear-gradient(180deg, rgba(8,9,11,0.42), rgba(8,9,11,0.1) 40%, rgba(8,9,11,0.5)); }
body.light-env #bg-grain { opacity: calc(0.12 * var(--fx-k)); }
body.light-env #bg-dots { opacity: calc(0.25 * var(--fx-k)); }

/* station change: a burst of static + one scan line sweeping down (0.55s digital, 0.9s analog) */
#tune-flash { position: absolute; inset: 0; pointer-events: none; opacity: 0;
  background: url("/static/brand/grain.png") 0 0 / 96px 96px, rgba(210,215,225,0.05); }
#tune-flash i { position: absolute; left: 0; right: 0; top: -20%; height: 16%; opacity: 0.9;
  background: linear-gradient(180deg, transparent, rgba(255,255,255,0.11), transparent); }
#tune-flash.go { animation: tune-flash 0.55s ease-out; }
#tune-flash.go i { animation: tune-scan 0.55s linear; }
#tune-flash.go.analog, #tune-flash.go.analog i { animation-duration: 0.9s; }
@keyframes tune-flash { 0% { opacity: 0; } 10% { opacity: 0.95; } 24% { opacity: 0.45; } 38% { opacity: 0.8; } 100% { opacity: 0; } }
@keyframes tune-scan { from { transform: translateY(0); } to { transform: translateY(760%); } }

/* Now Playing card: slow glass glare every ~16s */
.np-sweep { position: absolute; inset: 0; border-radius: inherit; overflow: hidden; pointer-events: none; }
.np-sweep::before { content: ''; position: absolute; top: 0; bottom: 0; left: 0; width: 45%;
  background: linear-gradient(100deg, transparent, rgba(255,255,255,0.05) 42%, rgba(255,255,255,0.09) 50%, rgba(255,255,255,0.05) 58%, transparent);
  transform: translateX(-120%); animation: np-sweep 16s ease-in-out infinite; will-change: transform; }
@keyframes np-sweep { 0%, 72% { transform: translateX(-120%); } 84%, 100% { transform: translateX(330%); } }

/* ON AIR pill breathes */
.stn-plaque.on .pl-on { animation: pl-breathe 2.6s ease-in-out infinite; }
@keyframes pl-breathe { 0%, 100% { opacity: 1; } 50% { opacity: 0.62; } }

/* effect levels: Full (default desktop) · Lite (default phones) · Off (admin kill switch or listener choice) */
body.fx-lite #bg-grain, body.fx-lite .stn-plaque.on .pl-on { animation: none; }
body.fx-lite #bg-pulse, body.fx-lite .np-sweep { display: none; }
body.fx-off #bg-grain, body.fx-off #bg-dots, body.fx-off #bg-pulse, body.fx-off .np-sweep, body.fx-off #tune-flash { display: none; }
body.fx-off .stn-plaque.on .pl-on, body.fx-off #stage-bg video.show { animation: none; }
body.power-off #bg-grain, body.power-off .np-sweep::before, body.power-off .stn-plaque .pl-on { animation-play-state: paused; }
@media (prefers-reduced-motion: reduce) {
  #stage-bg video.show, #bg-grain, .np-sweep::before, .stn-plaque.on .pl-on,
  #tune-flash.go, #tune-flash.go i, .brand-disc { animation: none !important; }
}

/* ---------- station plaques (replace the logo chips) ---------- */
#station-rail { width: min(960px, 100%); }
.rail-scroll { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; }
.stn-plaque {
  --c: var(--env-accent);
  position: relative; min-width: 168px; padding: 10px 16px 11px; text-align: center;
  border-radius: 6px; color: var(--ink);
  background:
    linear-gradient(180deg, rgba(255,255,255,0.07), rgba(255,255,255,0.02) 45%, rgba(0,0,0,0.18)),
    color-mix(in srgb, var(--panel) 88%, transparent);
  border: 1px solid color-mix(in srgb, var(--c) 45%, #6b5a3a);
  box-shadow: inset 0 0 0 1px rgba(0,0,0,0.5), inset 0 0 0 3px color-mix(in srgb, var(--c) 12%, transparent),
    inset 0 0 0 4px rgba(0,0,0,0.45), 0 6px 18px rgba(0,0,0,0.35);
  transition: transform 0.18s, box-shadow 0.25s, border-color 0.25s;
}
.stn-plaque::before, .stn-plaque::after {
  content: ''; position: absolute; top: 5px; width: 4px; height: 4px; border-radius: 50%;
  background: radial-gradient(circle at 35% 35%, #fff8, #0008); box-shadow: 0 calc(100% + 0px) 0 0 transparent;
}
.stn-plaque::before { left: 6px; box-shadow: 0 var(--rivet, 0) 0 0 transparent; }
.stn-plaque::after { right: 6px; }
.stn-plaque .pl-freq { display: block; font-size: 19px; font-weight: 800; letter-spacing: 1px; font-variant-numeric: tabular-nums; line-height: 1.05; color: color-mix(in srgb, var(--c) 75%, var(--ink)); }
.stn-plaque .pl-freq small { font-size: 10px; font-weight: 700; letter-spacing: 2px; margin-left: 5px; vertical-align: 3px; opacity: 0.75; }
.stn-plaque .pl-name { display: block; font-size: 11.5px; font-weight: 700; letter-spacing: 2.2px; text-transform: uppercase; margin-top: 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 200px; }
.stn-plaque .pl-rule { display: block; height: 1px; margin: 6px auto 0; width: 60%; background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--c) 60%, transparent), transparent); }
.stn-plaque:hover { transform: translateY(-2px); border-color: var(--c); box-shadow: inset 0 0 0 1px rgba(0,0,0,0.5), inset 0 0 0 3px color-mix(in srgb, var(--c) 22%, transparent), inset 0 0 0 4px rgba(0,0,0,0.45), 0 10px 26px rgba(0,0,0,0.45), 0 0 22px color-mix(in srgb, var(--c) 25%, transparent); }
.stn-plaque.on { border-color: var(--c); box-shadow: inset 0 0 0 1px rgba(0,0,0,0.5), inset 0 0 0 3px color-mix(in srgb, var(--c) 35%, transparent), inset 0 0 0 4px rgba(0,0,0,0.45), 0 0 0 1px color-mix(in srgb, var(--c) 40%, transparent), 0 0 28px color-mix(in srgb, var(--c) 35%, transparent); }
.stn-plaque.on .pl-name { color: var(--c); }
.stn-plaque .pl-on { position: absolute; left: 50%; top: -5px; transform: translateX(-50%); font-size: 8.5px; letter-spacing: 2.5px; padding: 1px 7px; border-radius: 999px; background: var(--c); color: #111; font-weight: 800; opacity: 0; transition: opacity 0.2s; }
.stn-plaque.on .pl-on { opacity: 1; }
body.light-env .stn-plaque { background: linear-gradient(180deg, #fbfbfc, #e9eaee); color: #26282b; }

/* ---------- mobile: full-width receiver, scroll-snap plaques, tighter chrome ---------- */
@media (max-width: 760px) {
  #topbar { padding: 8px 12px; gap: 8px; }
  .mode-tabs { order: 0; width: auto; margin-left: 0; }
  .mode-tab { padding: 6px 14px; font-size: 12px; }
  .top-actions { gap: 2px; }
  .icon-btn { width: 34px; height: 34px; }
  #stage { padding: 4px 8px 16px; gap: 12px; }
  .receiver { width: 100% !important; }
  #np { padding: 9px 12px; gap: 10px; border-radius: 12px; }
  #np-art { width: 64px; height: 64px; box-shadow: 4px 4px 0 color-mix(in srgb, var(--st-color, var(--env-accent)) 80%, #000); }
  #np-art #np-logo { padding: 12px; }
  #np-station { font-size: 13px; }
  #np-track { font-size: 12px; }
  #station-rail { margin: 0 -8px; width: calc(100% + 16px); max-width: none; }
  .rail-scroll { width: 100%; }
  .rail-scroll { flex-wrap: nowrap; justify-content: flex-start; overflow-x: auto; padding: 8px 12px 12px; gap: 10px;
    scroll-snap-type: x mandatory; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
  .rail-scroll::-webkit-scrollbar { display: none; }
  .stn-plaque { flex: 0 0 auto; min-width: 150px; scroll-snap-align: center; }
  #foot { padding: 6px 10px 14px; }
  #age-badge { bottom: 40px; right: 8px; }
  #foot { flex-wrap: wrap; text-align: center; }
}
/* phone held sideways: the set gets the height, everything else gets out of its way */
@media (max-width: 1023px) and (orientation: landscape) and (max-height: 560px) {
  #topbar { padding: 6px 12px; gap: 10px; }
  .brand-disc { width: 34px; height: 34px; }
  .brand-word { font-size: 12px; letter-spacing: 2px; }
  .mode-tab { padding: 7px 14px; font-size: 12px; }
  .icon-btn { width: 34px; height: 34px; }
  #stage { padding-top: 4px; gap: 8px; }
  /* the art carries its own aspect-ratio, so giving it a height lets the width follow */
  .receiver { height: calc(100dvh - 136px); width: auto; max-width: 100%; }
  .receiver .rx-art { height: 100%; width: auto; max-width: 100%; margin: 0 auto; }
  #np { display: none; }
  #stage { padding-bottom: 8px; }
  #station-rail { margin-top: 2px; }
  .rail-scroll { gap: 8px; flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; max-width: 100%; }
  .rail-scroll::-webkit-scrollbar { display: none; }
  .stn-plaque { min-width: 118px; padding: 5px 10px 6px; flex: none; }
  .stn-plaque .pl-logo { max-height: 26px; }
  .stn-plaque .pl-freq { font-size: 15px; } .stn-plaque .pl-name { font-size: 9px; }
  .stn-plaque .pl-on { font-size: 7px; padding: 1px 5px; }
  #foot, .boot-sub { display: none; }
  /* sideways, the window takes the whole height it can get */
  #os-win { left: 6px; right: 6px; top: 6px; bottom: 6px; width: auto; height: auto; }
  .boot-word { font-size: clamp(24px, 6.6vw, 60px); }
  .boot-mark { width: clamp(74px, 20vh, 120px); }
  #boot-btn { margin-top: 12px; padding: 12px 42px; font-size: 15px; }
}

/* compact screens: wide-and-short glass keeps everything inside */
.rx-screen.compact { padding: 1.4% 3%; }
.rx-screen.compact .scr-freq-big { font-size: 9.5cqw; }
.rx-screen.compact .scr-top { font-size: 2.4cqw; }
.rx-screen.compact .scr-stn { font-size: 3.2cqw; }
.rx-screen.compact .scr-presets { margin-top: 1cqw; }
.rx-screen.compact .scr-presets button { font-size: 2.2cqw; padding: 0.9cqw 0; }
.rx-screen.compact .scr-seg svg { height: 10.5cqw; }
.rx-screen.compact .scr-marquee { font-size: 2.8cqw; }
.rx-screen.compact .scr-sub { margin-top: 0.4cqw; }

/* live visualizer canvases + vertical EQ faders */
.rx-vis { position: absolute; z-index: 3; pointer-events: none; }
.rx-eqhit { position: absolute; z-index: 6; cursor: ns-resize; }
.rx-eqhit:hover { box-shadow: inset 0 0 0 1.5px color-mix(in srgb, var(--env-accent) 45%, transparent); border-radius: 6px; }
.rx-eqcap { position: absolute; z-index: 5; pointer-events: none; transition: top 0.05s linear; }

/* ---------- poster backdrop (stations without a video scene) ---------- */
#bg-poster { position: absolute; inset: -6%; background-size: cover; background-position: center;
  filter: blur(26px) saturate(0.9) brightness(0.55); opacity: 0; transition: opacity 1.6s ease;
  transform: scale(1.06); }
#bg-poster.show { opacity: 1; animation: bg-drift 60s ease-in-out infinite alternate; }

/* ---------- the fake ads ----------
   A banner across the bottom, one at a time and the whole width, the way the real ones look.
   They are drawn to this shape rather than cropped into it (scripts/make_ad_banners.py), so the
   headline is readable at any width. Nothing says "fictional" on them: the jokes do that. */
#adbar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 62;
  display: block; line-height: 0; overflow: hidden;
  box-shadow: 0 -10px 30px rgba(0,0,0,0.45);
  transform: translateY(102%); transition: transform 0.75s cubic-bezier(0.2, 0.7, 0.2, 1);
}
#adbar.show { transform: none; }
#ad-img { display: block; width: 100%; height: auto; aspect-ratio: 8 / 1; object-fit: cover; }
#ad-img.swap { animation: ad-in 0.5s ease both; }
@keyframes ad-in { from { opacity: 0; transform: translateX(26px); } to { opacity: 1; transform: none; } }
#ad-x {
  position: absolute; right: 6px; top: 6px; z-index: 3;
  width: 24px; height: 24px; border-radius: 2px; color: #fff; font-size: 11px;
  background: rgba(0,0,0,0.45); line-height: 1;
}
#ad-x:hover { background: rgba(0,0,0,0.75); }
body.fx-off #adbar { display: none; }
@media (prefers-reduced-motion: reduce) {
  #adbar { transition: none; }
  #ad-img.swap { animation: none; }
}

/* ---------- poster lightbox ---------- */
#lightbox { position: fixed; inset: 0; z-index: 90; background: rgba(6,7,9,0.88); display: grid; place-items: center;
  backdrop-filter: blur(6px); animation: lb-in 0.25s ease; }
#lightbox[hidden] { display: none; }
@keyframes lb-in { from { opacity: 0; } }
.lb-inner { display: flex; align-items: center; gap: 18px; padding: 24px; max-width: 100vw; }
#lightbox figure { margin: 0; display: flex; flex-direction: column; gap: 14px; align-items: center; }
#lb-img { width: min(78vh, 86vw); height: min(78vh, 86vw); object-fit: cover; border-radius: 4px;
  box-shadow: 12px 12px 0 color-mix(in srgb, var(--st-color, var(--env-accent)) 85%, #000), 0 30px 80px rgba(0,0,0,0.6);
  animation: lb-pop 0.35s cubic-bezier(.2,.8,.2,1); }
@keyframes lb-pop { from { transform: scale(0.96); opacity: 0; } }
#lightbox figcaption { display: flex; align-items: center; gap: 14px; color: var(--ink); font-size: 14px; letter-spacing: 0.5px; }
#lightbox figcaption b { font-weight: 800; letter-spacing: 1px; text-transform: uppercase; }
#lightbox figcaption span:not(.lb-dots) { color: var(--st-color, var(--env-accent)); font-weight: 700; }
.lb-dots { display: flex; gap: 6px; }
.lb-dots i { width: 7px; height: 7px; border-radius: 50%; background: var(--ink-dim); opacity: 0.45; }
.lb-dots i.on { background: var(--st-color, var(--env-accent)); opacity: 1; }
.lb-nav, .lb-close { background: none; border: 1px solid rgba(255,255,255,0.18); color: var(--ink); width: 44px; height: 44px;
  border-radius: 50%; font-size: 26px; line-height: 1; cursor: pointer; display: grid; place-items: center; }
.lb-nav:hover, .lb-close:hover { border-color: var(--st-color, var(--env-accent)); color: var(--st-color, var(--env-accent)); }
.lb-close { position: fixed; top: 18px; right: 18px; font-size: 18px; }
@media (max-width: 720px) { .lb-nav { display: none; } .lb-inner { padding: 12px; } }

/* ---------- station logo lockups (transparent art from admin) ---------- */
.stn-plaque.has-logo { padding: 12px 18px 10px; min-width: 176px; }
.stn-plaque .pl-logo { display: block; height: 46px; width: auto; max-width: 190px; object-fit: contain; margin: 0 auto;
  filter: drop-shadow(0 2px 0 rgba(0,0,0,0.55)) drop-shadow(0 6px 10px rgba(0,0,0,0.35)); transition: transform 0.18s, filter 0.25s; }
.stn-plaque:hover .pl-logo { transform: scale(1.03); }
.stn-plaque.on .pl-logo { filter: drop-shadow(0 2px 0 rgba(0,0,0,0.55)) drop-shadow(0 0 14px color-mix(in srgb, var(--c) 55%, transparent)); }
.np-logo-wide { display: block; height: 46px; width: auto; max-width: min(300px, 60vw); object-fit: contain; object-position: left center;
  filter: drop-shadow(0 2px 0 rgba(0,0,0,0.5)); margin-bottom: 2px; }
.lb-logo { height: 40px; width: auto; max-width: 240px; object-fit: contain; display: block; filter: drop-shadow(0 2px 0 rgba(0,0,0,0.6)); }
@media (max-width: 760px) {
  .stn-plaque.has-logo { min-width: 150px; padding: 10px 12px 8px; }
  .stn-plaque .pl-logo { height: 36px; max-width: 140px; }
  .np-logo-wide { height: 32px; }
}

/* model drawer: mode group headers (both modes listed, cross-mode pick switches) */
.model-group {
  grid-column: 1 / -1; font-size: 11px; letter-spacing: 2.5px; font-weight: 700;
  color: var(--ink-dim); padding: 10px 4px 0; border-bottom: 1px solid var(--line);
  margin-bottom: 2px;
}
.model-group:first-child { padding-top: 0; }

/* station color bleeds into the chrome while tuned */
#np { border-left: 3px solid var(--st-color, var(--line)); transition: border-color 0.8s ease; }
#freq-chip { color: color-mix(in srgb, var(--st-color, var(--ink-dim)) 60%, var(--ink-dim)); transition: color 0.8s ease; }

/* live waveform strip fills the NP card's right side */
#np-wave { margin-left: auto; width: 180px; height: 44px; flex: none; opacity: 0.9; }
@media (max-width: 900px) { #np-wave { display: none; } }

/* 4: inactive plaques sit back; hover brings them forward */
.stn-plaque:not(.on) { filter: brightness(0.78) saturate(0.85); transition: filter 0.25s ease, transform 0.25s ease; }
.stn-plaque:not(.on):hover { filter: brightness(1.02) saturate(1); }

/* 7: model drawer scales to the 24-strong fleet */
@media (min-width: 900px) { #model-list { grid-template-columns: 1fr 1fr 1fr; } }
.model-group { position: sticky; top: 64px; z-index: 3;
  background: var(--panel); padding-bottom: 6px; }
.model-card { transition: transform 0.18s ease, border-color 0.2s, box-shadow 0.2s; }
.model-card:hover { transform: translateY(-3px); border-color: color-mix(in srgb, var(--env-accent) 55%, var(--line)); }

/* 8: brand lockup balanced with the enlarged bar */
.brand-word { font-size: 15.5px; letter-spacing: 3.5px; }
.brand-disc { width: 56px; height: 56px; }

/* 9: tube warm-up — screens, needles, LEDs and meters glow in on power-up */
.receiver .rx-layer { transition: opacity 0.9s ease, filter 0.9s ease; }
.receiver.warmup .rx-layer { opacity: 0.15; filter: brightness(1.9) blur(0.6px); }

/* 10: dial-light flicker while hunting through static (analog only) */
.rx-screen, .rx-needle { transform: translateZ(0); }
.receiver.static-hunt .rx-needle,
.receiver.static-hunt .rx-ledrow i.on { animation: dial-flicker 0.42s steps(3, end) infinite; }
@keyframes dial-flicker {
  0%, 100% { opacity: 1; }
  38% { opacity: 0.82; }
  71% { opacity: 0.93; }
}

.boot-sub { animation: boot-word-in 1.1s cubic-bezier(0.22, 0.75, 0.25, 1) 0.45s both; }
.boot-mark {
  /* the record spins up and settles upright while the glow keeps breathing (separate properties, so both run) */
  animation: vu-mark 1.3s ease-in-out infinite,
             boot-spin 4.6s cubic-bezier(0.12, 0.62, 0.15, 1) 0.25s both;
}
@keyframes vu-mark {
  0%, 100% { filter: drop-shadow(0 0 6px color-mix(in srgb, var(--env-accent) 25%, transparent)); }
  45% { filter: drop-shadow(0 0 26px color-mix(in srgb, var(--env-accent) 55%, transparent)); }
}
@keyframes boot-spin { from { transform: rotate(0deg); } to { transform: rotate(1080deg); } }   /* three turns */
@media (prefers-reduced-motion: reduce) {
  .boot-word, .boot-sub, .boot-mark { animation: none; }
}

/* LIVE badge: broadcast-red pulse, only while genuinely on-air */
#np { position: relative; }
#np-live {
  position: absolute; top: 12px; right: 18px;
  display: none; align-items: center; gap: 7px;
  font-size: 11px; font-weight: 800; letter-spacing: 2.5px;
  color: #e8452e;
}
#np-live.show { display: inline-flex; }
#np-live i {
  width: 8px; height: 8px; border-radius: 50%; background: #e8452e;
  animation: live-pulse 1.6s ease-out infinite;
}
@keyframes live-pulse {
  0% { box-shadow: 0 0 0 0 rgba(232, 69, 46, 0.55); }
  70% { box-shadow: 0 0 0 9px rgba(232, 69, 46, 0); }
  100% { box-shadow: 0 0 0 0 rgba(232, 69, 46, 0); }
}
@media (max-width: 900px) { #np-live { top: 9px; right: 12px; } }
@media (prefers-reduced-motion: reduce) { #np-live i { animation: none; } }



/* stations with no broadcast yet: gentle dim + OFF AIR badge in the same
   voice as the ON AIR pill (identical geometry, muted slate) */
.stn-plaque.offair { filter: brightness(0.82) saturate(0.85); }
.stn-plaque.offair:hover { filter: none; }
.stn-plaque.offair::after {
  content: 'OFF AIR'; position: absolute; left: 50%; top: -5px;
  transform: translateX(-50%);
  font-size: 8.5px; letter-spacing: 2.5px; padding: 1px 7px;
  border-radius: 999px; background: #3a3d44; color: #b8bac0; font-weight: 800;
}
.stn-plaque.offair .pl-on { display: none; }

/* ---------- first-visit hints (coach.js): soft focus ring + small label with a swirl ---------- */
#coach { position: fixed; inset: 0; pointer-events: none; z-index: 60; }
.coach-spot {
  position: fixed; border-radius: 50%; pointer-events: none; opacity: 0; transition: opacity 0.5s ease;
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--st-color, var(--env-accent)) 72%, transparent),
              0 0 26px 8px color-mix(in srgb, var(--st-color, var(--env-accent)) 32%, transparent),
              inset 0 0 18px 4px color-mix(in srgb, var(--st-color, var(--env-accent)) 22%, transparent);
}
.coach-spot.rect { border-radius: 16px; }
.coach-spot::after {                 /* one ring rippling outward: transform + opacity only */
  content: ''; position: absolute; inset: -2px; border-radius: inherit;
  border: 2px solid color-mix(in srgb, var(--st-color, var(--env-accent)) 60%, transparent);
  animation: coach-ping 2.2s ease-out infinite;
}
.coach-spot.rect::after { animation-name: coach-ping-rect; }
@keyframes coach-ping { 0% { transform: scale(1); opacity: 0.85; } 100% { transform: scale(1.5); opacity: 0; } }
@keyframes coach-ping-rect { 0% { transform: scale(1); opacity: 0.7; } 100% { transform: scale(1.06, 1.35); opacity: 0; } }
.coach-spot.show { opacity: 1; }

.coach-tip {
  position: fixed; pointer-events: auto; cursor: pointer; opacity: 0; transform: translateY(6px);
  transition: opacity 0.5s ease, transform 0.5s ease;
  background: rgba(12, 12, 14, 0.86); color: #ede3d1; text-align: left;
  border: 1px solid color-mix(in srgb, var(--st-color, var(--env-accent)) 55%, #3a3d44);
  border-radius: 8px; padding: 7px 12px 8px; max-width: 250px;
  box-shadow: 0 10px 26px rgba(0, 0, 0, 0.45);
}
.coach-tip.show { opacity: 1; transform: none; }
.coach-tip b { display: block; font-size: 12px; font-weight: 800; letter-spacing: 2.2px; white-space: nowrap; }
.coach-tip small { display: block; font-size: 11px; letter-spacing: 0.3px; color: #b9b2a3; margin-top: 2px; }
.coach-tip svg { position: absolute; width: 34px; height: 30px; overflow: visible; pointer-events: none; }
.coach-tip[data-side="above"] svg { top: calc(100% + 6px); }
.coach-tip[data-side="below"] svg { bottom: calc(100% + 6px); transform: rotate(180deg); }
.coach-tip svg path { fill: none; stroke: color-mix(in srgb, var(--st-color, var(--env-accent)) 80%, #ede3d1);
  stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.coach-tip svg .sw { stroke-dasharray: 90; stroke-dashoffset: 90; }
.coach-tip.show svg .sw { animation: coach-draw 0.9s 0.25s ease-out forwards; }
@keyframes coach-draw { to { stroke-dashoffset: 0; } }
@media (prefers-reduced-motion: reduce) {
  .coach-spot::after { animation: none; }
  .coach-tip svg .sw { stroke-dashoffset: 0; animation: none !important; }
}

/* ---------- tuner put away ----------
   The receiver is the control surface, so hiding it means standing in for every knob it took
   with it: the deck below is power, tuning, mute and volume, square and big enough to hit.
   Everything else gets the room the set was using — the art, the title, the level, the LIVE
   lamp — and the corners come in, because the point of this mode is the picture, not a box. */
body.no-rx #receiver-wrap { display: none; }
body.no-rx #stage { gap: 14px; padding-top: 2px; }
body.no-rx #np {
  width: min(1180px, 100%); border-radius: 4px; padding: 22px 26px; gap: 26px;
  border: 1px solid color-mix(in srgb, var(--st-color, var(--line)) 45%, var(--line));
  border-left-width: 5px;
  background: color-mix(in srgb, var(--panel) 62%, transparent);
  backdrop-filter: blur(3px);
}
body.no-rx #np-art { width: 168px; height: 168px; border-radius: 2px;
  box-shadow: 9px 9px 0 color-mix(in srgb, var(--st-color, var(--env-accent)) 80%, #000); }
body.no-rx #np-station { font-size: 22px; letter-spacing: 0.5px; }
body.no-rx #np-station .np-logo-wide { max-height: 54px; }
body.no-rx #np-track { font-size: 18px; }
body.no-rx #np-tag { font-size: 13px; }
body.no-rx #np-live { font-size: 12px; letter-spacing: 3px; padding: 7px 14px; border-radius: 2px; }
body.no-rx #np-live i { width: 9px; height: 9px; }
body.no-rx #np-wave { width: 300px; height: 74px; }
body.no-rx .stn-plaque { border-radius: 3px; }

/* [hidden] loses to a display rule, so the deck was showing beside the tuner as well as
   instead of it. It only ever appears when the tuner is away. */
#deck {
  display: none; align-items: stretch; gap: 10px; flex-wrap: wrap; justify-content: center;
  width: min(1180px, 100%);
}
body.no-rx #deck { display: flex; }
#deck[hidden] { display: none; }
.dk {
  min-width: 62px; height: 60px; padding: 0 18px; border-radius: 3px;
  border: 1px solid var(--line); background: color-mix(in srgb, var(--panel) 72%, transparent);
  color: var(--ink-dim); font-size: 17px; font-weight: 700; letter-spacing: 2px;
  display: grid; place-items: center; transition: all 0.16s;
}
.dk span { font-size: 11.5px; letter-spacing: 2.6px; }
.dk:hover { color: var(--ink); border-color: var(--dim, #4a4d55); background: color-mix(in srgb, var(--panel) 92%, transparent); }
.dk:active { transform: translateY(1px); }
.dk.on { color: #121212; background: var(--st-color, var(--env-accent)); border-color: transparent; }
.dk-pwr.on { background: var(--st-color, var(--env-accent)); }
.dk-read {
  flex: 1; min-width: 180px; display: flex; flex-direction: column; justify-content: center;
  padding: 0 20px; border: 1px solid var(--line); border-radius: 3px;
  background: color-mix(in srgb, var(--panel) 72%, transparent);
}
.dk-read b { font-size: 30px; font-weight: 300; letter-spacing: 1px; line-height: 1;
  color: var(--st-color, var(--env-accent)); font-variant-numeric: tabular-nums; }
.dk-read span { font-size: 11.5px; letter-spacing: 2.4px; color: var(--ink-dim); margin-top: 5px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dk-vol { display: flex; align-items: center; gap: 12px; padding: 0 18px; height: 60px;
  border: 1px solid var(--line); border-radius: 3px;
  background: color-mix(in srgb, var(--panel) 72%, transparent); }
.dk-vol span { font-size: 11px; letter-spacing: 2.4px; color: var(--ink-dim); }
.dk-vol input { width: 150px; accent-color: var(--st-color, var(--env-accent)); }
body.no-rx.power-off .dk-read b { color: var(--ink-dim); }

@media (max-width: 760px) {
  body.no-rx #np { padding: 14px; gap: 14px; }
  body.no-rx #np-art { width: 104px; height: 104px; }
  body.no-rx #np-station { font-size: 17px; }
  body.no-rx #np-track { font-size: 14px; }
  body.no-rx #np-wave { display: none; }
  .dk { height: 52px; min-width: 54px; padding: 0 12px; }
  .dk-read { min-width: 120px; padding: 0 12px; }
  .dk-read b { font-size: 23px; }
  .dk-vol { width: 100%; justify-content: center; }
  .dk-vol input { width: 60%; }
}

/* ---------- station clock ----------
   Central by default, because that is where the station keeps its hours. The picker beside it
   is a real <select>, so it behaves like the phone's own control rather than a menu I invented. */
#clock-wrap { position: relative; display: flex; align-items: center; gap: 6px;
  margin-right: 6px; padding-right: 17px; }
#clock { display: flex; align-items: baseline; gap: 6px; white-space: nowrap; }
#clock b { font-size: 15px; font-weight: 400; letter-spacing: 0.5px; color: var(--ink);
  font-variant-numeric: tabular-nums; }
#clock em { font-style: normal; font-size: 10px; letter-spacing: 1.6px; color: var(--ink-dim); }
/* The select is laid over the caret at zero opacity rather than restyled. A styled select still
   paints its chosen option inside itself, which is what was spilling "Cen" across the corner. */
#clock-tz { position: absolute; right: 0; top: 0; width: 17px; height: 100%;
  opacity: 0; cursor: pointer; border: 0; padding: 0; }
#clock-wrap::after {
  content: ''; position: absolute; right: 3px; top: 50%; margin-top: -2px;
  width: 0; height: 0; border-left: 4px solid transparent; border-right: 4px solid transparent;
  border-top: 5px solid var(--ink-dim); pointer-events: none; transition: border-top-color 0.2s;
}
#clock-wrap:hover::after { border-top-color: var(--env-accent); }
@media (max-width: 1480px) { #clock b { font-size: 14px; } }
@media (max-width: 760px) { #clock em { display: none; } #clock-wrap { margin-right: 0; } }

/* ---------- titles that move ----------
   The panel clips, the inner span walks. Ellipsis stays as the fallback for anyone who has
   asked for less motion, so nothing is ever simply cut off with no way to read it. */
#np-track { position: relative; }
/* width:max-content is what lets it exceed the clipping parent; without it the span is sized
   to the panel and there is never anything to walk. */
#np-track .np-roll { display: inline-block; width: max-content; max-width: none;
  white-space: nowrap; will-change: transform; }
#np-track .np-roll.walk { animation: np-walk var(--walk, 14s) ease-in-out infinite alternate; }
@keyframes np-walk {
  0%, 12%   { transform: translateX(0); }
  88%, 100% { transform: translateX(var(--over, 0)); }
}
#np-track.np-in .np-roll { animation-name: np-arrive, np-walk; animation-duration: 0.55s, var(--walk, 14s);
  animation-delay: 0s, 0.55s; animation-timing-function: cubic-bezier(0.2, 0.7, 0.2, 1), ease-in-out;
  animation-iteration-count: 1, infinite; animation-direction: normal, alternate; }
#np-track.np-in .np-roll:not(.walk) { animation: np-arrive 0.55s cubic-bezier(0.2, 0.7, 0.2, 1) both; }
@keyframes np-arrive { from { opacity: 0; transform: translateX(14px); } to { opacity: 1; transform: translateX(0); } }
/* the station name gets the same arrival, without the walk */
#np-station { transition: opacity 0.4s ease; }
@media (prefers-reduced-motion: reduce) {
  #np-track .np-roll.walk { animation: none; }
  #np-track { text-overflow: ellipsis; }
}

/* ---------- the tip bar ----------
   The tuner starts put away, which hides a lot of the set, so this says so — once per tip, a
   few times at most, and never again once the control it points at has been used. It is a strip
   rather than a modal: it never covers the picture and never needs dismissing to carry on. */
#tipbar {
  display: flex; align-items: center; justify-content: center; gap: 12px;
  margin: 0 auto 2px; padding: 9px 14px; width: fit-content; max-width: calc(100% - 24px);
  border: 1px solid color-mix(in srgb, var(--st-color, var(--env-accent)) 34%, var(--line));
  border-radius: 3px; background: color-mix(in srgb, var(--panel) 80%, transparent);
  backdrop-filter: blur(4px); box-shadow: 0 14px 34px -18px #000;
  font-size: 13px; color: var(--ink-dim); line-height: 1.4;
  opacity: 0; transform: translateY(-6px); transition: opacity 0.5s ease, transform 0.5s ease;
}
#tipbar.show { opacity: 1; transform: none; }
#tip-text { min-width: 0; }
#tip-do {
  flex: none; height: 30px; padding: 0 13px; border-radius: 2px;
  border: 1px solid color-mix(in srgb, var(--st-color, var(--env-accent)) 55%, var(--line));
  color: var(--st-color, var(--env-accent));
  font-size: 10.5px; letter-spacing: 1.8px; font-weight: 700; text-transform: uppercase;
  white-space: nowrap; transition: all 0.18s;
}
#tip-do:hover { background: color-mix(in srgb, var(--st-color, var(--env-accent)) 16%, transparent); }
#tip-x { flex: none; width: 24px; height: 24px; border-radius: 2px; color: #6c6a64; font-size: 12px; }
#tip-x:hover { color: var(--ink); background: rgba(255,255,255,0.07); }
@media (max-width: 760px) {
  #tipbar { font-size: 12px; gap: 9px; padding: 8px 10px; margin-bottom: 4px; }
  #tip-do { height: 27px; padding: 0 10px; font-size: 9.5px; letter-spacing: 1.2px; }
}
@media (prefers-reduced-motion: reduce) { #tipbar { transition: opacity 0.3s ease; transform: none; } }

/* ---------- bigger mark, psychedelic glow behind it ----------
   The glow is a second element rather than a filter on the record, so the colour can wheel
   round on its own while the record keeps spinning. Two counter-rotating cones, blurred to
   nothing, which is enough to read as a haze and cheap enough to leave running. */
.boot-mark { width: clamp(220px, 34vh, 360px); }
.boot-logo { position: relative; }
.boot-glow {
  position: absolute; left: 50%; top: 0; translate: -50% 0;
  width: clamp(330px, 52vh, 560px); aspect-ratio: 1; margin-top: clamp(-56px, -9vh, -40px);
  border-radius: 50%; pointer-events: none; z-index: -1; opacity: 0.55;
  background:
    conic-gradient(from 0deg, #ff4d2e, #ffd23f, #4ee07a, #35b7ff, #a05cff, #ff3fb0, #ff4d2e),
    radial-gradient(circle, #fff 0%, transparent 62%);
  background-blend-mode: screen;
  filter: blur(42px) saturate(1.5);
  animation: boot-glow-turn 14s linear infinite, boot-glow-breathe 5.5s ease-in-out infinite;
}
.boot-glow::after {
  content: ''; position: absolute; inset: 14%;
  border-radius: 50%; mix-blend-mode: screen;
  background: conic-gradient(from 180deg, #35b7ff, #a05cff, #ff3fb0, #ffd23f, #35b7ff);
  filter: blur(30px); opacity: 0.75;
  animation: boot-glow-turn 9s linear infinite reverse;
}
@keyframes boot-glow-turn { to { rotate: 360deg; } }
@keyframes boot-glow-breathe { 0%, 100% { opacity: 0.42; } 50% { opacity: 0.72; } }
body.fx-off .boot-glow { display: none; }
@media (max-width: 760px) { .boot-mark { width: clamp(150px, 26vh, 230px); } }
@media (prefers-reduced-motion: reduce) { .boot-glow { animation: none; } }

/* ---------- the station on the now-playing bar ----------
   The logo takes the height it can get and the name is set to carry the line on its own when a
   station has no wide logo. Both arrive rather than appear, and the logo keeps a slow sheen so
   the bar is never completely still. */
.np-logo-wide { height: 68px; max-width: min(420px, 64vw); }
body.no-rx #np-station .np-logo-wide { max-height: none; height: 86px; max-width: min(520px, 60vw); }
#np-station .np-logo-wide { animation: np-logo-in 0.6s cubic-bezier(0.2, 0.7, 0.2, 1) both,
                                       np-logo-sheen 7s ease-in-out 0.6s infinite; }
@keyframes np-logo-in { from { opacity: 0; transform: translateY(8px) scale(0.96); } to { opacity: 1; transform: none; } }
@keyframes np-logo-sheen {
  0%, 100% { filter: drop-shadow(0 2px 0 rgba(0,0,0,0.5)); }
  50% { filter: drop-shadow(0 2px 0 rgba(0,0,0,0.5))
               drop-shadow(0 0 16px color-mix(in srgb, var(--st-color, var(--env-accent)) 55%, transparent)); }
}
/* stations with no wide logo get the same treatment on the words */
#np-station { animation: np-logo-in 0.6s cubic-bezier(0.2, 0.7, 0.2, 1) both; }
body.fx-off #np-station .np-logo-wide, body.fx-off #np-station { animation: none; }
@media (max-width: 760px) {
  .np-logo-wide { height: 44px; max-width: 60vw; }
  body.no-rx #np-station .np-logo-wide { height: 52px; }
}
@media (prefers-reduced-motion: reduce) {
  #np-station, #np-station .np-logo-wide { animation: none; }
}

/* ---------- the tone arm ----------
   It rides the record while it spins up, then lifts away as the record slows and parks itself
   off to the side. Kept see-through: it belongs to the same ghost as the glow, not to the mark.
   The geometry hangs off --disc so arm and record scale together. */
.boot-logo { --disc: clamp(220px, 34vh, 360px); }
.boot-arm {
  position: absolute; left: 50%; top: 0; z-index: 3; pointer-events: none;
  width: calc(var(--disc) * 0.062); height: calc(var(--disc) * 0.56);
  margin-left: calc(var(--disc) * 0.40); margin-top: calc(var(--disc) * 0.05);
  transform-origin: 50% calc(var(--disc) * 0.05);
  border-radius: 999px; opacity: 0.58;        /* see-through, but it has to read against the sleeve art */
  background: linear-gradient(90deg, #6f6a61, #e8e3d6 42%, #6f6a61);
  filter: drop-shadow(0 3px 7px rgba(0, 0, 0, 0.55));
  animation: boot-arm-off 5.1s linear 0.25s both;
}
.boot-arm::before {                       /* the pivot it turns on */
  content: ''; position: absolute; left: 50%; top: 0; translate: -50% -22%;
  width: calc(var(--disc) * 0.105); height: calc(var(--disc) * 0.105); border-radius: 50%;
  background: radial-gradient(circle at 34% 30%, #efeade, #7b7569 60%, #4b473f);
}
.boot-arm::after {                        /* the head at the far end */
  content: ''; position: absolute; left: 50%; bottom: 0; translate: -50% 0; rotate: -8deg;
  width: calc(var(--disc) * 0.082); height: calc(var(--disc) * 0.10); border-radius: 2px;
  background: linear-gradient(150deg, #e4dfd2, #645f57);
}
@keyframes boot-arm-off {
  0%        { rotate: -33deg; }           /* down on the record while it turns */
  58%       { rotate: -29deg; animation-timing-function: cubic-bezier(0.3, 0, 0.2, 1); }
  100%      { rotate: 24deg; }            /* lifted off and parked as it stops */
}
body.fx-off .boot-arm { display: none; }
@media (max-width: 760px) { .boot-logo { --disc: clamp(150px, 26vh, 230px); } }
@media (prefers-reduced-motion: reduce) { .boot-arm { animation: none; rotate: 24deg; } }

/* ---------- portrait: show the whole frame, not a slice of it ----------
   The scenes are 16:9 and a phone held upright is about 9:19.5. Covering that crops away
   roughly two thirds of the width, which is how a mouth full of teeth becomes an unreadable
   smear. Upright, the video is contained instead — the whole frame, letterboxed — and the
   gap behind it is filled by the scene's own poster, blown up and blurred. That costs one
   image rather than a second video, which matters: a phone has only so many decoders and the
   audio needs one of them. */
/* The same panel in landscape on a phone.

   It was dropped outright here - two hundred pixels against a screen barely four hundred
   took the picture and the dial with it. It is a third of that now, so with the tuner put
   away, which is exactly when nothing else on screen says what is playing, it stays and is
   squeezed to a single line. With the tuner up the receiver's own screen carries the title
   and this would only be saying it twice.

   These rules sit AFTER the body.no-rx block on purpose: they carry the same weight, so
   placed before it they lost and the panel came back at its desktop size. */
@media (max-width: 1023px) and (orientation: landscape) and (max-height: 560px) {
  body.no-rx #np { display: flex; padding: 6px 10px; gap: 10px; border-radius: 10px;
    background: color-mix(in srgb, var(--panel) 42%, transparent); }
  body.no-rx #np-art { width: 46px; height: 46px; border-radius: 3px;
    box-shadow: 3px 3px 0 color-mix(in srgb, var(--st-color, var(--env-accent)) 80%, #000); }
  body.no-rx #np-art #np-logo { padding: 6px; }
  body.no-rx #np-station { font-size: 13px; }
  body.no-rx #np-station .np-logo-wide { max-height: 22px; }
  body.no-rx #np-track { font-size: 17px; }
  body.no-rx #np-tag { display: none; }
  body.no-rx #np-wave { display: none; }
  body.no-rx #np-live { font-size: 9px; letter-spacing: 1.5px; padding: 4px 7px; }
  body.no-rx #np-live i { width: 6px; height: 6px; }
  #release { padding: 6px 10px; }
  .rl-links a.has-badge { padding: 4px 7px; }
  .rl-links a img.rl-badge { height: 20px; }
}

/* ---------- out now ----------
   Shown only while a song that is actually released is on air, which is the one moment
   anybody wants to go and find it. Flat and typographic rather than a row of brand logos:
   the strip belongs to the station, not to three shops. The bars are driven by the real
   analyser, so they move with the song being advertised rather than looping a canned
   animation at it. */
#release {
  display: flex; align-items: center; gap: 16px; position: relative; overflow: hidden;
  width: min(960px, 100%); box-sizing: border-box;
  padding: 10px 18px; border-radius: 12px;
  border: 1px solid color-mix(in srgb, var(--st-color, var(--env-accent)) 42%, var(--line));
  border-left: 3px solid var(--st-color, var(--env-accent));
  background: color-mix(in srgb, var(--panel) 76%, transparent);
  animation: rl-in 0.5s cubic-bezier(0.2, 0.7, 0.2, 1) both;
}
#release[hidden] { display: none; }
@keyframes rl-in { from { opacity: 0; transform: translateY(10px); } }

.rl-bars { display: flex; align-items: flex-end; gap: 3px; height: 22px; flex: none; }
.rl-bars i {
  display: block; width: 3px; height: 4px; border-radius: 1px;
  background: var(--st-color, var(--env-accent));
  transition: height 0.09s linear; will-change: height;
}

.rl-txt { display: flex; flex-direction: column; min-width: 0; flex: 1 1 auto; }
.rl-kicker {
  font-size: 10px; letter-spacing: 0.22em; text-transform: uppercase;
  color: color-mix(in srgb, var(--st-color, var(--env-accent)) 85%, var(--ink));
}
.rl-kicker b { font-weight: 800; letter-spacing: 0.18em; }
.rl-title {
  font-size: 15px; color: var(--ink); font-weight: 600; letter-spacing: 0.01em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* Each door wears its own service's colour rather than the station's. A colour is not a
   trademark, and it is what the eye actually catches at a glance - which is the whole job
   here. The marks themselves belong to the three companies: drop their official badge into
   static/brand/platform/<name>.svg and the button wears that instead of the word, with no
   other change needed. */
.rl-links { display: flex; gap: 7px; flex: none; align-items: stretch; }
/* [hidden] is only display:none at the weight of a bare element selector, so the
   display:inline-flex below beat it and a button with no address still showed - Volume II
   has no public Apple page yet and was offering one anyway. */
.rl-links a[hidden] { display: none; }
.rl-links a {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 11px; letter-spacing: 0.06em; text-transform: uppercase; font-weight: 700;
  color: var(--ink); text-decoration: none; white-space: nowrap;
  padding: 7px 12px; border-radius: 3px;
  border: 1px solid color-mix(in srgb, var(--pc, var(--env-accent)) 60%, var(--line));
  background: color-mix(in srgb, var(--pc, var(--env-accent)) 14%, transparent);
  transition: background 0.18s ease, transform 0.18s ease,
              border-color 0.18s ease, color 0.18s ease;
}
/* the service's own colour, as a dot and as the hover fill */
.rl-links a::before {
  content: ''; width: 9px; height: 9px; border-radius: 50%; flex: none;
  background: var(--pc, var(--env-accent));
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--pc, var(--env-accent)) 28%, transparent);
}
.rl-links a:hover {
  background: var(--pc, var(--env-accent));
  border-color: var(--pc, var(--env-accent));
  color: #0d0e10; transform: translateY(-1px);
}
.rl-links a:hover::before { background: #0d0e10; box-shadow: none; }
#rl-apple { --pc: #fa243c; }
#rl-spotify { --pc: #1db954; }
#rl-youtube { --pc: #ff0033; }

/* when an official badge image is present it replaces the word and the dot entirely,
   unmodified, which is what every one of their brand guides asks for */
.rl-links a.has-badge { padding: 7px 12px; gap: 0; }
.rl-links a.has-badge::before { display: none; }
.rl-links a.has-badge span { display: none; }
/* a mark has to be read at a glance across a room, which eighteen pixels was not */
.rl-links a img.rl-badge { height: 28px; width: auto; display: block; }
.rl-links a.has-badge:hover { background: color-mix(in srgb, var(--pc) 22%, transparent); }

/* one slow pass of light, the way a lit sign catches it */
.rl-sheen {
  position: absolute; inset: 0 auto 0 -40%; width: 34%; pointer-events: none;
  background: linear-gradient(100deg, transparent,
    color-mix(in srgb, var(--st-color, var(--env-accent)) 16%, transparent), transparent);
  animation: rl-sheen 6.5s ease-in-out infinite;
}
@keyframes rl-sheen { 0%, 58% { transform: translateX(0); } 92%, 100% { transform: translateX(420%); } }

@media (max-width: 760px) {
  #release { padding: 8px 12px; gap: 11px; border-radius: 10px; }
  .rl-title { font-size: 14px; }
  .rl-links a { font-size: 10px; padding: 5px 8px; }
  .rl-links a.has-badge { padding: 6px 9px; }
  .rl-links a img.rl-badge { height: 24px; }
  .rl-links { gap: 5px; }
  .rl-bars { height: 18px; }
}
@media (max-width: 460px) {
  .rl-bars { display: none; }          /* the title and the three doors matter more */
  .rl-links a { padding: 5px 7px; letter-spacing: 0.03em; }
  .rl-links a.has-badge { padding: 5px 7px; }
  .rl-links a img.rl-badge { height: 21px; }
}
@media (prefers-reduced-motion: reduce) {
  #release { animation: none; }
  .rl-sheen { display: none; }
  .rl-bars i { transition: none; }
}

/* The now-playing panel on a phone with the tuner put away.

   Those sizes were written for a desktop with the tuner hidden, and they beat the phone
   rules on specificity, so a 168px thumbnail came along to a 390px screen: the panel ate a
   third of the picture and pushed the one thing anybody reads - what is playing - down into
   small print. The art comes down, the type goes up, and the panel sits lighter on the
   footage it is covering. */
@media (max-width: 760px) {
  body.no-rx #np { padding: 9px 12px; gap: 12px; border-radius: 12px;
    background: color-mix(in srgb, var(--panel) 46%, transparent); }
  body.no-rx #np-art { width: 82px; height: 82px; border-radius: 3px;
    box-shadow: 5px 5px 0 color-mix(in srgb, var(--st-color, var(--env-accent)) 80%, #000); }
  body.no-rx #np-art #np-logo { padding: 11px; }
  body.no-rx #np-station { font-size: 16px; }
  body.no-rx #np-station .np-logo-wide { max-height: 32px; }
  body.no-rx #np-track { font-size: 19px; }
  body.no-rx #np-tag { font-size: 12.5px; }
  body.no-rx #np-live { font-size: 10px; letter-spacing: 2px; padding: 5px 9px; }
  body.no-rx #np-live i { width: 7px; height: 7px; }
  body.no-rx #np-wave { display: none; }   /* no room for it beside bigger type */
}

@media (orientation: portrait) and (max-width: 900px) {
  #stage-bg video { object-fit: contain; }   /* matches the base rule's specificity, and comes after it */
  #stage-bg::before {
    content: ''; position: absolute; inset: -8%;
    background-image: var(--scene-poster, none);
    background-size: cover; background-position: center;
    filter: blur(34px) saturate(0.85) brightness(0.5);
    transform: scale(1.1);
    transition: background-image 0.6s ease;
  }
  body.fx-off #stage-bg::before { filter: blur(34px) brightness(0.45); }
}

/* ---------- the logo takes a hint from the picture behind it ----------
   Turned away from whatever hue the scene is sitting on, with a halo that goes dark against a
   bright scene and soft against a dark one. The transition is long on purpose: this should
   never read as the logo flashing, only as it quietly staying legible. */
.brand-disc {
  filter: hue-rotate(var(--logo-rot, 0deg))
          drop-shadow(0 5px 9px rgba(0, 0, 0, calc(0.45 + 0.4 * var(--logo-halo, 0.4))))
          drop-shadow(0 0 14px rgba(0, 0, 0, calc(0.5 * var(--logo-halo, 0.4))));
  transition: filter 1.4s ease;
}
.brand-word b { transition: filter 1.4s ease; filter: hue-rotate(calc(var(--logo-rot, 0deg) * 0.5)); }
body.fx-off .brand-disc { filter: drop-shadow(0 5px 9px rgba(0,0,0,0.65)); }
@media (prefers-reduced-motion: reduce) { .brand-disc, .brand-word b { transition: none; } }
