/* ── tokens ─────────────────────────────────────────────────────────── */
:root{
  --paper:#F3F2EF; --surface:#FFF; --surface-2:#EDECE7; --shell:#20302E;
  --ink:#17211F; --ink-2:#4A5754; --ink-3:#7A8683;
  --rule:#D8D8D1; --rule-soft:#E6E5DF;
  --signal:#0B7B72; --signal-dim:#0B7B7214;
  --dial:#B0602F; --dial-dim:#B0602F14;
  --crit:#A63A2E;
  --tile:#F7F7F4;
  --display:"Familjen Grotesk","Helvetica Neue",Arial,sans-serif;
  --body:"Newsreader",Georgia,serif;
  --mono:"IBM Plex Mono",ui-monospace,Menlo,monospace;
  --player-h:150px; /* pre-JS reserve; app.js replaces it with the measured height */
}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]){
  --paper:#101817; --surface:#16201F; --surface-2:#1D2827; --shell:#0A1211;
  --ink:#E8E9E5; --ink-2:#A6B2AF; --ink-3:#76817E;
  --rule:#2C3735; --rule-soft:#232E2C;
  --signal:#4FBDAF; --signal-dim:#4FBDAF1A;
  --dial:#D98A55; --dial-dim:#D98A5518;
  --crit:#DE7A6B;
  --tile:#E9E9E4;
}}
:root[data-theme="dark"]{
  --paper:#101817; --surface:#16201F; --surface-2:#1D2827; --shell:#0A1211;
  --ink:#E8E9E5; --ink-2:#A6B2AF; --ink-3:#76817E;
  --rule:#2C3735; --rule-soft:#232E2C;
  --signal:#4FBDAF; --signal-dim:#4FBDAF1A;
  --dial:#D98A55; --dial-dim:#D98A5518;
  --crit:#DE7A6B;
  --tile:#E9E9E4;
}

*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{margin:0;background:var(--paper);color:var(--ink);font:16px/1.6 var(--body);
  -webkit-font-smoothing:antialiased;padding-bottom:calc(var(--player-h) + env(safe-area-inset-bottom))}
a{color:var(--signal);text-underline-offset:2px}
:focus-visible{outline:2px solid var(--signal);outline-offset:2px}
button{font:inherit;cursor:pointer}
.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
.shell{max-width:78rem;margin:0 auto;padding:0 1rem}
svg{display:block}

/* ── header ─────────────────────────────────────────────────────────── */
.top{position:sticky;top:0;z-index:40;background:color-mix(in srgb,var(--paper) 92%,transparent);
  backdrop-filter:blur(10px);border-bottom:1px solid var(--rule)}
.top-in{display:flex;align-items:center;gap:.7rem;padding-block:.55rem}
.brand{display:flex;align-items:center;gap:.45rem;font-family:var(--display);font-weight:700;
  font-size:1rem;letter-spacing:-.02em;color:var(--ink);text-decoration:none;flex:0 0 auto}
.brand .tick{width:11px;height:20px;border-left:2px solid var(--signal);
  background-image:repeating-linear-gradient(to bottom,var(--rule) 0 1px,transparent 1px 5px)}
.brand span.txt{display:none}
@media(min-width:30rem){.brand span.txt{display:inline}}
form.search{flex:1 1 auto;min-width:0}
form.search input{width:100%;padding:.42rem .8rem;border:1px solid var(--rule);border-radius:999px;
  background:var(--surface);color:var(--ink);font:inherit;font-size:.92rem}
form.search input::placeholder{color:var(--ink-3)}
.iconctl{flex:0 0 auto;background:var(--surface);border:1px solid var(--rule);border-radius:999px;
  width:32px;height:32px;color:var(--ink-2);display:grid;place-items:center;padding:0}
.iconctl svg{width:15px;height:15px}

/* ── #4 compact filter bar: one row of selects, not two chip rows ──── */
.fbar{border-bottom:1px solid var(--rule);background:var(--surface)}
.fbar-in{display:flex;align-items:center;gap:.4rem;padding-block:.4rem;flex-wrap:wrap}
.fsel{position:relative;display:inline-flex;align-items:center;flex:0 0 auto}
.fsel select{appearance:none;font-family:var(--display);font-weight:500;font-size:.79rem;
  border:1px solid var(--rule);border-radius:5px;padding:.26rem 1.4rem .26rem .5rem;
  background:var(--paper);color:var(--ink-2);max-width:8.5rem;text-overflow:ellipsis}
@media(min-width:34rem){.fsel select{max-width:12rem}}
.fsel::after{content:"";position:absolute;right:.45rem;pointer-events:none;
  width:0;height:0;border:3.5px solid transparent;border-top-color:var(--ink-3);margin-top:3px}
