/* Filter Club — shared styles */

:root{
  --bg:#0b0c10;
  --panel:rgba(255,255,255,.035);
  --panel-hi:rgba(255,255,255,.062);
  --ink:#f2f3f5;
  --dim:#8b8f9a;
  --dimmer:#5c606b;
  --line:rgba(255,255,255,.09);
  --accent:#8b6bff;          /* violet */
  --accent-soft:rgba(139,107,255,.16);
  --pink:#ff5c8a;
  --pink-soft:rgba(255,92,138,.15);
  --font:'DM Sans',-apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;
  --maxw:1080px;
}

*{box-sizing:border-box;margin:0;padding:0}
/* present for screen readers and crawlers, not painted */
.sronly{position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
html{scroll-behavior:smooth}
body{
  background:var(--bg);
  color:var(--ink);
  font-family:var(--font);
  font-size:16px;
  line-height:1.62;
  -webkit-font-smoothing:antialiased;
  min-height:100vh;
  display:flex;
  flex-direction:column;
}

/* ---------- background: warm haze + grain (no grid) ---------- */
.bg,.grain{position:fixed;inset:0;z-index:0;pointer-events:none}
.bg::before{
  content:"";position:absolute;inset:-30%;
  background:
    radial-gradient(50vw 50vw at 10% 0%,   rgba(109,75,255,.30), transparent 62%),
    radial-gradient(46vw 46vw at 96% 18%,  rgba(255,92,138,.18), transparent 62%),
    radial-gradient(64vw 44vw at 46% 108%, rgba(255,157,77,.14), transparent 66%);
  filter:blur(12px);
}
.grain{
  opacity:.05;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='140'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3'/></filter><rect width='140' height='140' filter='url(%23n)'/></svg>");
}

.wrap{position:relative;z-index:1;width:100%;max-width:var(--maxw);margin:0 auto;padding:0 24px}
main.wrap{flex:1;padding-top:42px;padding-bottom:90px}

a{color:inherit;text-decoration:none}

/* ---------- header ---------- */
header{
  position:sticky;top:0;z-index:20;
  background:rgba(11,12,16,.82);
  backdrop-filter:blur(14px);
  border-bottom:1px solid var(--line);
}
.bar{display:flex;align-items:center;gap:22px;padding:13px 0}
.brandlink{display:flex;align-items:center;gap:11px;flex:none}
.brandlink svg{width:26px;height:26px;fill:var(--ink)}
.brand{font-weight:700;font-size:1.02rem;letter-spacing:-.015em}
.spacer{flex:1}

nav{display:flex;align-items:center;gap:2px}
.navitem{position:relative}
.navitem>a{
  display:flex;align-items:center;gap:5px;
  font-size:.88rem;font-weight:500;color:var(--dim);
  padding:.45rem .7rem;border-radius:7px;white-space:nowrap;
  transition:color .18s,background .18s;
}
.navitem>a:hover{color:var(--ink);background:var(--panel)}
.navitem>a.on{color:var(--ink)}
.chev{width:9px;height:6px;opacity:.6;transition:transform .18s}
.navitem.has-menu:hover .chev{transform:rotate(180deg)}

.menu{
  position:absolute;top:100%;left:0;min-width:186px;
  background:#15161d;
  border:1px solid var(--line);
  border-radius:10px;
  padding:6px;
  box-shadow:0 16px 40px rgba(0,0,0,.5);
  opacity:0;pointer-events:none;transform:translateY(-5px);
  transition:opacity .16s,transform .16s;
}
/* stays focusable while closed so keyboard users can tab in and reveal it */
/* :has(:focus-visible) rather than :focus-within. Focus lands on mousedown,
   so holding the button on one item left its menu open while hover opened
   the next, and you got two at once. focus-visible only matches keyboard
   focus, which is who the rule was for. */
.navitem.has-menu:hover .menu,
.navitem.has-menu:has(:focus-visible) .menu{opacity:1;pointer-events:auto;transform:translateY(0)}
.menu a{
  display:block;padding:.5rem .7rem;border-radius:6px;
  font-size:.86rem;color:var(--dim);transition:color .15s,background .15s;
}
.menu a:hover{color:var(--ink);background:var(--panel-hi)}

.join{
  flex:none;font-size:.82rem;font-weight:500;color:var(--ink);
  border:1px solid rgba(255,255,255,.17);border-radius:100px;padding:.42rem 1.05rem;
  transition:background .2s,color .2s,border-color .2s;
}
.join:hover{background:var(--ink);border-color:var(--ink);color:var(--bg)}

.burger{display:none;background:none;border:0;cursor:pointer;padding:8px;flex:none}
.burger span{display:block;width:19px;height:1.6px;background:var(--ink);margin:4px 0;border-radius:2px}

/* ---------- page head ---------- */
.phead{max-width:62ch;margin:0 auto 38px;text-align:center}
body.home .phead,.article .phead{margin-left:0;text-align:left}
.kicker{font-size:.7rem;font-weight:700;letter-spacing:.17em;text-transform:uppercase;color:var(--accent)}
h1{font-size:clamp(1.85rem,4vw,2.7rem);font-weight:700;letter-spacing:-.03em;line-height:1.14;margin:.45rem 0 .65rem}
.phead p{color:var(--dim);font-size:1.02rem}

h2{font-size:.73rem;font-weight:700;letter-spacing:.16em;text-transform:uppercase;color:var(--dimmer);margin:48px 0 16px}

/* ---------- layout helpers ---------- */
.grid{display:grid;gap:14px}
.g2{grid-template-columns:repeat(2,1fr)}
.g3{grid-template-columns:repeat(3,1fr)}
.g4{grid-template-columns:repeat(4,1fr)}
@media(max-width:880px){.g4{grid-template-columns:repeat(2,1fr)}}
.split{display:grid;grid-template-columns:1fr 300px;gap:36px;margin-top:48px;align-items:start}
.split h2{margin-top:0}
/* Square artwork, six across so a full release week sits on one row.
   Column counts are fixed to divisors of six (6, 3, 2) rather than left to
   auto-fit, which stranded a single card on its own row at some widths. */
.gsleeve{grid-template-columns:repeat(6,1fr)}
@media(max-width:1000px){.gsleeve{grid-template-columns:repeat(3,1fr)}}
@media(max-width:560px){.gsleeve{grid-template-columns:repeat(2,1fr)}}

@media(max-width:880px){
  .g2,.g3{grid-template-columns:1fr}
  .split{grid-template-columns:1fr;gap:12px}
  .split aside{margin-top:36px}
  .split aside .sleeve{max-width:180px}   /* stops the artwork going full-bleed */
}

/* ---------- cards ---------- */
.card{
  display:block;
  background:var(--panel);
  border:1px solid var(--line);
  border-radius:12px;
  padding:20px;
  transition:background .2s,border-color .2s,transform .2s;
}
/* a: a card with nowhere to go should not lift under the cursor */
a.card:hover{background:var(--panel-hi);border-color:rgba(255,255,255,.16);transform:translateY(-2px)}
.card h3{font-size:1.02rem;font-weight:700;letter-spacing:-.012em;line-height:1.34;margin-bottom:.35rem}
.card p{color:var(--dim);font-size:.885rem}
.card .tag+h3{margin-top:.6rem}

.meta{font-size:.74rem;color:var(--dimmer);margin-top:.75rem;display:flex;gap:.45rem;flex-wrap:wrap;align-items:center}

.tag{
  display:inline-block;font-size:.65rem;font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  padding:.22rem .52rem;border-radius:5px;background:var(--accent-soft);color:var(--accent);
}
.tag.warm{background:var(--pink-soft);color:#ff9ab5}
.score{
  font-weight:700;color:var(--accent);background:var(--accent-soft);
  padding:.1rem .4rem;border-radius:4px;font-size:.72rem;
}

/* ---------- feature ---------- */
.feature{
  display:block;border:1px solid var(--line);border-radius:14px;overflow:hidden;
  transition:border-color .2s,transform .2s;
}
.feature:hover{border-color:rgba(255,255,255,.18);transform:translateY(-2px)}
.art{height:200px;display:flex;align-items:flex-end;padding:18px}
.art-a{background:radial-gradient(60% 90% at 20% 20%, rgba(255,255,255,.15), transparent 60%),linear-gradient(120deg,#3a2230,#7d3a35 55%,#b4713f)}
.art-b{background:radial-gradient(60% 90% at 75% 25%, rgba(255,255,255,.14), transparent 60%),linear-gradient(120deg,#2c2438,#6b3348 55%,#a8663c)}
.fbody{padding:22px;background:var(--panel)}
.fbody h3{font-size:1.42rem;font-weight:700;letter-spacing:-.025em;line-height:1.24;margin-bottom:.5rem}
.fbody p{color:var(--dim);font-size:.94rem;max-width:66ch}
.embed{position:relative;aspect-ratio:16/9;width:100%;max-width:66ch;margin:18px 0;border-radius:12px;overflow:hidden;background:#000}
.embed iframe{position:absolute;inset:0;width:100%;height:100%;border:0}
.embed.sc{aspect-ratio:auto}
.embed.sc iframe{position:static;height:166px}

/* ---------- rows ---------- */
.rows{border:1px solid var(--line);border-radius:12px;overflow:hidden;background:var(--panel)}
.row{display:flex;gap:16px;align-items:center;padding:14px 18px;border-bottom:1px solid var(--line);transition:background .16s}
.row:last-child{border-bottom:0}
.row:hover{background:var(--panel-hi)}
.row .n{font-size:.78rem;color:var(--dimmer);width:24px;flex:none;font-variant-numeric:tabular-nums}
.row .main{flex:1;min-width:0}
.row .t{font-weight:500;font-size:.95rem}
.row .s{font-size:.81rem;color:var(--dim)}
.row .r{font-size:.77rem;color:var(--dimmer);flex:none;text-align:right;white-space:nowrap}
.date{flex:none;width:36px;text-align:center;font-size:.62rem;letter-spacing:.09em;color:var(--dimmer);line-height:1.15}
.date b{display:block;font-size:1.05rem;color:var(--ink);font-weight:700;letter-spacing:-.02em}

.more{display:inline-block;margin-top:14px;font-size:.85rem;color:var(--accent)}
.more:hover{text-decoration:underline}

/* ---------- artwork ----------
   Cards get a real image when the content file provides one, otherwise a
   deterministic warm gradient (.t1–.t6) so nothing ever renders as a hole. */
.thumb,.sleeve,.heroart,.articlehero{background-size:cover;background-position:center}
.sleeve{aspect-ratio:1;border-radius:8px}
/* width:100% keeps the box full-bleed; max-height stops a full-width card
   towering, and background-size:cover crops instead of squashing */
.thumb{width:100%;aspect-ratio:16/10;max-height:230px}
.t1{background-image:linear-gradient(140deg,#4a2438,#a8563f)}
.t2{background-image:linear-gradient(140deg,#2a2f42,#6d5f84)}
.t3{background-image:linear-gradient(140deg,#5c2a1e,#c0763a)}
.t4{background-image:linear-gradient(140deg,#33262c,#8a6b6b)}
.t5{background-image:linear-gradient(140deg,#4a1f30,#a3486a)}
.t6{background-image:linear-gradient(140deg,#243437,#5e8a7d)}
.sleeve.big{margin-bottom:0}

/* thumbnail-led cards */
.thumbcard{padding:0;overflow:hidden}
.thumbcard .cardbody{padding:16px 18px 20px}
.thumbcard .sleeve{border-radius:0}
.thumbcard h3{margin-top:.15rem}

/* =================================================================
   HOME DASHBOARD
   Wide magazine grid: rotating hero + category tiles, then a row of
   panels, then the platforms / newsletter / follow strip.
   ================================================================= */
body.home main.wrap{max-width:1560px;padding-left:18px;padding-right:18px;padding-top:18px}

.dash{display:grid;grid-template-columns:1.42fr 1fr;gap:12px}
@media(max-width:1100px){.dash{grid-template-columns:1fr}}

/* --- hero carousel --- */
.hero{position:relative;border:1px solid var(--line);border-radius:12px;overflow:hidden;min-height:440px}
@media(max-width:1100px){.hero{min-height:360px}}
@media(max-width:640px){.hero{min-height:360px}.hero .dots{display:none}}
.slide{
  position:absolute;inset:0;display:flex;align-items:center;
  opacity:0;visibility:hidden;transition:opacity .5s ease,visibility .5s ease;
}
/* the photo sits on its own layer so it can be graded without touching the text */
.slidebg{
  position:absolute;inset:0;z-index:0;
  background-size:cover;background-position:center;
  filter:brightness(.58) contrast(1.08) saturate(.85);
}
/* photos vary wildly in brightness and colour; this pass makes any of them
   sit consistently under the headline */
.slide::after{
  content:"";position:absolute;inset:0;z-index:0;
  background:linear-gradient(115deg,#2a1f4d,#6d4bff 45%,#ff5c8a);
  mix-blend-mode:color;opacity:.55;
}
.slide.on{opacity:1;visibility:visible}
.slide::before{
  content:"";position:absolute;inset:0;z-index:1;
  background:linear-gradient(100deg, rgba(8,9,12,.96) 0%, rgba(8,9,12,.92) 42%, rgba(8,9,12,.55) 68%, rgba(8,9,12,.12) 100%);
}
.slideinner{position:relative;z-index:2;padding:34px 40px;max-width:56%}
@media(max-width:1100px){.slideinner{max-width:74%;padding:30px}}
@media(max-width:640px){.slideinner{max-width:100%;padding:24px}}
.slideinner h2{
  font-size:clamp(1.6rem,2.7vw,2.5rem);font-weight:700;letter-spacing:-.035em;
  line-height:1.06;text-transform:uppercase;color:var(--ink);margin:.5rem 0 .7rem;
}
.slideinner p{color:#c8ccd4;font-size:1rem;max-width:42ch;line-height:1.5}
.herobtn{
  display:inline-block;margin-top:1.5rem;padding:.72rem 1.5rem;
  border:1px solid rgba(255,255,255,.55);border-radius:3px;
  font-size:.74rem;font-weight:700;letter-spacing:.13em;text-transform:uppercase;
  transition:background .2s,color .2s;
}
.slide:hover .herobtn{background:var(--ink);color:var(--bg)}
.dots{position:absolute;right:22px;bottom:20px;display:flex;gap:9px;z-index:3}
.dots .dot{
  width:9px;height:9px;border-radius:50%;cursor:pointer;padding:0;
  background:none;border:1px solid rgba(255,255,255,.5);transition:background .2s,border-color .2s;
}
.dots .dot.on{background:var(--accent);border-color:var(--accent)}
/* swipe hint: only on mobile, where the hero is a swipe carousel (no dots) */
.swipehint{display:none}
@media(max-width:640px){
  .swipehint{
    display:flex;align-items:center;gap:7px;position:absolute;right:18px;bottom:18px;z-index:3;
    font-size:.7rem;font-weight:600;letter-spacing:.18em;text-transform:uppercase;
    color:rgba(255,255,255,.88);padding:7px 13px;border:1px solid rgba(255,255,255,.28);
    border-radius:999px;background:rgba(8,9,12,.4);-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);
  }
  .swipehint .arr{font-size:1.05rem;line-height:1;opacity:.85}
  .swipehint .l{animation:nudgeL 1.6s ease-in-out infinite}
  .swipehint .r{animation:nudgeR 1.6s ease-in-out infinite}
}
@keyframes nudgeL{0%,100%{transform:translateX(0)}50%{transform:translateX(-3px)}}
@keyframes nudgeR{0%,100%{transform:translateX(0)}50%{transform:translateX(3px)}}

/* --- category tiles --- */
.tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));grid-auto-rows:1fr;gap:12px}
@media(max-width:640px){.tiles{grid-template-columns:1fr}}
.tile{
  display:flex;flex-direction:column;overflow:hidden;
  border:1px solid var(--line);border-radius:12px;background:var(--panel);
  transition:border-color .2s,transform .2s,background .2s;
}
.tile:hover{border-color:rgba(255,255,255,.2);background:var(--panel-hi);transform:translateY(-2px)}
.tileart{position:relative;height:150px;background-size:cover;background-position:center;flex:none}
.tileart::after{content:"";position:absolute;inset:0;background:linear-gradient(180deg,transparent 45%,rgba(8,9,12,.7))}
.chip{
  position:absolute;top:11px;left:11px;z-index:2;
  font-size:.6rem;font-weight:700;letter-spacing:.13em;text-transform:uppercase;
  padding:.28rem .5rem;border:1px solid var(--accent);color:#fff;background:rgba(139,107,255,.85);
}
.tilebody{padding:15px 16px 17px;display:flex;flex-direction:column;flex:1}
.tilebody h3{
  font-size:1.02rem;font-weight:700;letter-spacing:-.02em;line-height:1.2;
  text-transform:uppercase;margin-bottom:.4rem;
}
.tilebody p{color:var(--dim);font-size:.82rem;line-height:1.45}
.tilebody .more{margin-top:auto;padding-top:.7rem;font-size:.78rem}

/* --- panel row --- */
/* the reference layout: a wide releases panel then two narrower ones */
/* Two rows: releases spans both on the left, song of the week and events
   sit side by side on the right and stretch to a shared height, and the
   radio/join/follow strip fills the space underneath them. */
.panels{
  display:grid;grid-template-columns:1.55fr 1fr 1.1fr;
  gap:12px;margin-top:12px;align-items:start;
}
.panels.one{grid-template-columns:1fr}
@media(max-width:1180px){.panels{grid-template-columns:1fr 1fr}}
@media(max-width:760px){.panels{grid-template-columns:1fr}}
/* middle column of the panels row: song of the week over the radio */
.panelcol{display:flex;flex-direction:column;gap:12px;min-width:0}
.panel{border:1px solid var(--line);border-radius:12px;background:var(--panel);display:flex;flex-direction:column}
.panelhead{
  display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:13px 16px;border-bottom:1px solid var(--line);
}
.panelhead h3{
  font-size:.72rem;font-weight:700;letter-spacing:.15em;text-transform:uppercase;color:var(--accent);
}
.panelhead a{font-size:.68rem;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--dimmer)}
.panelhead a:hover{color:var(--ink)}
.panelbody{padding:14px 16px 16px;flex:1}

/* auto-FILL, not auto-fit: empty tracks are kept, so a single release stays
   card-sized instead of stretching into a giant square */
.relgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:14px}
.relcard .sleeve{margin-bottom:10px;border-radius:4px}
.relname{font-size:.76rem;font-weight:700;text-transform:uppercase;letter-spacing:.02em;line-height:1.25}
.relmeta{font-size:.76rem;color:var(--dim);line-height:1.35}
/* release cards stack label above date rather than running them
   together, which wrapped mid-date in a narrow card */
.thumbcard .meta{display:block}
.thumbcard .meta span{display:block}
.reldate{font-size:.72rem;color:var(--dimmer);margin-top:.2rem}
.relcard:hover .relname{color:var(--accent)}

/* --- bottom strip --- */
.strip{
  display:grid;grid-template-columns:1.1fr 1fr auto;gap:18px;align-items:stretch;
  margin-top:12px;border:1px solid var(--line);border-radius:12px;overflow:hidden;
  background:linear-gradient(115deg, rgba(139,107,255,.10), rgba(255,92,138,.05));
}
.stripcol{padding:20px 24px;display:flex;flex-direction:column;justify-content:center}
.stripcol + .stripcol{border-left:1px solid var(--line)}
.strip.two{grid-template-columns:1fr auto}
.strip .btn.small{width:auto;align-self:flex-start;margin-top:0;padding:.5rem 1.2rem}
@media(max-width:820px){
  .strip{grid-template-columns:1fr;gap:0}
  .stripcol + .stripcol{border-left:0;border-top:1px solid var(--line)}
}
.signupbox h4,.follow h4{
  font-size:.68rem;font-weight:700;letter-spacing:.15em;text-transform:uppercase;
  color:var(--dimmer);margin-bottom:.6rem;
}
.signup{display:flex;border:1px solid var(--line);border-radius:4px;overflow:hidden;max-width:320px}
.signup input{
  flex:1;min-width:0;background:none;border:0;padding:.6rem .8rem;
  color:var(--ink);font:inherit;font-size:.85rem;
}
.signup input::placeholder{color:var(--dimmer)}
.signup input:focus{outline:2px solid var(--accent);outline-offset:-2px}
.signup button{
  background:none;border:0;border-left:1px solid var(--line);
  color:var(--ink);padding:0 .9rem;cursor:pointer;font-size:1rem;
}
.signup button:hover{background:var(--accent);color:#fff}

.socials{display:flex;gap:9px}
.soc{
  display:grid;place-items:center;width:32px;height:32px;border-radius:6px;
  border:1px solid var(--line);color:var(--dim);transition:color .2s,border-color .2s,background .2s;
}
.soc svg{width:16px;height:16px}
.soc:hover{color:var(--ink);border-color:var(--ink);background:var(--panel-hi)}

/* radio + song of the week pair */
.duo{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-top:48px}
@media(max-width:820px){.duo{grid-template-columns:1fr}}
.radiocard,.sotwcard{
  display:grid;grid-template-columns:120px 1fr;gap:18px;align-items:center;
  border:1px solid var(--line);border-radius:12px;padding:18px;background:var(--panel);
  transition:background .2s,border-color .2s,transform .2s;
}
.radiocard:hover,.sotwcard:hover{background:var(--panel-hi);border-color:rgba(255,255,255,.16);transform:translateY(-2px)}
.radiocard h3,.sotwcard h3{font-size:1.08rem;font-weight:700;letter-spacing:-.015em;margin:.5rem 0 .25rem}
.radiocard p,.sotwcard p{color:var(--dim);font-size:.86rem}
.radiocard .more,.sotwcard .more{margin-top:.6rem;font-size:.82rem}
.radioart{
  aspect-ratio:1;border-radius:8px;
  background:radial-gradient(circle at 50% 50%, rgba(139,107,255,.95), rgba(139,107,255,.18) 42%, transparent 62%),
             linear-gradient(140deg,#221a3d,#4a2450);
}

/* radio page */
.player{display:grid;grid-template-columns:92px 1fr;gap:22px;align-items:center;
  border:1px solid var(--line);border-radius:16px;padding:24px;
  background:
    radial-gradient(90% 140% at 0% 0%, rgba(139,107,255,.14), transparent 60%),
    var(--panel);
  position:relative;overflow:hidden}
/* Centova only stores a 60px cover and there is no larger one to fetch, so
   this can never be sharp at any useful size. Kept small to hold the upscale
   down, with an inset edge because a lot of the artwork is a photo of a light
   vinyl label and the blown-up edges bleed into the panel otherwise. */
.playerart{aspect-ratio:1;border-radius:10px;background-size:cover;background-position:center;
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.10), inset 0 0 18px rgba(0,0,0,.45);
  background-image:
    radial-gradient(circle at 50% 50%, rgba(139,107,255,.95), rgba(139,107,255,.18) 42%, transparent 62%),
    linear-gradient(140deg,#221a3d,#4a2450)}
.playermain h3{font-size:1.5rem;font-weight:700;letter-spacing:-.025em;margin:.4rem 0 .3rem}
.playermain p{color:var(--dim);max-width:52ch;margin-bottom:14px}
.live{display:flex;align-items:center;gap:7px;font-size:.7rem;font-weight:700;
  letter-spacing:.15em;text-transform:uppercase;color:var(--accent)}

/* waveform. the canvas is drawn from the live audio, so it sits flat and
   quiet until playback starts rather than faking movement. */
.viz{display:block;width:100%;height:56px;margin:0 0 14px;opacity:.9}

/* shown only while the station is off air */
.rdown{font-size:.85rem;line-height:1.5;color:var(--ink);
  background:var(--pink-soft);border:1px solid rgba(255,92,138,.28);
  border-radius:10px;padding:11px 14px;margin:0 0 16px;max-width:56ch}
.rdown[hidden]{display:none}

.pctl{display:flex;align-items:center;gap:16px;flex-wrap:wrap}
.pbtn{
  width:52px;height:52px;flex:none;border-radius:50%;cursor:pointer;
  display:grid;place-items:center;
  border:1px solid rgba(139,107,255,.5);
  background:linear-gradient(160deg, rgba(139,107,255,.32), rgba(255,92,138,.18));
  color:var(--ink);transition:transform .15s, box-shadow .2s, border-color .2s;
}
.pbtn:hover{transform:scale(1.05);border-color:var(--accent);
  box-shadow:0 0 0 6px rgba(139,107,255,.12)}
.picon{width:22px;height:22px;fill:currentColor}
.pbtn .ppause{display:none}
.pbtn[data-state="playing"] .pplay{display:none}
.pbtn[data-state="playing"] .ppause{display:block}
.pstate{font-size:.75rem;font-weight:700;letter-spacing:.14em;text-transform:uppercase;
  color:var(--dim);min-width:7ch}
.pvol{display:flex;align-items:center;gap:9px;margin-left:auto}
.vsr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0)}
.vicon{width:18px;height:18px;fill:none;stroke:var(--dim);stroke-width:1.7;
  stroke-linecap:round;stroke-linejoin:round}
.pvol input[type=range]{
  -webkit-appearance:none;appearance:none;width:110px;height:4px;border-radius:4px;
  background:rgba(255,255,255,.16);outline:none;cursor:pointer;
}
.pvol input[type=range]::-webkit-slider-thumb{
  -webkit-appearance:none;width:13px;height:13px;border-radius:50%;
  background:var(--accent);border:none;cursor:pointer;
}
.pvol input[type=range]::-moz-range-thumb{
  width:13px;height:13px;border-radius:50%;background:var(--accent);border:none;cursor:pointer;
}
@media(max-width:760px){
  .player{grid-template-columns:96px 1fr;gap:18px;padding:20px}
  .pvol{margin-left:0}
}

/* Player and chat share one grid. Closed, the chat column is 0fr and the
   player has the row to itself; open, it slides across to make room. Both
   tracks are fr units because grid-template-columns only animates between
   comparable units. */
.radiowrap{display:grid;grid-template-columns:1fr 0fr;gap:0;align-items:start;
  transition:grid-template-columns .45s cubic-bezier(.4,0,.2,1), gap .45s}
.radiowrap.open{grid-template-columns:1fr 1.05fr;gap:18px}
.radiowrap .player{min-width:0}

/* chat toggle in the player controls */
.chattoggle{
  display:inline-flex;align-items:center;gap:7px;cursor:pointer;
  padding:.42rem .85rem;border-radius:100px;font:inherit;font-size:.78rem;
  border:1px solid var(--line);background:rgba(255,255,255,.04);color:var(--dim);
  transition:color .2s,border-color .2s,background .2s;
}
.chattoggle:hover{color:var(--ink);border-color:var(--accent)}
.chattoggle svg{width:15px;height:15px;fill:none;stroke:currentColor;
  stroke-width:1.7;stroke-linejoin:round}
.chattoggle[aria-expanded="true"]{color:var(--ink);border-color:var(--accent);
  background:rgba(139,107,255,.14)}

/* radio chat */
.chat{border:0 solid var(--line);border-radius:16px;
  padding:20px 0;background:var(--panel);
  min-width:0;overflow:hidden;
  /* Padding and border collapse too. A 0fr column can't squeeze them out on
     its own, so without this the closed state leaves a visible sliver. */
  opacity:0;transform:translateX(14px);pointer-events:none;visibility:hidden;
  transition:opacity .3s ease, transform .45s cubic-bezier(.4,0,.2,1),
             padding .45s cubic-bezier(.4,0,.2,1), border-width .45s,
             visibility 0s linear .45s}
.radiowrap.open .chat{opacity:1;transform:none;pointer-events:auto;visibility:visible;
  border-width:1px;padding:20px;transition-delay:0s}
.chathead{display:flex;align-items:baseline;gap:12px;margin-bottom:12px}
.chathead h3{font-size:.72rem;font-weight:700;letter-spacing:.16em;
  text-transform:uppercase;color:var(--accent)}
.chathere{font-size:.74rem;color:var(--dim)}
.chatname{margin-left:auto;background:none;border:0;padding:0;cursor:pointer;
  font:inherit;font-size:.74rem;color:var(--dim);text-decoration:underline}
.chatname:hover{color:var(--ink)}
.chatlog{height:260px;overflow-y:auto;overscroll-behavior:contain;
  display:flex;flex-direction:column;gap:7px;padding-right:6px}
.chatrow{font-size:.88rem;line-height:1.45;word-break:break-word}
.chatrow b{font-weight:600;margin-right:.5rem}
.chatrow span{color:var(--dim)}
.chattime{color:var(--dimmer);font-size:.72rem;margin-right:.45rem;
  font-variant-numeric:tabular-nums;white-space:nowrap}
/* the badge sits between the name and the message, so it needs
   its own breathing room on the right */
.chatrow .cmbadge{margin-right:.45rem}
.chatnote{font-size:.74rem;color:var(--dim);min-height:1.1rem;margin:.5rem 0 0}
.chatnote.bad{color:var(--pink)}
.chatjoin,.chatsay{display:flex;gap:8px;margin-top:10px}
/* display:flex above would otherwise win over the hidden attribute */
.chatjoin[hidden],.chatsay[hidden]{display:none}
.chatempty{margin:auto 0;color:var(--dim);font-size:.85rem;text-align:center}
.chatjoin input,.chatsay input{
  flex:1;min-width:0;padding:.6rem .85rem;border-radius:100px;
  border:1px solid var(--line);background:rgba(255,255,255,.04);
  color:var(--ink);font:inherit;font-size:.86rem;outline:none;
}
.chatjoin input:focus,.chatsay input:focus{border-color:var(--accent)}
.chatjoin .btn,.chatsay .btn{flex:none}
.chatfine{font-size:.7rem;color:var(--dim);opacity:.7;margin-top:10px}

/* inline audio example in a production piece */
.example{margin:28px 0;padding:16px 18px;border:1px solid var(--line);
  border-radius:12px;background:var(--panel)}
.example figcaption{font-size:.7rem;font-weight:700;letter-spacing:.15em;
  text-transform:uppercase;color:var(--accent);margin-bottom:12px}
/* the native control until example.js takes over, then it drives a hidden one */
.example audio{width:100%;display:block}
.example.custom audio{display:none}

.exui{display:flex;align-items:center;gap:14px}
.exbtn{
  width:40px;height:40px;flex:none;border-radius:50%;cursor:pointer;
  display:grid;place-items:center;
  border:1px solid rgba(139,107,255,.5);
  background:linear-gradient(160deg, rgba(139,107,255,.32), rgba(255,92,138,.18));
  color:var(--ink);transition:transform .15s, box-shadow .2s, border-color .2s;
}
.exbtn:hover{transform:scale(1.06);border-color:var(--accent);
  box-shadow:0 0 0 5px rgba(139,107,255,.12)}
.exbtn .picon{width:17px;height:17px;fill:currentColor}
.exbtn .expa{display:none}
.example[data-state="playing"] .exbtn .expl{display:none}
.example[data-state="playing"] .exbtn .expa{display:block}

.exseek{
  -webkit-appearance:none;appearance:none;flex:1;min-width:0;
  height:4px;border-radius:4px;outline:none;cursor:pointer;
  background:rgba(255,255,255,.16);
}
.exseek::-webkit-slider-thumb{
  -webkit-appearance:none;width:13px;height:13px;border-radius:50%;
  background:var(--accent);border:none;cursor:pointer;
}
.exseek::-moz-range-thumb{
  width:13px;height:13px;border-radius:50%;background:var(--accent);
  border:none;cursor:pointer;
}
.extime{font-size:.74rem;color:var(--dim);font-variant-numeric:tabular-nums;
  flex:none;min-width:8ch;text-align:right}

/* volume on an article example, same shape as the radio player's */
.exvol{display:flex;align-items:center;gap:8px;flex:none}
.exvol input[type=range]{
  -webkit-appearance:none;appearance:none;width:78px;height:4px;border-radius:4px;
  background:rgba(255,255,255,.16);outline:none;cursor:pointer;
}
.exvol input[type=range]::-webkit-slider-thumb{
  -webkit-appearance:none;width:11px;height:11px;border-radius:50%;
  background:var(--accent);border:none;cursor:pointer;
}
.exvol input[type=range]::-moz-range-thumb{
  width:11px;height:11px;border-radius:50%;background:var(--accent);
  border:none;cursor:pointer;
}
/* phones have hardware volume keys and the row runs out of width first */
@media(max-width:560px){ .exvol{display:none} }

/* article comments. Sits in the article column, so it inherits its width. */
.comments{max-width:70ch;margin:48px auto 0;padding-top:28px;
  border-top:1px solid var(--line)}
.cmhead2{display:flex;align-items:baseline;gap:12px;margin-bottom:18px}
.cmhead2 h2{font-size:1.15rem;font-weight:700;letter-spacing:-.02em;margin:0}
.cmcount{font-size:.78rem;color:var(--dim)}
.cmlist{display:flex;flex-direction:column;gap:18px}

/* a reply sits indented under whatever it answers, with a rule down the
   left so the thread reads as one thing at a glance */
.cmreply{margin-left:26px;padding-left:16px;border-left:2px solid var(--accent-soft)}
.cmreplybtn{
  margin-top:8px;background:none;border:0;padding:0;cursor:pointer;
  font:inherit;font-size:.74rem;color:var(--dimmer);
}
.cmreplybtn:hover{color:var(--accent)}
.cmcancel{
  background:none;border:0;padding:0;cursor:pointer;
  font:inherit;font-size:.74rem;color:var(--dimmer);align-self:flex-start;
}
.cmcancel:hover{color:var(--accent)}
/* the form is moved into a row while replying, so it needs its own room */
.cmrow .cmform{margin-top:14px}
@media(max-width:560px){ .cmreply{margin-left:12px;padding-left:12px} }
.cmempty{color:var(--dim);font-size:.9rem}
.cmrow{border-left:2px solid var(--line);padding-left:14px}
.cmhead{display:flex;align-items:baseline;gap:10px;margin-bottom:3px}
.cmhead b{font-weight:600;font-size:.88rem}
.cmhead time{font-size:.72rem;color:var(--dim)}
/* marks a comment posted through the keyed admin endpoint */
.cmbadge{font-style:normal;font-size:.6rem;font-weight:700;letter-spacing:.1em;
  text-transform:uppercase;padding:.12rem .38rem;border-radius:4px;
  background:var(--accent-soft);color:var(--accent)}
.cmrow p{font-size:.92rem;line-height:1.6;color:var(--ink);
  white-space:pre-wrap;word-break:break-word;margin:0}
.cmform{margin-top:24px}
.cmform textarea{
  width:100%;padding:.8rem .95rem;border-radius:12px;resize:vertical;
  border:1px solid var(--line);background:rgba(255,255,255,.04);
  color:var(--ink);font:inherit;font-size:.9rem;line-height:1.5;outline:none;
}
.cmform textarea:focus{border-color:var(--accent)}
.cmactions{display:flex;align-items:center;justify-content:space-between;
  gap:12px;margin-top:10px}
.cmas{font-size:.78rem;color:var(--dim)}
.cmname{background:none;border:0;padding:0;font:inherit;font-size:.78rem;
  color:var(--accent);cursor:pointer;text-decoration:underline}
.cmnote{font-size:.78rem;color:var(--dim);min-height:1.1rem;margin-top:10px}
.cmnote.bad{color:var(--pink)}
/* the chat grows downward past the player rather than squashing to match it */
.radiowrap.open .chatlog{height:min(52vh,420px)}

@media(max-width:900px){
  /* no room for two columns: the chat drops underneath instead */
  .radiowrap,.radiowrap.open{grid-template-columns:1fr;gap:0}
  .radiowrap.open{gap:18px}
  .chat{transform:translateY(-10px)}
  .radiowrap.open .chatlog{height:300px}
}
@media(prefers-reduced-motion:reduce){
  .radiowrap,.chat{transition:none}
}

.setup{border:1px solid var(--line);border-radius:12px;padding:24px;background:var(--panel)}
.setup h3{font-size:1.1rem;font-weight:700;margin-bottom:.8rem}
.setup ol{padding-left:1.15rem;color:var(--dim)}
.setup li{margin-bottom:.5rem}
.setup strong{color:var(--ink)}

/* "Listen" button in the header */
/* reads as a radio station, not a generic link */
.listen{
  display:flex;align-items:center;gap:9px;flex:none;
  padding:.34rem .9rem .34rem .75rem;border-radius:100px;
  border:1px solid rgba(139,107,255,.45);background:rgba(139,107,255,.12);
  color:var(--ink);transition:background .2s,border-color .2s;
}
.listen:hover{background:rgba(139,107,255,.24);border-color:var(--accent)}
.lwrap{display:flex;flex-direction:column;line-height:1.12}
.lwrap em{
  font-style:normal;font-size:.58rem;font-weight:700;letter-spacing:.16em;
  text-transform:uppercase;color:var(--accent);
}
/* the song title truncates but the "· Listen live" tail never does, so the
   call to action survives however long the track name is */
.lwrap b{font-size:.78rem;font-weight:500;color:var(--ink);display:flex;min-width:0}
.lwrap b #npsong{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:24ch}
.lwrap b i{font-style:normal;color:var(--dim);flex:none;white-space:pre}
@media(max-width:520px){.lwrap em{display:none}}
@media(max-width:1180px){.lwrap b #npsong{max-width:14ch}}
.listen .dot,.live .dot,.striplisten .dot{
  width:6px;height:6px;border-radius:50%;background:var(--accent);
  box-shadow:0 0 0 0 rgba(139,107,255,.6);animation:pulse 2.4s infinite;
}
@keyframes pulse{
  0%{box-shadow:0 0 0 0 rgba(139,107,255,.55)}
  70%{box-shadow:0 0 0 7px rgba(139,107,255,0)}
  100%{box-shadow:0 0 0 0 rgba(139,107,255,0)}
}
@media(prefers-reduced-motion:reduce){.listen .dot,.live .dot,.striplisten .dot,.striplisten .disc::after{animation:none}}

/* article page */
.article{max-width:70ch;margin:0 auto}   /* centre the column in the page */
.back{display:inline-block;font-size:.83rem;color:var(--dim);margin-bottom:1.6rem}
.back:hover{color:var(--ink)}
.article h1{margin:.45rem 0 .7rem}
.standfirst{font-size:1.12rem;color:var(--dim);line-height:1.55;margin-bottom:1rem}
.byline{
  display:flex;align-items:center;gap:10px;font-size:.8rem;
  padding-bottom:1.6rem;border-bottom:1px solid var(--line);
}
.byline .avatar{
  width:30px;height:30px;border-radius:50%;margin:0;flex:none;
  display:grid;place-items:center;background:var(--panel-hi);
  border:1px solid var(--line);color:var(--dim);
}
.byline .avatar svg{width:16px;height:16px}
.byline .who{color:var(--ink);font-weight:500}
.byline .when{color:var(--dimmer)}
.byline .who+.when::before{content:"·";margin-right:.5rem;color:var(--dimmer)}

/* download button at the foot of an article */
.dl{
  display:flex;align-items:center;gap:14px;margin-top:2.4rem;
  border:1px solid var(--line);border-radius:12px;padding:16px 18px;
  background:var(--panel);transition:background .2s,border-color .2s,transform .2s;
}
.dl:hover{background:var(--panel-hi);border-color:var(--accent);transform:translateY(-2px)}
.dl.buy{margin-top:2.4rem}
.dl.buy+.dl{margin-top:10px}
.dl.buy .dlicon{background:var(--pink-soft);color:#ff9ab5}
.dlicon{
  width:38px;height:38px;flex:none;border-radius:9px;display:grid;place-items:center;
  background:var(--accent-soft);color:var(--accent);
}
.dlicon svg{width:19px;height:19px}
.dl strong{display:block;font-size:.95rem;font-weight:700;letter-spacing:-.01em}
.dl em{display:block;font-style:normal;font-size:.78rem;color:var(--dimmer);margin-top:.1rem}
.articlehero{height:320px;border-radius:12px;margin:1.8rem 0 .4rem}
/* A fixed 320px is a wide band on a desktop and very nearly a square on a
   phone, where cover then throws away most of a 16:9 picture. Narrow screens
   get the image's own proportions instead. */
@media(max-width:760px){
  .articlehero{height:auto;aspect-ratio:var(--hero-ratio,1.78)}
}
.prose h2,.prose h3{
  font-size:1.16rem;font-weight:700;letter-spacing:-.015em;text-transform:none;
  color:var(--ink);margin:2rem 0 .7rem;
}
.prose ul,.prose ol{padding-left:1.2rem;color:var(--dim);margin-bottom:1rem}
.prose li{margin-bottom:.35rem}
.prose blockquote{
  border-left:2px solid var(--accent);padding-left:16px;margin:1.4rem 0;
  color:var(--ink);font-size:1.05rem;
}
/* A fact that changed after publication. Boxed so it cannot be mistaken
   for part of the piece as originally written. */
.prose .update{
  display:block;
  border:1px solid var(--accent-soft);
  border-left:3px solid var(--accent);
  background:rgba(139,107,255,.07);
  border-radius:10px;
  padding:16px 18px;
  margin:1.6rem 0;
  color:var(--ink);
  font-size:.95rem;
  line-height:1.6;
}
.prose .update strong,.prose .update b{color:var(--ink)}

.prose code{background:rgba(255,255,255,.07);padding:.08rem .34rem;border-radius:4px;font-size:.9em}
/* height:auto is what stops the picture stretching. Images carry their
   own width and height so the browser can reserve the box, and without
   this the height stays at the attribute value while max-width scales
   the width down. */
.prose img{max-width:100%;height:auto;border-radius:10px;margin:1.2rem 0}
.faq{margin:2.4rem 0 0;padding-top:1.8rem;border-top:1px solid var(--line)}
.faq h2{font-size:1.5rem;font-weight:700;letter-spacing:-.02em;margin-bottom:1.1rem}
.faqitem{margin-bottom:1.1rem}
.faqitem h3{font-size:1.05rem;font-weight:700;color:var(--ink);margin-bottom:.3rem}
.faqitem p{color:var(--dim);line-height:1.55;max-width:62ch}
.prose hr{border:0;border-top:1px solid var(--line);margin:2rem 0}

/* Reader polls sit above comments, with the result bar appearing only after
   the visitor has voted (or when there are already votes to show). */
.readerpoll{margin:2.2rem 0 1.2rem;border:1px solid var(--line);border-radius:12px;padding:20px;background:var(--panel)}
.readerpoll h2{font-size:1.05rem;margin:0 0 13px}
.pollchoices{display:grid;gap:8px}
.pollchoice{position:relative;overflow:hidden;isolation:isolate;display:flex;justify-content:space-between;align-items:center;width:100%;
  padding:11px 13px;border:1px solid rgba(255,255,255,.14);border-radius:8px;background:rgba(255,255,255,.03);color:var(--ink);font:inherit;font-size:.88rem;text-align:left;cursor:pointer}
.pollchoice::before{content:"";position:absolute;z-index:-1;inset:0 auto 0 0;width:var(--poll-result,0%);background:rgba(139,107,255,.18);transition:width .35s ease}
.pollchoice:hover:not(:disabled){border-color:rgba(139,107,255,.65);background:rgba(139,107,255,.09)}
.pollchoice.picked{border-color:var(--accent)}
.pollchoice:disabled{cursor:default}
.pollchoice b{font-size:.78rem;color:var(--accent)}
.pollnote{margin:.8rem 0 0;color:var(--dimmer);font-size:.78rem}

.empty{
  border:1px dashed var(--line);border-radius:12px;padding:26px;
  color:var(--dim);font-size:.9rem;text-align:center;
}
.empty code{background:rgba(255,255,255,.07);padding:.08rem .34rem;border-radius:4px}

.avatar{width:54px;height:54px;border-radius:50%;margin-bottom:12px}
.av-a{background:linear-gradient(140deg,#5a3448,#a3564a)}
.av-b{background:linear-gradient(140deg,#234b52,#4a9c86)}
.av-c{background:linear-gradient(140deg,#6b3a1e,#d19a4e)}

/* ---------- song of the week ---------- */
aside .sotw{display:block;border:1px solid var(--line);border-radius:12px;padding:16px;background:var(--panel);transition:background .2s,border-color .2s}
aside .sotw:hover{background:var(--panel-hi);border-color:rgba(255,255,255,.16)}
aside .sotw .t{font-weight:700;margin-top:2px}
aside .sotw .s{font-size:.85rem;color:var(--dim)}
aside .sotw .vote{font-size:.73rem;color:var(--accent);margin-top:.55rem}

.sotw-hero{display:grid;grid-template-columns:260px 1fr;gap:32px;align-items:start}
.sotw-hero h3{font-size:1.9rem;font-weight:700;letter-spacing:-.03em;line-height:1.14;margin:.6rem 0 .2rem}
.sotw-hero .byline{color:var(--accent);font-size:.95rem;margin-bottom:.9rem}
.sotw-hero>div>p{color:var(--dim);max-width:56ch}
.votebar{height:5px;border-radius:4px;background:rgba(255,255,255,.08);margin:18px 0 8px;overflow:hidden}
.votebar span{display:block;height:100%;background:var(--accent);border-radius:4px}
.sotw-hero .btn{margin-top:18px}
@media(max-width:760px){
  .sotw-hero{grid-template-columns:1fr}
  .sotw-hero .sleeve{max-width:220px}   /* square artwork would otherwise go full-bleed */
}

.howto{margin-top:54px;border:1px solid var(--line);border-radius:12px;padding:24px;background:var(--panel)}
.howto ol{padding-left:1.15rem;color:var(--dim)}
.howto li{margin-bottom:.5rem}
.howto strong{color:var(--ink)}
.chan{color:var(--accent);background:var(--accent-soft);padding:.05rem .34rem;border-radius:4px;font-size:.9em}

/* ---------- misc ---------- */
.btn{
  display:inline-block;padding:.8rem 1.7rem;
  border:1px solid rgba(255,255,255,.18);border-radius:100px;
  background:rgba(255,255,255,.03);color:var(--ink);
  font-size:.86rem;font-weight:500;
  transition:background .2s,border-color .2s,color .2s,transform .2s;
}
.btn:hover{background:var(--ink);border-color:var(--ink);color:var(--bg);transform:translateY(-1px)}
.btn.small{margin-top:12px;width:100%;text-align:center;padding:.62rem 1rem;font-size:.8rem}

.cta-band{
  margin-top:54px;border:1px solid var(--line);border-radius:12px;padding:24px;
  background:linear-gradient(120deg, rgba(109,75,255,.12), rgba(255,92,138,.07));
  display:flex;gap:24px;align-items:center;justify-content:space-between;flex-wrap:wrap;
}
.cta-band h3{font-size:1.12rem;font-weight:700;letter-spacing:-.015em}
.cta-band p{color:var(--dim);font-size:.9rem}

.prose{max-width:62ch}
.prose p{color:var(--dim);margin-bottom:1rem}
.prose strong{color:var(--ink);font-weight:700}
.prose a{color:var(--accent);border-bottom:1px solid rgba(139,107,255,.4)}

.note{
  margin-top:34px;font-size:.79rem;color:var(--dimmer);
  border-left:2px solid var(--accent-soft);padding-left:12px;
}

/* ---------- footer ---------- */
footer{position:relative;z-index:1;border-top:1px solid var(--line);background:rgba(0,0,0,.2)}
.foot{padding:38px 24px 26px}
.footcols{display:grid;grid-template-columns:repeat(5,1fr);gap:22px;margin-bottom:30px}
.footcols h4{font-size:.68rem;font-weight:700;letter-spacing:.15em;text-transform:uppercase;color:var(--dimmer);margin-bottom:.7rem}
.footcols a{display:block;font-size:.85rem;color:var(--dim);padding:.16rem 0;transition:color .15s}
.footcols a:hover{color:var(--ink)}
.footbar{
  border-top:1px solid var(--line);padding-top:18px;
  display:flex;justify-content:space-between;flex-wrap:wrap;gap:.5rem 2rem;
  font-size:.79rem;color:var(--dim);
}
.ilink{color:var(--dim);border-bottom:1px solid rgba(255,255,255,.14);padding-bottom:1px}
.ilink:hover{color:var(--ink);border-color:var(--ink)}
@media(max-width:880px){.footcols{grid-template-columns:repeat(2,1fr)}}

/* ---------- mobile nav ---------- */
@media(max-width:900px){
  .burger{display:block;order:3}
  .join{display:none}
  nav{
    order:4;width:100%;display:none;flex-direction:column;align-items:stretch;gap:0;
    padding:8px 0 14px;border-top:1px solid var(--line);margin-top:10px;
  }
  .bar{flex-wrap:wrap;gap:0 14px}
  .spacer{flex:1}
  nav.open{display:flex}
  .navitem>a{padding:.6rem .2rem;font-size:.95rem;justify-content:space-between}
  /* pointer-events too: the base rule turns them off and only hover or focus
     turns them back on, neither of which a touch tap does. The submenu is laid
     out inline here, so it is always tappable. */
  .menu{
    position:static;opacity:1;visibility:visible;transform:none;pointer-events:auto;
    box-shadow:none;border:0;background:none;padding:0 0 6px 14px;min-width:0;
  }
  .menu a{padding:.4rem .2rem;font-size:.88rem}
  .navitem.has-menu:hover .chev{transform:none}
}

/* ---------- radio player ---------- */
.rartist{color:var(--accent) !important;font-weight:500;margin-bottom:14px !important}
.rbar{height:5px;border-radius:4px;background:rgba(255,255,255,.1);overflow:hidden;max-width:520px}
.rbar span{display:block;height:100%;width:0;background:var(--accent);border-radius:4px;transition:width .25s linear}
.rtime{display:flex;justify-content:space-between;max-width:520px;font-size:.74rem;
  color:var(--dimmer);margin-top:6px;font-variant-numeric:tabular-nums}
.rctl{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-top:16px}
.rbtn{
  font:inherit;font-size:.82rem;font-weight:500;cursor:pointer;
  background:none;border:1px solid rgba(255,255,255,.18);border-radius:100px;
  color:var(--ink);padding:.5rem 1.35rem;transition:background .2s,color .2s,border-color .2s;
}
.rbtn:hover{background:var(--ink);border-color:var(--ink);color:var(--bg)}
.rbtn.primary{background:var(--accent);border-color:var(--accent);color:#fff;min-width:96px}
.rbtn.primary:hover{filter:brightness(1.12);background:var(--accent);color:#fff}
.rvol{display:flex;align-items:center;gap:8px;font-size:.74rem;color:var(--dimmer)}
.rvol input{width:96px;accent-color:var(--accent)}

/* radio embed (Mixcloud / SoundCloud) */
.embedwrap{border:1px solid var(--line);border-radius:12px;overflow:hidden;background:var(--panel)}
.embedwrap iframe{display:block;width:100%;border:0}

/* ---------- media embeds ---------- */
.embed{margin:1.8rem 0 3rem;border-radius:12px;overflow:hidden;border:1px solid var(--line);background:#000}
.embed iframe{display:block;width:100%;border:0}
/* more breathing room between tracks: space before each song title */
.prose p:has(strong){margin-top:2.4rem;font-size:1.12rem;line-height:1.4}
.prose p:has(strong) strong{font-weight:700}

/* ---------- artist / label roster ---------- */
.rostgrid{grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:12px}
.rost{
  display:block;border:1px solid var(--line);border-radius:12px;overflow:hidden;
  background:var(--panel);transition:background .2s,border-color .2s,transform .2s;
}
a.rost:hover{background:var(--panel-hi);border-color:rgba(255,255,255,.18);transform:translateY(-2px)}
.rostart{width:100%;aspect-ratio:1;background-size:cover;background-position:center}
.rostbody{padding:12px 13px 14px}
.rostbody h3{font-size:.86rem;font-weight:700;letter-spacing:-.01em;line-height:1.25}
.rostbody .aka{font-size:.72rem;color:var(--dimmer);margin-top:.2rem;line-height:1.3}

/* ---------- captioned images ---------- */
.prose figure{margin:1.8rem 0}
/* floated figures: text wraps alongside */
.prose figure.left,.prose figure.right{width:min(42%, 270px);margin-top:.15rem}
.prose figure.left{float:left;margin-right:1.6rem;margin-bottom:1.1rem}
.prose figure.right{float:right;margin-left:1.6rem;margin-bottom:1.1rem}
.prose figure.left img,.prose figure.right img{width:100%;height:auto;max-height:none}
.prose h2,.prose h3{clear:both}          /* headings never collide with a float */
.prose::after{content:"";display:block;clear:both}
@media(max-width:620px){
  .prose figure.left,.prose figure.right{float:none;width:auto;margin:1.8rem 0}
}
/* width:auto so a portrait photo is not upscaled to the column width */
.prose figure img{
  display:block;width:auto;height:auto;max-width:100%;max-height:620px;
  border-radius:10px;margin:0 auto;
}
.prose figcaption{
  margin-top:.6rem;font-size:.78rem;color:var(--dimmer);line-height:1.5;
  border-left:2px solid var(--accent-soft);padding-left:11px;
}

/* ---------- follow the artist ---------- */
.followbox{
  display:flex;align-items:center;gap:14px;flex-wrap:wrap;
  margin-top:1rem;
}
.fname{font-size:.95rem;font-weight:700;letter-spacing:-.01em}
.followbox .ig{
  display:inline-flex;align-items:center;gap:8px;
  font-size:.88rem;color:var(--dim);
  border:1px solid var(--line);border-radius:100px;padding:.42rem .95rem;
  transition:color .2s,border-color .2s,background .2s;
}
.followbox .ig svg{width:16px;height:16px}
.followbox .ig:hover{color:var(--ink);border-color:var(--accent);background:var(--accent-soft)}

/* ---------- scheduled (preview only) ---------- */
.scheduled{
  margin-bottom:1.6rem;padding:.75rem 1rem;border-radius:9px;
  background:var(--accent-soft);border:1px solid rgba(139,107,255,.4);
  color:var(--ink);font-size:.83rem;
}
.tag.sched{background:rgba(255,255,255,.1);color:var(--dim);margin-left:.35rem}

/* ---------- foot band ---------- */
.stripcol h4{
  font-size:.68rem;font-weight:700;letter-spacing:.15em;text-transform:uppercase;
  color:var(--dimmer);margin-bottom:.7rem;
}
.striplisten,.radiopanel{display:inline-flex;align-items:center;gap:12px;color:var(--ink)}
.striplisten .disc,.radiopanel .disc{
  width:42px;height:42px;border-radius:50%;flex:none;
  background:radial-gradient(circle at 50% 50%, rgba(139,107,255,.95), rgba(139,107,255,.2) 42%, #191428 62%);
  border:1px solid rgba(255,255,255,.14);
  display:grid;place-items:center;
}
.striplisten .disc::after,.radiopanel .disc::after{content:"";width:8px;height:8px;border-radius:50%;background:var(--bg)}
/* The home-page Radio art echoes the live indicator in the header: a purple
   centre that pulses outward, rather than the old black record-hole dot. */
.striplisten .disc::after{background:var(--accent);box-shadow:0 0 0 0 rgba(139,107,255,.6);animation:pulse 2.4s infinite}
.striplisten strong,.radiopanel strong{display:block;font-size:.95rem;font-weight:700;letter-spacing:-.01em}
.striplisten em,.radiopanel em{display:block;font-style:normal;font-size:.78rem;color:var(--accent)}
.striplisten:hover em,.radiopanel:hover em{text-decoration:underline}

/* ---------- review header ---------- */
.reviewbar{
  display:flex;gap:26px;align-items:center;flex-wrap:wrap;
  margin:1.6rem 0 .4rem;padding:16px 18px;
  border:1px solid var(--line);border-radius:12px;background:var(--panel);
}
.reviewbar>div{display:flex;flex-direction:column;gap:.15rem}
.reviewbar span{
  font-size:.63rem;font-weight:700;letter-spacing:.14em;
  text-transform:uppercase;color:var(--dimmer);
}
.reviewbar strong{font-size:.95rem;font-weight:500}
.scorebox{margin-left:auto}
.scorebox b{
  display:grid;place-items:center;width:54px;height:54px;border-radius:12px;
  background:var(--accent-soft);color:var(--accent);
  font-size:1.25rem;font-weight:700;letter-spacing:-.02em;
}
/* a row of stars needs to run wide rather than sit in a square */
.scorebox b.stars{width:auto;min-width:0;padding:0 .85rem;font-size:1.05rem;letter-spacing:.06em}

.rostbody .loc{font-size:.74rem;color:var(--dimmer);margin-top:.15rem}

/* ---------- home: roster slice ---------- */
.discgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:14px}
.disc{display:block}
.discart{aspect-ratio:1;border-radius:8px;background-size:cover;background-position:center;margin-bottom:10px}
.disc strong{display:block;font-size:.86rem;font-weight:700;letter-spacing:-.01em;line-height:1.25}
.disc em{display:block;font-style:normal;font-size:.74rem;color:var(--dimmer);margin-top:.1rem}
.disc:hover strong{color:var(--accent)}

/* ---------- disclosure ---------- */
.disclosure{
  margin:1.4rem 0 .2rem;padding:.8rem 1rem;border-radius:9px;
  border:1px solid rgba(255,157,77,.35);background:rgba(255,157,77,.09);
  color:var(--dim);font-size:.83rem;line-height:1.55;
}
.disclosure strong{color:var(--ink)}

/* ---------- pre-save ---------- */
.presaveband{
  display:flex;align-items:center;justify-content:space-between;gap:24px;flex-wrap:wrap;
  margin-top:2.4rem;padding:20px 22px;border-radius:12px;
  border:1px solid rgba(139,107,255,.35);
  background:linear-gradient(115deg, rgba(139,107,255,.14), rgba(255,92,138,.07));
}
.pbtext strong{display:block;font-size:1.05rem;font-weight:700;letter-spacing:-.015em}
.pbtext em{display:block;font-style:normal;font-size:.85rem;color:var(--dim);margin-top:.15rem}
.presave{
  display:inline-flex;align-items:center;gap:12px;flex:none;
  padding:.85rem 1.5rem;border-radius:100px;
  background:var(--accent);color:#fff;font-size:.9rem;font-weight:700;
  letter-spacing:-.01em;transition:filter .2s,transform .2s;
}
.presave:hover{filter:brightness(1.12);transform:translateY(-1px)}
.presave .soon{
  font-size:.62rem;font-weight:700;letter-spacing:.12em;text-transform:uppercase;
  background:rgba(255,255,255,.22);padding:.2rem .5rem;border-radius:4px;
}

/* song of the week, in the home row */
.sotwpanel{display:block}
/* The artwork runs the full width of its column. Capping it left a short
   panel next to the much taller releases grid and a lot of dead space. */
.sotwpanel .sleeve{margin-bottom:14px;width:100%;max-width:250px}
.sotwpanel strong{display:block;font-size:1.02rem;font-weight:700;letter-spacing:-.015em;line-height:1.25}
.sotwpanel em{display:block;font-style:normal;font-size:.82rem;color:var(--dim);margin-top:.15rem}
.sotwpanel:hover strong{color:var(--accent)}

.chip.sched{left:auto;right:11px;background:rgba(11,12,16,.85);border-color:rgba(255,255,255,.35)}

.kicker .wk{color:var(--dimmer);margin-left:.5rem}
/* Artist / label header: picture beside the name and bio rather than a
   stack down the middle, which stranded thin entries on a wide screen. */
.rosterhead{display:grid;grid-template-columns:240px 1fr;gap:32px;
  align-items:start;margin-bottom:8px}
.rosterpic img{display:block;width:100%;height:auto;border-radius:12px}
.rosterinfo h1{margin:.3rem 0 .5rem}
.rosterinfo .rmeta{color:var(--dim);font-size:.92rem;margin-bottom:.2rem}
.rosterinfo .prose{margin-top:1rem}
.offsite{color:var(--accent)}
.offsite:hover{text-decoration:underline}
@media(max-width:760px){
  .rosterhead{grid-template-columns:1fr;gap:20px}
  .rosterpic{max-width:220px}
}

/* ---------- roster search ---------- */
.rostersearch{display:flex;align-items:center;justify-content:center;gap:14px;margin:-14px 0 30px}
.rostersearch input{
  flex:1;max-width:420px;background:var(--panel);color:var(--ink);font:inherit;
  font-size:.92rem;border:1px solid var(--line);border-radius:100px;padding:.62rem 1.1rem;
}
.rostersearch input::placeholder{color:var(--dimmer)}
.rostersearch input:focus{outline:none;border-color:var(--accent);background:var(--panel-hi)}
.rcount{font-size:.8rem;color:var(--dimmer)}

/* about page: centred column, text still left aligned so it reads */
body.about .prose,body.about .card{margin-left:auto;margin-right:auto}
body.about .card{max-width:62ch}
body.about h2{text-align:center}

/* ---------- artist / label pages ---------- */
/* The header is now two columns, so the text reads left-aligned beside the
   picture. Related articles sit in a normal grid underneath. */
body.roster .prose{max-width:62ch}
body.roster .grid > *{min-width:0}

/* Interview questions. The answer is a normal paragraph, so the question has
   to carry the contrast on its own. */
/* Q and A hang in the margin so the two are told apart by the label rather
   than by colour, and a long answer stays aligned under its own first line. */
.prose .q,.prose .q + p{
  display:flex;gap:.75rem;line-height:1.55;
}
.prose .q{margin:1.9rem 0 .55rem;font-weight:700;color:var(--ink)}
.prose .q + p + .q{
  border-top:1px solid var(--line);padding-top:1.7rem;margin-top:1.7rem;
}
.prose .q ~ h3{margin-top:3.4rem}
.prose .q ~ hr{margin:2.6rem 0 2rem}
.prose .q + p{margin-top:0}
.prose .q::before,.prose .q + p::before{
  flex:none;width:1.1em;font-weight:700;font-size:.82em;line-height:1.9;
  letter-spacing:.06em;color:var(--accent);
}
.prose .q::before{content:"Q"}
.prose .q + p::before{content:"A"}


/* The strip spans two columns, so it is wide for three small items. The old
   ratios gave the widest column to a single button and pinned every column's
   content to the left, which pooled all the empty space on the right of each
   one and read as stretched. Even thirds with the content centred spreads the
   air symmetrically instead. */

/* The releases column is taller than song of the week and events, so the
   roster panel fills the space under those two rather than leaving it blank. */
.panels{grid-template-rows:auto auto}
.panels > .panel.wide{grid-row:1 / span 2}
.panels > .panel.roster{grid-column:2 / span 2;grid-row:2}
/* One row of small tiles, sized so the panel fills the gap under song of the
   week and events without overshooting the releases column beside it. */
.rostgrid.mini{grid-template-columns:repeat(6,1fr);gap:10px}
.rostgrid.mini .rostart{aspect-ratio:auto;height:78px}
.rostgrid.mini .rostbody{padding:8px 9px 10px}
.rostgrid.mini .rostbody h3{font-size:.76rem}
.rostgrid.mini .rostbody .aka{display:none}
@media(max-width:1180px){
  .panels > .panel.wide{grid-row:auto}
  .panels > .panel.roster{grid-column:1 / span 2;grid-row:auto}
}
@media(max-width:760px){
  .panels > .panel.roster{grid-column:1}
  .rostgrid.mini{grid-template-columns:repeat(2,1fr)}
}

/* ---------- Filter Cup ---------- */
/* Roulé fights in pink, Crydamoure in blue, everywhere on the page. */
.cup-board{display:flex;gap:12px;flex-wrap:wrap;margin:1.4rem 0 .6rem}
.cup-board > div{flex:1;min-width:220px;border:1px solid var(--line);border-radius:12px;padding:14px 18px;background:var(--panel)}
.cup-board .lab-a{border-top:2px solid var(--pink)}
.cup-board .lab-b{border-top:2px solid #4fa3ff}
.cup-score{display:block;font-size:1.25rem;font-weight:700}
.cup-board em{display:block;font-style:normal;font-size:.8rem;color:var(--dim);margin-top:2px}
.cup-progress{font-size:.85rem;color:var(--dim);margin:.4rem 0 1rem}
.cup-roundnav{display:flex;gap:8px;flex-wrap:wrap;margin:0 0 1.6rem}
.cup-roundnav a{font-size:.78rem;font-weight:500;color:var(--dim);border:1px solid var(--line);border-radius:100px;padding:.35rem .85rem;transition:color .15s,border-color .15s}
.cup-roundnav a:hover{color:var(--ink);border-color:var(--accent)}
.cup-roundnav a.on{color:var(--ink);border-color:var(--accent);background:var(--accent-soft)}
.cup-rules{margin:0 0 1rem}
.cup-ties{display:grid;gap:22px;margin:0 0 2.5rem}
.cup-tie{border:1px solid var(--line);border-radius:14px;padding:20px;background:var(--panel)}
.cup-tiehead{display:flex;gap:10px;align-items:center;margin-bottom:14px}
.cup-tiehead strong{font-size:.95rem}
.cup-matchup{display:grid;grid-template-columns:1fr auto 1fr;gap:12px;align-items:stretch}
@media(max-width:640px){.cup-matchup{grid-template-columns:1fr}.cup-vs{margin:2px auto}}
.cup-vs{align-self:center;font-weight:700;font-size:.75rem;letter-spacing:.1em;color:var(--dimmer);border:1px solid var(--line);border-radius:50%;width:44px;height:44px;display:grid;place-items:center;background:var(--bg)}
.cup-track{border:1px solid var(--line);border-radius:10px;overflow:hidden;background:var(--bg);display:flex;flex-direction:column}
.cup-track.lab-a{border-top:2px solid var(--pink)}
.cup-track.lab-b{border-top:2px solid #4fa3ff}
.cupthumb{aspect-ratio:16/8;background-size:cover;background-position:center}
.cup-trackbody{padding:14px 16px 16px;display:flex;flex-direction:column;gap:0;flex:1}
.cup-trackbody .tag{align-self:flex-start}
.cup-trackbody .tag.lab-a{background:var(--pink-soft);color:#ff9ab5}
.cup-trackbody .tag.lab-b{background:rgba(79,163,255,.15);color:#9cc8ff}
.cup-track h4{margin:.55rem 0 .15rem;font-size:1rem;line-height:1.3}
.cup-artist{margin:0;color:var(--dim);font-size:.86rem}
.cup-cat{margin:.3rem 0 .8rem;font-size:.76rem;color:var(--dimmer)}
.cuplisten{margin-top:auto;font-size:.82rem;font-weight:500;color:var(--accent)}
.cuplisten:hover{text-decoration:underline}
.cup-play{margin:.8rem -16px -16px;border-top:1px solid var(--line);background:#000}
.cup-play iframe{display:block;width:100%;height:190px;border:0}
.cup-nolink{margin:.8rem 0 0;font-size:.82rem}
.cup-nolink a{color:var(--accent);font-weight:500}
.cup-nolink a:hover{text-decoration:underline}
.cup-track.won{border-color:var(--accent);border-top-color:var(--accent)}
.cup-track.lost{opacity:.55}
.cup-track.tbd{display:flex;align-items:center;justify-content:center;min-height:180px;color:var(--dimmer);font-size:.85rem;border-style:dashed}
.cup-vote{margin-top:14px;display:grid;gap:8px}
.cup-vote .pollchoice{position:relative;overflow:hidden;isolation:isolate;display:flex;justify-content:space-between;align-items:center;gap:10px;width:100%;text-align:left;font:inherit;font-size:.86rem;font-weight:500;color:var(--ink);background:var(--bg);border:1px solid var(--line);border-radius:9px;padding:.6rem .9rem;cursor:pointer}
.cup-vote .pollchoice::before{content:"";position:absolute;z-index:-1;inset:0 auto 0 0;width:var(--poll-result,0%);background:rgba(139,107,255,.18);transition:width .35s ease}
.cup-vote .pollchoice:hover:not(:disabled){border-color:rgba(139,107,255,.65)}
.cup-vote .pollchoice.picked{border-color:var(--accent)}
.cup-vote .pollchoice:disabled{cursor:default}
.cup-vote .pollchoice b{font-size:.78rem;color:var(--accent)}
.cup-vote .pollnote{margin:.2rem 0 0;color:var(--dimmer);font-size:.78rem}
.cup-through{margin:1rem 0 0;font-size:.88rem}
.cup-through::before{content:"✓ ";color:var(--accent);font-weight:700}
.cup-ties.decided .cup-tie,.cup-ties.upcoming .cup-tie{padding:16px 18px}
.cup-entry{display:flex;gap:12px;align-items:center;padding:10px 18px;border-bottom:1px solid var(--line)}
.cup-entry:last-child{border-bottom:0}
.cup-entry .main{flex:1;min-width:0}
.cup-entry .t{font-weight:500;font-size:.9rem}
.cup-entry .s{font-size:.78rem;color:var(--dim)}