.fsel[data-on="1"] select{border-color:var(--signal);background:var(--signal-dim);color:var(--signal);font-weight:600}
.fsel[data-on="1"]::after{border-top-color:var(--signal)}
/* The right-hand cluster travels as one and never splits. */
.fbar-right{display:flex;align-items:center;gap:.4rem;flex:0 0 auto;margin-left:auto}
.fcount{font-family:var(--mono);font-size:.64rem;letter-spacing:.06em;color:var(--ink-3);
  white-space:nowrap;font-variant-numeric:tabular-nums}
.clearf{font-family:var(--mono);font-size:.64rem;letter-spacing:.06em;text-transform:uppercase;
  color:var(--ink-3);background:none;border:0;padding:.2rem .3rem;text-decoration:underline}

/* #11 favourites lifted out of the filter row, in copper */
.favlink{display:inline-flex;align-items:center;gap:.35rem;flex:0 0 auto;text-decoration:none;
  font-family:var(--display);font-weight:600;font-size:.78rem;border:1px solid var(--dial);
  color:var(--dial);background:var(--dial-dim);border-radius:5px;padding:.24rem .55rem}
.favlink svg{width:12px;height:12px}
.favlink b{font-family:var(--mono);font-size:.68em;font-weight:600;opacity:.8}
.favlink[aria-current="page"]{background:var(--dial);color:var(--paper)}

/* ── active filters ─────────────────────────────────────────────────── */
.active{display:flex;align-items:center;flex-wrap:wrap;gap:.35rem;margin:1rem 0 0}
.active-lbl{font-family:var(--mono);font-size:.6rem;letter-spacing:.11em;text-transform:uppercase;
  color:var(--ink-3);margin-right:.1rem}
.active-or{font-family:var(--mono);font-size:.6rem;letter-spacing:.08em;text-transform:uppercase;
  color:var(--ink-3)}
.achip{display:inline-flex;align-items:center;gap:.4rem;text-decoration:none;
  font-family:var(--display);font-weight:600;font-size:.76rem;
  border:1px solid var(--signal);background:var(--signal-dim);color:var(--signal);
  border-radius:999px;padding:.2rem .5rem .2rem .6rem}
.achip span{font-size:1rem;line-height:1;opacity:.65;margin-top:-1px}
.achip:hover{background:var(--signal);color:#fff}
.achip:hover span{opacity:1}
.active-clear{font-family:var(--mono);font-size:.62rem;letter-spacing:.06em;text-transform:uppercase;
  color:var(--ink-3);margin-left:.2rem}

/* ── feature hint ────────────────────────────────────────────────────────
   The sleep timer, favourites and the dial are all easy to miss. One rotating
   line, dismissible, remembered — cheap discovery without a tour. */
.hint{display:flex;align-items:flex-start;gap:.55rem;background:var(--surface);
  border:1px solid var(--rule);border-left:3px solid var(--dial);border-radius:9px;
  padding:.55rem .7rem;margin:1rem 0 0;font-size:.88rem;color:var(--ink-2);max-width:46rem}
.hint[hidden]{display:none}
.hint svg{width:14px;height:14px;flex:0 0 auto;color:var(--dial);margin-top:.15rem}
.hint b{font-family:var(--display);font-weight:600;color:var(--ink)}
.hint-x{margin-left:auto;background:none;border:0;color:var(--ink-3);font-size:1rem;
  line-height:1;padding:0 .1rem;flex:0 0 auto}
.hint-x:hover{color:var(--ink)}

/* ── recent genres: quick repeats in the filter bar's open space ────── */
.recents{display:none;align-items:center;gap:.3rem;
  /* The only flexible thing in the row, so it is what gives way. A fade on the
     trailing edge makes the clip read as deliberate rather than broken. */
  flex:1 1 0;min-width:0;overflow:hidden;flex-wrap:nowrap;
  mask-image:linear-gradient(to right,#000 calc(100% - 22px),transparent 100%)}
.recents[hidden]{display:none}
@media (min-width:64rem){
  .recents:not([hidden]){display:flex}
  /* A wrapping row moves an item to the next line before it will shrink one,
     which is what put Favourites underneath. With nowrap, the recents clip
     instead and everything else keeps its place. */
  .fbar-in{flex-wrap:nowrap}
}
.recents .rlbl{font-family:var(--mono);font-size:.58rem;letter-spacing:.11em;text-transform:uppercase;
  color:var(--ink-3);margin-right:.05rem}
.rchip{font-family:var(--display);font-weight:600;font-size:.72rem;text-decoration:none;
  border:1px solid var(--rule-soft);border-radius:999px;padding:.16rem .5rem;
  color:var(--ink-2);background:var(--paper);white-space:nowrap;flex:0 0 auto;
  max-width:11rem;overflow:hidden;text-overflow:ellipsis}
.rchip:hover{border-color:var(--signal);color:var(--signal);background:var(--signal-dim)}
.rchip[aria-current="true"]{background:var(--signal);border-color:var(--signal);color:#fff}

/* ── layout: optional desktop rail beside the content ───────────────── */
.layout{display:block}
/* The content column wraps the hint and <main> so they stay in one grid cell;
   as separate children the hint took the column and pushed main to a new row. */
.col{min-width:0}
.rail{display:none}
@media (min-width:68rem){
  .layout{display:grid;grid-template-columns:13.5rem minmax(0,1fr);gap:1.6rem;align-items:start}
  .rail{display:block;position:sticky;top:4.6rem;padding:1.2rem 0 1rem;
    max-height:calc(100vh - 6rem);overflow-y:auto;scrollbar-width:thin}
}
.railgrp{display:flex;flex-direction:column;gap:1px;margin:0 0 1.1rem}
.railhd{font-family:var(--mono);font-size:.58rem;font-weight:600;letter-spacing:.12em;
  text-transform:uppercase;color:var(--ink-3);margin:0 0 .35rem;padding-left:.5rem}
.raili{display:flex;align-items:center;gap:.45rem;text-decoration:none;color:var(--ink-2);
  font-family:var(--display);font-weight:500;font-size:.82rem;border-radius:7px;
  padding:.34rem .5rem;transition:background .15s ease,color .15s ease}
.raili svg{width:13px;height:13px;flex:0 0 auto;opacity:.65}
.raili .railtxt{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.raili .railn{font-family:var(--mono);font-size:.62rem;font-weight:600;color:var(--ink-3);
  font-variant-numeric:tabular-nums;flex:0 0 auto;margin-left:auto}
.raili:hover{background:var(--surface);color:var(--ink)}
.raili.on{background:var(--signal-dim);color:var(--signal)}
.raili.on svg{opacity:1}
.raili.on .railn{color:var(--signal)}
.railclear{color:var(--ink-3);font-weight:400;font-size:.76rem}

/* ── first-run / misconfiguration notices ───────────────────────────── */
.setup{background:var(--surface);border:1px solid var(--rule);border-left:3px solid var(--dial);
  border-radius:10px;padding:1.2rem 1.3rem;margin:0 0 1.6rem;max-width:44rem}
.setup h2{font-family:var(--display);font-weight:600;font-size:1.1rem;margin:0 0 .5rem}
.setup p{margin:.6rem 0 0;color:var(--ink-2);font-size:.95rem;max-width:none}
.setup pre{font-family:var(--mono);font-size:.82rem;background:var(--surface-2);
  border:1px solid var(--rule-soft);border-radius:6px;padding:.6rem .8rem;margin:.7rem 0;overflow-x:auto}
.setup code,.setup-warn code{font-family:var(--mono);font-size:.85em;background:var(--surface-2);
  border:1px solid var(--rule-soft);border-radius:3px;padding:.06em .3em}
.setup-warn{color:var(--crit)}
.setup-banner{background:var(--surface);border:1px solid var(--crit);border-radius:8px;
  padding:.7rem .9rem;margin:1rem 0 0;font-size:.9rem;max-width:none}

/* ── page head ──────────────────────────────────────────────────────── */
h1.page{font-family:var(--display);font-weight:700;font-size:clamp(1.4rem,4vw,1.9rem);
  letter-spacing:-.025em;margin:1.2rem 0 .15rem;text-wrap:balance}
.lede{color:var(--ink-2);margin:0 0 1rem;max-width:62ch;font-size:.95rem}

/* ── listing ────────────────────────────────────────────────────────
   Two views off one markup. `grid` stacks a square logo tile, the name, then
   a footer of bitrate + actions. `list` turns both wrappers into
   display:contents so logo / name / meta / actions become one row on the box.

   Logo tiles keep a light ground in both themes and use object-fit:contain,
   because station artwork is overwhelmingly a dark wordmark drawn for white —
   `cover` crops it and a dark tile erases it. */
.panel{display:grid;gap:.6rem;margin:0 0 1.6rem;padding:0;list-style:none}
.panel[data-view="grid"]{grid-template-columns:repeat(auto-fill,minmax(min(100%,8.5rem),1fr))}
@media(min-width:34rem){.panel[data-view="grid"]{grid-template-columns:repeat(auto-fill,minmax(min(100%,10.5rem),1fr))}}
.panel[data-view="list"]{grid-template-columns:repeat(auto-fill,minmax(min(100%,20.5rem),1fr));gap:.55rem}

.box{container-type:inline-size;position:relative;width:100%;text-align:left;
  background:var(--surface);border:1px solid var(--rule-soft);border-radius:12px;
  color:var(--ink);box-shadow:0 1px 2px rgba(23,33,31,.05);
  transition:box-shadow .18s ease,border-color .18s ease,transform .18s ease}
.box:hover{border-color:var(--rule);box-shadow:0 5px 18px rgba(23,33,31,.1);transform:translateY(-2px)}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]) .box{box-shadow:0 1px 2px rgba(0,0,0,.3)}
  :root:not([data-theme="light"]) .box:hover{box-shadow:0 5px 20px rgba(0,0,0,.45)}}
:root[data-theme="dark"] .box{box-shadow:0 1px 2px rgba(0,0,0,.3)}
:root[data-theme="dark"] .box:hover{box-shadow:0 5px 20px rgba(0,0,0,.45)}
.box[data-playing="true"]{border-color:var(--signal);
  box-shadow:0 0 0 1px var(--signal),0 5px 18px color-mix(in srgb,var(--signal) 24%,transparent)}
.box[data-playing="true"] .nm{color:var(--signal)}

.play-hit{font:inherit;color:inherit;text-align:left;background:none;border:0;padding:0}

.logo{position:relative;background:var(--tile);display:grid;place-items:center;
  overflow:hidden;flex:0 0 auto;isolation:isolate}
.logo img{width:100%;height:100%;object-fit:contain;display:block;grid-area:1/1}

/* Missing artwork gets the note glyph on the same tile ground every other
   thumbnail uses. A tinted per-station ground read as a different design
   sitting next to real logos, so it went. */
.artnote{grid-area:1/1;width:38%;height:38%;color:var(--ink-3);opacity:.42}

/* Play badge, after the radioindia.in pattern: a large arrow in a translucent
   ring, no scrim over the artwork. The ring carries its own shadow so it holds
   on light logos as well as dark ones. */
.playbadge{position:absolute;inset:0;display:grid;place-items:center;z-index:3;
  opacity:0;transition:opacity .16s ease;pointer-events:none}
.pbring{width:40%;aspect-ratio:1;max-width:62px;min-width:24px;border-radius:50%;
  display:grid;place-items:center;
  /* Flat translucent white, no backdrop-filter: the blur smeared the artwork
     behind the ring and read as an out-of-focus photo. A dark glyph keeps it
     legible on pale logos, where white-on-white disappeared. */
  background:rgba(255,255,255,.82);
  box-shadow:0 2px 12px rgba(12,25,23,.28)}
.pbring svg{width:42%;height:42%;color:#17211F;transform:translateX(6%)}
.box:hover .pbring{background:rgba(255,255,255,.95)}
@media (hover:hover){
  .box:hover .playbadge,
  .detail-art:hover .playbadge,
  .play-hit:focus-visible .playbadge{opacity:1}
}
/* Nothing reveals it on touch, so keep it visible but a touch softer. */
@media (hover:none){ .playbadge{opacity:.92} }
.box[data-playing="true"] .playbadge,
.detail-art[data-playing="true"] .playbadge{opacity:0!important}

/* Equaliser in the thumbnail — sized down to ~55% of the first pass, which
   was loud enough to distract from the artwork. */
.eq{position:absolute;inset:0;z-index:4;display:none;align-items:flex-end;justify-content:center;
  gap:6%;padding:38% 39% 34%;background:color-mix(in srgb, #0C1917 34%, transparent)}
.box[data-playing="true"] .eq,
.detail-art[data-playing="true"] .eq{display:flex}
.eq i{flex:1 1 0;min-width:2px;max-width:4px;border-radius:2px;background:#fff;
  transform-origin:bottom;box-shadow:0 0 6px color-mix(in srgb,var(--signal) 60%,transparent);
  animation:eqbar .85s ease-in-out infinite}
.eq i:nth-child(1){height:42%;animation-delay:-.62s}
.eq i:nth-child(2){height:88%;animation-delay:-.31s}
.eq i:nth-child(3){height:62%;animation-delay:-.47s}
.eq i:nth-child(4){height:100%}
@keyframes eqbar{0%,100%{transform:scaleY(.28)}50%{transform:scaleY(1)}}
@media (prefers-reduced-motion:reduce){.eq i{animation:none;transform:scaleY(.75)}}

.nm{font-family:var(--display);font-weight:600;color:inherit;display:block}
.mt{font-family:var(--mono);letter-spacing:.04em;text-transform:uppercase;color:var(--ink-3);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0;display:block}
.acts{display:flex;gap:.25rem;align-items:center;flex:0 0 auto}
.abtn{display:inline-flex;align-items:center;gap:.3rem;border:1px solid var(--rule-soft);
  border-radius:7px;background:var(--paper);color:var(--ink-3);text-decoration:none;
  font-family:var(--display);font-weight:600;font-size:.68rem;line-height:1;
  transition:color .15s ease,border-color .15s ease,background .15s ease}
.abtn svg{width:12px;height:12px;flex:0 0 auto}
.abtn .lbl{display:none}
.abtn:hover{border-color:var(--signal);color:var(--signal);background:var(--signal-dim)}
.abtn.fav[aria-pressed="true"]{color:var(--dial);border-color:color-mix(in srgb,var(--dial) 40%,transparent);
  background:var(--dial-dim)}
.abtn.fav[aria-pressed="true"]:hover{border-color:var(--dial);color:var(--dial);background:var(--dial-dim)}

/* ── grid view: big tile, name under, info footer ── */
.panel[data-view="grid"] .box{display:flex;flex-direction:column;overflow:hidden}
.panel[data-view="grid"] .play-hit{display:flex;flex-direction:column;width:100%}
.panel[data-view="grid"] .logo{width:100%;aspect-ratio:1;border-bottom:1px solid var(--rule-soft)}
.panel[data-view="grid"] .logo img{padding:9%}
.panel[data-view="grid"] .nm{font-size:.82rem;line-height:1.25;padding:.5rem .55rem .1rem;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;min-height:2.6em}
.panel[data-view="grid"] .foot{display:flex;align-items:center;justify-content:space-between;
  gap:.3rem;margin-top:auto;padding:.1rem .45rem .45rem}
.panel[data-view="grid"] .mt-full{display:none}
.panel[data-view="grid"] .mt-short{font-size:.58rem}
.panel[data-view="grid"] .abtn{padding:.24rem .3rem}

/* ── list view: the horizontal row ── */
.panel[data-view="list"] .box{display:grid;grid-template-columns:auto minmax(0,1fr) auto;
  grid-template-areas:"logo name acts" "logo meta acts";column-gap:.65rem;
  align-items:center;padding:.6rem .65rem}
.panel[data-view="list"] .play-hit,
.panel[data-view="list"] .foot{display:contents}
.panel[data-view="list"] .logo{grid-area:logo;width:42px;height:42px;border-radius:9px}
.panel[data-view="list"] .logo img{padding:8%}
.panel[data-view="list"] .artnote{width:52%;height:52%}
.panel[data-view="list"] .eq{padding:22% 24%;gap:8%}
.panel[data-view="list"] .eq i{max-width:3px;box-shadow:none}
.panel[data-view="list"] .nm{grid-area:name;font-size:.9rem;line-height:1.25;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding-right:1.2rem}
.panel[data-view="list"] .mt-short{display:none}
.panel[data-view="list"] .mt-full{grid-area:meta;font-size:.6rem;margin-top:.15rem}
.panel[data-view="list"] .acts{grid-area:acts}
.panel[data-view="list"] .abtn{padding:.28rem .45rem}
/* The label is only worth its width when the card has room — ask the card,
   not the viewport. */
@container (min-width:19rem){.panel[data-view="list"] .abtn .lbl{display:inline}}

/* ── view switch ── */
.viewsw{display:inline-flex;gap:1px;border:1px solid var(--rule);border-radius:6px;
  overflow:hidden;flex:0 0 auto;background:var(--rule)}
.viewsw button{background:var(--paper);border:0;color:var(--ink-3);padding:.22rem .34rem;
  display:grid;place-items:center;line-height:1}
.viewsw button svg{width:13px;height:13px}
.viewsw button[aria-pressed="true"]{background:var(--signal);color:#fff}

.empty{border:1px dashed var(--rule);border-radius:12px;padding:2.2rem 1rem;text-align:center;color:var(--ink-2)}
.morebtn{display:block;margin:0 auto 1.6rem;font-family:var(--display);font-weight:600;font-size:.85rem;
  border:1px solid var(--rule);background:var(--surface);color:var(--ink-2);border-radius:9px;
  padding:.5rem 1.2rem;box-shadow:0 1px 2px rgba(23,33,31,.05)}
.morebtn:hover{border-color:var(--signal);color:var(--signal)}

/* ── #7 detail page ─────────────────────────────────────────────────── */
.detail{display:grid;grid-template-columns:auto minmax(0,1fr);gap:1rem;align-items:start;
  background:var(--surface);border:1px solid var(--rule);border-radius:6px;padding:1rem;margin:1.2rem 0 1.6rem}
.detail-art{width:104px;flex:0 0 auto;border-radius:11px;overflow:hidden;padding:0}
.detail-art .play-hit{display:block;width:100%}
.detail-art .logo{width:100%;aspect-ratio:1;border-radius:0}
.detail-art .logo img{padding:8%}
.detail-np{font-size:.92rem;color:var(--signal);margin:.35rem 0 0;font-weight:500;
  display:flex;align-items:center;gap:.4rem}
.detail-np[hidden]{display:none}
.detail-np::before{content:"";width:6px;height:6px;border-radius:50%;background:var(--signal);flex:0 0 auto}
.detail h1{font-family:var(--display);font-weight:700;font-size:clamp(1.3rem,3.6vw,1.8rem);
  letter-spacing:-.02em;margin:0 0 .3rem;line-height:1.15;text-wrap:balance}
.dbtns{display:flex;gap:.4rem;flex-wrap:wrap;margin:.6rem 0 0}
.dbtn{display:inline-flex;align-items:center;gap:.4rem;font-family:var(--display);font-weight:600;
  font-size:.82rem;border:1px solid var(--rule);background:var(--paper);color:var(--ink);
  border-radius:5px;padding:.35rem .75rem;text-decoration:none}
.dbtn svg{width:12px;height:12px}
.dbtn.primary{background:var(--signal);border-color:var(--signal);color:#fff}
.dbtn.copper[aria-pressed="true"]{background:var(--dial);border-color:var(--dial);color:#fff}
.facts{display:grid;grid-template-columns:repeat(auto-fit,minmax(8.5rem,1fr));gap:1px;
  background:var(--rule);border:1px solid var(--rule);border-radius:5px;overflow:hidden;margin:0 0 1.6rem}
.fact{background:var(--surface);padding:.5rem .7rem}
.fact dt{font-family:var(--mono);font-size:.58rem;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3)}
.fact dd{font-family:var(--display);font-weight:600;font-size:.9rem;margin:.15rem 0 0;
  overflow-wrap:anywhere;font-variant-numeric:tabular-nums}
.tagrow{display:flex;gap:.3rem;flex-wrap:wrap;margin:0 0 1.6rem}
.tagrow a{font-family:var(--mono);font-size:.66rem;letter-spacing:.04em;text-decoration:none;
  border:1px solid var(--rule);border-radius:999px;padding:.15rem .5rem;color:var(--ink-2);background:var(--surface)}
.tagrow a:hover{border-color:var(--signal);color:var(--signal)}
h2.sec{font-family:var(--display);font-weight:600;font-size:1.02rem;letter-spacing:-.01em;
  margin:0 0 .5rem;padding-bottom:.3rem;border-bottom:1px solid var(--rule)}

/* ── player ─────────────────────────────────────────────────────────── */
.player{position:fixed;inset:auto 0 0 0;z-index:50;background:var(--shell);color:#EDEBE4;
  border-top:1px solid var(--rule);padding-bottom:env(safe-area-inset-bottom)}
.player-in{max-width:78rem;margin:0 auto;padding:.45rem 1rem .55rem}

/* #10 station logo in the bottom bar */
.np{display:grid;grid-template-columns:auto minmax(0,1fr);gap:.7rem;align-items:center}
.np-art{position:relative;flex:0 0 auto;display:block}
.np-logo{width:38px;height:38px;border-radius:4px;
  background:rgba(237,235,228,.08);border:1px solid rgba(237,235,228,.14);
  display:grid;place-items:center;overflow:visible;
  font-family:var(--display);font-weight:700;font-size:.7rem;color:rgba(237,235,228,.65)}
.np-logo img{border-radius:3px}

/* Status light on the thumbnail — always visible, no words needed. */
.np-dot{position:absolute;right:-3px;bottom:-3px;width:10px;height:10px;border-radius:50%;
  border:2px solid var(--shell);background:rgba(237,235,228,.45);z-index:2}
.player[data-state="playing"] .np-dot{background:var(--signal);
  box-shadow:0 0 0 0 color-mix(in srgb,var(--signal) 60%,transparent);animation:dotpulse 2.4s ease-out infinite}
.player[data-state="loading"] .np-dot{background:#C6A24E;animation:pulse 1s ease-in-out infinite}
.player[data-state="error"] .np-dot{background:var(--crit)}
@keyframes dotpulse{
  0%{box-shadow:0 0 0 0 color-mix(in srgb,var(--signal) 55%,transparent)}
  70%,100%{box-shadow:0 0 0 6px transparent}
}
@media (prefers-reduced-motion:reduce){.np-dot{animation:none!important}}
.np-logo img{width:100%;height:100%;object-fit:cover;display:block}
.np-txt{min-width:0}
.np-live{font-family:var(--mono);font-size:.55rem;letter-spacing:.13em;text-transform:uppercase;
  color:var(--signal);display:inline-flex;align-items:center;gap:.4em;flex:0 0 auto}
.np-live-txt{white-space:nowrap}

/* Live bars rather than a static dot: the movement is the point, it is the
   one thing on the bar that says audio is actually flowing. */
.np-eq{display:inline-flex;align-items:flex-end;gap:1.5px;height:9px;width:11px}
.np-eq i{flex:1 1 0;border-radius:1px;background:currentColor;transform-origin:bottom;height:100%}
.player[data-state="playing"] .np-eq i{animation:eqbar .8s ease-in-out infinite}
.np-eq i:nth-child(1){animation-delay:-.55s}
.np-eq i:nth-child(2){animation-delay:-.27s}
.player:not([data-state="playing"]) .np-eq i:nth-child(1){height:40%}
.player:not([data-state="playing"]) .np-eq i:nth-child(2){height:70%}
.player:not([data-state="playing"]) .np-eq i:nth-child(3){height:50%}
.player[data-state="loading"] .np-eq{animation:pulse 1s ease-in-out infinite}
.player[data-state="error"] .np-live{color:var(--crit)}
.player[data-state="idle"] .np-live{color:rgba(237,235,228,.5)}
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.25}}
@media (prefers-reduced-motion:reduce){.np-eq i{animation:none!important}}
/* Second line holds the status until a track title arrives, then the title
   takes it over — the wording is only useful while there is nothing better. */
.np-second{display:flex;align-items:baseline;gap:.5rem;min-width:0}
.player[data-has-track="true"] .np-live{display:none}
.np-name{display:block;font-family:var(--display);font-weight:700;font-size:.98rem;
  letter-spacing:-.015em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.np-name a{color:inherit;text-decoration:none}
.np-name a:hover{text-decoration:underline}
/* The track title gets a fixed slice of the bar and scrolls inside it when it
   is too long. Both this and .np-name are spans, so they need display:block —
   an inline element ignores overflow entirely, which is what let a long title
   bleed 300px across the dial. */
.np-track{display:block;font-size:.8rem;opacity:.72;min-height:1.15em;margin:.03rem 0 0;
  overflow:hidden;white-space:nowrap;position:relative;
  mask-image:linear-gradient(to right,transparent 0,#000 6px,#000 calc(100% - 10px),transparent 100%)}
.np-track:not(.scrolls){text-overflow:ellipsis;mask-image:none}
.np-track .roll{display:inline-block;white-space:nowrap}
.np-track.scrolls .roll{animation:roll var(--roll-dur,14s) linear infinite alternate}
@keyframes roll{
  0%, 10%   {transform:translateX(0)}
  90%, 100% {transform:translateX(var(--roll-shift,0px))}
}
@media (prefers-reduced-motion:reduce){
  .np-track.scrolls{mask-image:none;text-overflow:ellipsis}
  .np-track.scrolls .roll{animation:none}
}

/* the tuning dial — #9 same order as the listing */
.dial{position:relative;margin:.3rem 0 .05rem}
.dial-ticks{height:10px;background-image:repeating-linear-gradient(to right,
  rgba(237,235,228,.22) 0 1px,transparent 1px 9px)}
.needle{position:absolute;left:50%;top:-3px;bottom:-5px;width:2px;background:var(--dial);
  transform:translateX(-50%);z-index:2;pointer-events:none}
.needle::after{content:"";position:absolute;top:-3px;left:-3px;width:8px;height:8px;border-radius:50%;background:var(--dial)}
.strip{display:flex;gap:.45rem;overflow-x:auto;scroll-snap-type:x mandatory;
  padding:.45rem calc(50% - 2.6rem);scrollbar-width:none}
.strip::-webkit-scrollbar{display:none}
.dot{flex:0 0 5.2rem;scroll-snap-align:center;border-radius:6px;padding:.3rem .3rem;
  background:rgba(237,235,228,.08);border:1px solid rgba(237,235,228,.12);color:#EDEBE4;
  display:grid;grid-template-columns:auto minmax(0,1fr);gap:.3rem;align-items:center;
  transition:transform .18s ease,background .18s ease,border-color .18s ease}
.dot-lg{position:relative;width:20px;height:20px;border-radius:3px;
  background:rgba(237,235,228,.1);overflow:hidden;display:grid;place-items:center;
  font-family:var(--display);font-weight:700;font-size:.5rem;opacity:.8}
.dot-lg img{width:100%;height:100%;object-fit:cover;display:block}
.dot b{font-family:var(--display);font-weight:600;font-size:.63rem;line-height:1.15;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-align:left}
.dot[aria-current="true"]{background:var(--signal);border-color:var(--signal);color:#fff;transform:scale(1.06)}
.dot[aria-current="true"] .dot-lg{background:rgba(255,255,255,.18);opacity:1}

.transport{display:grid;grid-template-columns:1fr auto 1fr;align-items:center;
  gap:.75rem;padding:.1rem 0 0}
.tzone{display:flex;align-items:center;gap:.75rem;min-width:0}
.tzone--left{justify-content:flex-end}
.tzone--right{justify-content:flex-start}
.tbtn{background:none;border:0;color:#EDEBE4;opacity:.78;padding:.3rem;display:grid;place-items:center}
.tbtn svg{width:16px;height:16px}
.tbtn:hover{opacity:1}
.tbtn[disabled]{opacity:.28;cursor:not-allowed}
.tbtn--main{background:var(--signal);color:#fff;width:2.5rem;height:2.5rem;border-radius:50%;opacity:1}
.tbtn--main svg{width:14px;height:14px}
.tbtn--fav[aria-pressed="true"]{color:var(--dial);opacity:1}
.tbtn--sleep[aria-pressed="true"]{color:var(--dial);opacity:1}
/* A depleting ring around the minutes left, rather than a bare number — it
   reads as a countdown at a glance. */
.sleepring{position:relative;display:grid;place-items:center;width:20px;height:20px}
.sleepring svg{position:absolute;inset:0;width:100%;height:100%;transform:rotate(-90deg)}
.sleepring circle{fill:none;stroke-width:2.6}
.sleepring .ring-bg{stroke:rgba(237,235,228,.22)}
.sleepring .ring-fg{stroke:var(--dial);stroke-linecap:round;transition:stroke-dashoffset .6s linear}
.sleepnum{position:relative;font-family:var(--mono);font-size:.52rem;font-weight:600;
  letter-spacing:0;line-height:1;color:var(--dial)}

/* custom duration */
.sleepcustom{display:flex;align-items:center;gap:.3rem;padding:.35rem 0 0;justify-content:center;
  border-top:1px solid rgba(237,235,228,.14);margin-top:.35rem}
.sleepcustom input{width:3.4rem;background:rgba(237,235,228,.08);color:#EDEBE4;
  border:1px solid rgba(237,235,228,.2);border-radius:6px;padding:.18rem .35rem;
  font-family:var(--mono);font-size:.66rem;text-align:center}
.sleepcustom input::-webkit-outer-spin-button,
.sleepcustom input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.sleepcustom input[type=number]{-moz-appearance:textfield}
.sleepcustom label{font-family:var(--mono);font-size:.58rem;letter-spacing:.08em;
  text-transform:uppercase;color:rgba(237,235,228,.6)}
.sleepcustom button{background:var(--dial);border:1px solid var(--dial);color:#fff;
  border-radius:6px;font-family:var(--display);font-weight:600;font-size:.66rem;
  padding:.2rem .55rem;opacity:1}

/* #6 volume popover */
.volwrap{position:relative;display:inline-grid}
.volpop{position:absolute;bottom:calc(100% + .45rem);left:50%;transform:translateX(-50%);
  background:var(--shell);border:1px solid rgba(237,235,228,.2);border-radius:8px;
  padding:.55rem .6rem;display:flex;align-items:center;gap:.45rem;box-shadow:0 6px 20px rgba(0,0,0,.3)}
.volpop[hidden]{display:none}
.volpop input[type=range]{appearance:none;width:7.5rem;height:4px;border-radius:4px;background:rgba(237,235,228,.25)}
.volpop input[type=range]::-webkit-slider-thumb{appearance:none;width:13px;height:13px;border-radius:50%;
  background:var(--signal);border:2px solid var(--shell);cursor:pointer}
.volpop input[type=range]::-moz-range-thumb{width:13px;height:13px;border:2px solid var(--shell);
  border-radius:50%;background:var(--signal);cursor:pointer}
.volpct{font-family:var(--mono);font-size:.6rem;color:rgba(237,235,228,.7);
  min-width:2.2rem;text-align:right;font-variant-numeric:tabular-nums}

.sleepmenu{display:flex;gap:.3rem;justify-content:center;padding:.25rem 0 0;flex-wrap:wrap}
.sleepmenu[hidden]{display:none}
.sleepmenu button{background:none;border:1px solid rgba(237,235,228,.18);color:#EDEBE4;
  border-radius:999px;font-family:var(--mono);font-size:.6rem;letter-spacing:.06em;padding:.18rem .5rem;opacity:.8}
.sleepmenu button:hover{opacity:1;border-color:var(--dial)}

@media (min-width:60rem){
  .player-in{display:grid;grid-template-columns:minmax(0,19rem) minmax(0,1fr) auto;
    grid-template-areas:"np dial transport";align-items:center;gap:1.1rem}
  .np{grid-area:np}
  .dial{grid-area:dial;margin:0}
  .transport{grid-area:transport;padding:0}
  /* On desktop the transport sits in an auto-width column, so the 1fr zones
     size to their content and the heavier right-hand side pushes play off
     centre. A shared minimum evens them out. */
  .tzone{min-width:7.5rem}
  .sleepmenu{position:absolute;right:1rem;bottom:calc(100% + .4rem);background:var(--shell);
    border:1px solid rgba(237,235,228,.2);border-radius:10px;padding:.5rem}
}
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important;scroll-behavior:auto!important}}
