:root{
    color-scheme: dark;
    /* ---- tokens: dark (default) ---- */
    --surface-0:#14100f;
    --surface-1:#1c1615;
    --surface-2:#241c1a;
    --surface-3:#2c2320;
    --surface-hover: rgba(243,236,228,0.05);
    --outline: rgba(243,236,228,0.10);
    --outline-strong: rgba(243,236,228,0.18);
    --ink:#f3ece4;
    --ink-dim:#b7a99e;
    --ink-faint:#7d7168;
    --accent:#e14a2e;        /* on-air red */
    --accent-ink:#fff5f2;
    --accent-2:#4fb6ac;      /* tuning teal */
    --accent-2-ink:#06201d;
    --good:#6fae7c;
    --good-bg: rgba(111,174,124,0.14);
    --warn:#e0a63a;
    --warn-bg: rgba(224,166,58,0.14);
    --danger:#e8604a;
    --danger-bg: rgba(232,96,74,0.14);
    --shadow: 0 1px 2px rgba(0,0,0,0.5), 0 4px 16px rgba(0,0,0,0.35);
    /* raised-card elevation: top highlight rim + contact shadow + soft ambient */
    --elev-1: inset 0 1px 0 rgba(255,255,255,0.05), 0 1px 2px rgba(0,0,0,0.45), 0 6px 16px -4px rgba(0,0,0,0.55);
    --elev-2: inset 0 1px 0 rgba(255,255,255,0.07), 0 2px 4px rgba(0,0,0,0.45), 0 14px 30px -8px rgba(0,0,0,0.6);
    --font-display: 'Arial Narrow', 'Helvetica Neue Condensed', 'Roboto Condensed', sans-serif;
    --font-body: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    --font-mono: ui-monospace, 'SF Mono', 'Cascadia Code', 'Roboto Mono', monospace;
  }

  @media (prefers-color-scheme: light){
    :root{
      color-scheme: light;
      --surface-0:#f6f1ea;
      --surface-1:#ffffff;
      --surface-2:#efe6da;
      --surface-3:#e6dacb;
      --surface-hover: rgba(30,20,15,0.04);
      --outline: rgba(30,20,15,0.10);
      --outline-strong: rgba(30,20,15,0.20);
      --ink:#231a15;
      --ink-dim:#5b4c42;
      --ink-faint:#8a7b6f;
      --accent:#c8371e;
      --accent-ink:#fff5f2;
      --accent-2:#0d7d72;
      --accent-2-ink:#eafffb;
      --good:#2f7a41;
      --good-bg: rgba(47,122,65,0.12);
      --warn:#a8730f;
      --warn-bg: rgba(168,115,15,0.14);
      --danger:#c8371e;
      --danger-bg: rgba(200,55,30,0.10);
      --shadow: 0 1px 2px rgba(30,20,10,0.08), 0 6px 20px rgba(30,20,10,0.08);
      --elev-1: inset 0 1px 0 rgba(255,255,255,0.55), 0 1px 2px rgba(30,20,10,0.10), 0 6px 16px -4px rgba(30,20,10,0.16);
      --elev-2: inset 0 1px 0 rgba(255,255,255,0.65), 0 2px 4px rgba(30,20,10,0.12), 0 14px 30px -8px rgba(30,20,10,0.22);
    }
  }
  :root[data-theme="dark"]{
    color-scheme: dark;
    --surface-0:#14100f; --surface-1:#1c1615; --surface-2:#241c1a; --surface-3:#2c2320;
    --surface-hover: rgba(243,236,228,0.05);
    --outline: rgba(243,236,228,0.10); --outline-strong: rgba(243,236,228,0.18);
    --ink:#f3ece4; --ink-dim:#b7a99e; --ink-faint:#7d7168;
    --accent:#e14a2e; --accent-ink:#fff5f2; --accent-2:#4fb6ac; --accent-2-ink:#06201d;
    --good:#6fae7c; --good-bg: rgba(111,174,124,0.14);
    --warn:#e0a63a; --warn-bg: rgba(224,166,58,0.14);
    --danger:#e8604a; --danger-bg: rgba(232,96,74,0.14);
    --shadow: 0 1px 2px rgba(0,0,0,0.5), 0 4px 16px rgba(0,0,0,0.35);
    /* raised-card elevation: top highlight rim + contact shadow + soft ambient */
    --elev-1: inset 0 1px 0 rgba(255,255,255,0.05), 0 1px 2px rgba(0,0,0,0.45), 0 6px 16px -4px rgba(0,0,0,0.55);
    --elev-2: inset 0 1px 0 rgba(255,255,255,0.07), 0 2px 4px rgba(0,0,0,0.45), 0 14px 30px -8px rgba(0,0,0,0.6);
  }
  :root[data-theme="light"]{
    color-scheme: light;
    --surface-0:#f6f1ea; --surface-1:#ffffff; --surface-2:#efe6da; --surface-3:#e6dacb;
    --surface-hover: rgba(30,20,15,0.04);
    --outline: rgba(30,20,15,0.10); --outline-strong: rgba(30,20,15,0.20);
    --ink:#231a15; --ink-dim:#5b4c42; --ink-faint:#8a7b6f;
    --accent:#c8371e; --accent-ink:#fff5f2; --accent-2:#0d7d72; --accent-2-ink:#eafffb;
    --good:#2f7a41; --good-bg: rgba(47,122,65,0.12);
    --warn:#a8730f; --warn-bg: rgba(168,115,15,0.14);
    --danger:#c8371e; --danger-bg: rgba(200,55,30,0.10);
    --shadow: 0 1px 2px rgba(30,20,10,0.08), 0 6px 20px rgba(30,20,10,0.08);
      --elev-1: inset 0 1px 0 rgba(255,255,255,0.55), 0 1px 2px rgba(30,20,10,0.10), 0 6px 16px -4px rgba(30,20,10,0.16);
      --elev-2: inset 0 1px 0 rgba(255,255,255,0.65), 0 2px 4px rgba(30,20,10,0.12), 0 14px 30px -8px rgba(30,20,10,0.22);
  }

  *{box-sizing:border-box;}
  html,body{margin:0;padding:0;}
  body{
    background:var(--surface-0);
    color:var(--ink);
    font-family:var(--font-body);
    -webkit-font-smoothing:antialiased;
    min-height:100vh;
    overflow-x:hidden;
  }
  a{color:var(--accent-2);}
  button{font-family:inherit;}

  .skip-link{position:absolute;left:-9999px;top:0;background:var(--accent);color:var(--accent-ink);padding:.6rem 1rem;border-radius:0 0 8px 0;z-index:200;}
  .skip-link:focus{left:0;}

  /* off-canvas for sighted users, still read by assistive tech */
  .visually-hidden{
    position:absolute; width:1px; height:1px; margin:-1px; padding:0;
    overflow:hidden; clip-path:inset(50%); white-space:nowrap; border:0;
  }

  :focus-visible{outline:2px solid var(--accent-2); outline-offset:2px;}

  /* ---------------- App bar ---------------- */
  .appbar{
    position:sticky; top:0; z-index:50;
    background:color-mix(in srgb, var(--surface-1) 92%, transparent);
    backdrop-filter:blur(10px);
    border-bottom:1px solid var(--outline);
    box-shadow:var(--shadow);
  }
  .appbar-inner{
    max-width:1180px; margin:0 auto;
    display:flex; align-items:center; gap:.9rem;
    padding:.7rem 1rem;
  }
  .brand{display:flex; align-items:center; gap:.6rem; text-decoration:none; color:var(--ink); flex:0 0 auto;}
  .brand-text{display:flex; flex-direction:column; align-items:flex-start; gap:.25rem; line-height:1.05;}
  /* Station wordmark: fixed height, width follows the 1024x248 source aspect. */
  .brand-logo{display:block; height:24px; width:auto; border-radius:3px;}
  .brand-name{font-family:var(--font-mono); font-variant-numeric:tabular-nums; text-transform:uppercase; letter-spacing:.06em; font-size:.62rem; color:var(--ink-dim);}

  /* ---------------- Hero logo lockup ---------------- */
  .hero-lockup{display:flex; flex-direction:column; align-items:flex-start; gap:.55rem;}
  .hero-logo{
    display:block; width:auto; border-radius:5px;
    height:clamp(46px, 3.4vw + 34px, 68px);
    box-shadow:var(--shadow);
  }
  .hero-sub{font-family:var(--font-mono); font-variant-numeric:tabular-nums; text-transform:uppercase; letter-spacing:.08em; font-size:.72rem; color:var(--accent-2);}

  .live-strip{
    display:flex; align-items:center; gap:.65rem; min-width:0; flex:0 1 420px;
    /* lifted off the appbar: gentle top-lit gradient + material elevation */
    background:linear-gradient(180deg, color-mix(in srgb, var(--ink) 5%, var(--surface-3)), var(--surface-3));
    border:1px solid var(--outline-strong);
    border-radius:12px; padding:.4rem .9rem .4rem .4rem; cursor:pointer;
    text-align:left; font-family:inherit; color:var(--ink);
    box-shadow:var(--elev-1);
    transition:background .15s ease, box-shadow .18s ease, transform .18s ease;
  }
  .live-strip:hover{
    background:linear-gradient(180deg, color-mix(in srgb, var(--ink) 10%, var(--surface-3)), color-mix(in srgb, var(--ink) 4%, var(--surface-3)));
    box-shadow:var(--elev-2);
    transform:translateY(-1px);
  }
  .live-strip:active{ transform:translateY(0); box-shadow:var(--elev-1); }
  @media (prefers-reduced-motion:reduce){ .live-strip, .live-strip:hover{ transform:none; } }
  .live-play{
    width:40px;height:40px;border-radius:50%;flex:none;
    background:var(--accent); display:flex; align-items:center; justify-content:center;
    box-shadow:0 2px 6px color-mix(in srgb, var(--accent) 45%, transparent);
    transition:transform .12s ease, background .15s ease;
  }
  .live-strip:hover .live-play{ transform:scale(1.06); }
  .live-strip:hover .live-play{ background:color-mix(in srgb, var(--accent) 90%, white); }
  .live-play svg{width:17px;height:17px; fill:#ffffff; margin-left:2px;}
  .live-play.playing svg{margin-left:0;}
  .live-play.loading svg{display:none;}
  .live-play .spinner{display:none;}
  .live-play.loading .spinner{
    display:block; width:18px;height:18px; border-radius:50%;
    border:2px solid rgba(255,255,255,.35); border-top-color:#fff;
    animation:spin .7s linear infinite;
  }
  @keyframes spin{ to{ transform:rotate(360deg); } }
  @media (prefers-reduced-motion:reduce){ .live-play.loading .spinner{animation-duration:1.4s;} }
  .live-art{
    width:40px;height:40px;border-radius:8px;flex:none; overflow:hidden;
    /* falls back to the station mark until the show photo loads */
    background:url("/assets/icon-256.png") center/cover no-repeat;
  }
  .live-art img{width:100%;height:100%;object-fit:cover; display:none;}
  .live-art img.loaded{display:block;}
  .live-copy{display:flex; flex-direction:column; min-width:0; line-height:1.28;}
  .live-label{display:flex; align-items:center; gap:.35rem; font-family:var(--font-display); text-transform:uppercase; letter-spacing:.08em; font-size:.6rem; font-weight:700; color:var(--accent);}
  .live-label .dot{width:6px;height:6px;border-radius:50%;background:var(--accent); box-shadow:0 0 0 0 rgba(225,74,46,.6); animation:pulse 1.8s infinite; flex:none;}
  @media (prefers-reduced-motion:reduce){ .live-label .dot{animation:none;} }
  @keyframes pulse{
    0%{box-shadow:0 0 0 0 color-mix(in srgb, var(--accent) 55%, transparent);}
    70%{box-shadow:0 0 0 8px color-mix(in srgb, var(--accent) 0%, transparent);}
    100%{box-shadow:0 0 0 0 color-mix(in srgb, var(--accent) 0%, transparent);}
  }
  .live-now{font-size:.84rem; font-weight:700; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;}
  .live-next{font-size:.72rem; color:var(--ink-dim); white-space:nowrap; overflow:hidden; text-overflow:ellipsis;}
  @media (max-width:760px){ .live-next{display:none;} }
  @media (max-width:480px){ .live-strip{padding:.35rem .7rem .35rem .35rem; gap:.5rem; flex-basis:auto;} .live-play{width:36px;height:36px;} .live-art{display:none;} }

  /* push the live/on-air player (and the actions after it) to the right edge */
  .live-strip{margin-left:auto;}
  .appbar-actions{display:flex; gap:.55rem;}
  /* Tablet and up: the live player sits dead-centre in the appbar. Brand and actions
     each take an equal share of the leftover space, so the strip lands on the middle
     axis of the 1180px column rather than being shoved right. */
  @media (min-width:761px){
    /* no min-width:0 — auto min-size keeps the wordmark and donate pill from clipping
       if the viewport gets tight; centring simply gives way instead of breaking them */
    .appbar-inner .brand{flex:1 1 0;}
    .appbar-inner .appbar-actions{flex:1 1 0; justify-content:flex-end;}
    .appbar-inner .live-strip{margin-left:0; flex:0 1 440px;}
  }
  /* compact donate button in the appbar */
  .appbar-actions .btn{padding:.36rem .8rem; font-size:.76rem;}
  .appbar-actions .btn svg{width:14px;height:14px;}
  /* wordmark donate pill: deepened accent, soft sheen on hover */
  .appbar-actions .btn-donate{
    --donate:color-mix(in srgb, var(--accent) 86%, #3d0f06);
    position:relative; overflow:hidden; isolation:isolate;
    padding:.46rem 1.15rem; text-decoration:none;
    background:linear-gradient(160deg,
      color-mix(in srgb, var(--donate) 92%, white) 0%,
      var(--donate) 55%,
      color-mix(in srgb, var(--donate) 88%, black) 100%);
    box-shadow:
      0 1px 2px color-mix(in srgb, var(--donate) 40%, transparent),
      0 4px 12px color-mix(in srgb, var(--donate) 26%, transparent),
      inset 0 1px 0 rgba(255,255,255,.22);
  }
  /* diagonal highlight that sweeps across on hover */
  .appbar-actions .btn-donate::after{
    content:""; position:absolute; inset:0; z-index:-1;
    background:linear-gradient(105deg, transparent 35%, rgba(255,255,255,.28) 50%, transparent 65%);
    transform:translateX(-130%);
    transition:transform .55s ease;
  }
  .appbar-actions .btn-donate:hover{
    background:linear-gradient(160deg,
      color-mix(in srgb, var(--donate) 86%, white) 0%,
      color-mix(in srgb, var(--donate) 96%, white) 55%,
      var(--donate) 100%);
    transform:translateY(-1px);
    box-shadow:
      0 2px 4px color-mix(in srgb, var(--donate) 42%, transparent),
      0 8px 20px color-mix(in srgb, var(--donate) 32%, transparent),
      inset 0 1px 0 rgba(255,255,255,.28);
  }
  .appbar-actions .btn-donate:hover::after{transform:translateX(130%);}
  .appbar-actions .btn-donate:active{transform:translateY(0) scale(.97);}
  @media (prefers-reduced-motion:reduce){
    .appbar-actions .btn-donate, .appbar-actions .btn-donate:hover{transform:none;}
    .appbar-actions .btn-donate::after{transition:none; display:none;}
  }
  .btn-donate .donate-label{
    font-family:var(--font-display); font-weight:800; font-size:.72rem;
    text-transform:uppercase; letter-spacing:.09em; line-height:1; text-decoration:none;
  }
  .btn{
    display:inline-flex; align-items:center; gap:.4rem; justify-content:center;
    border-radius:999px; border:1px solid transparent; cursor:pointer;
    font-size:.82rem; font-weight:600; padding:.5rem 1rem; white-space:nowrap;
    transition:transform .15s ease, background .15s ease, box-shadow .15s ease;
  }
  .btn:active{transform:scale(.97);}
  .btn-filled{background:var(--accent); color:var(--accent-ink); box-shadow:var(--shadow);}
  .btn-filled:hover{background:color-mix(in srgb, var(--accent) 88%, black);}
  .btn-tonal{background:color-mix(in srgb, var(--accent-2) 18%, var(--surface-1)); color:var(--accent-2);}
  .btn-tonal:hover{background:color-mix(in srgb, var(--accent-2) 28%, var(--surface-1));}
  .btn-icon{width:36px;height:36px;padding:0;border-radius:50%;background:transparent;color:var(--ink-dim);}
  .btn-icon:hover{background:var(--surface-hover); color:var(--ink);}
  .btn svg{width:16px;height:16px;flex:none;}

  .brand-text-label{display:none;}

  /* ---------------- Hero ---------------- */
  .hero{
    max-width:1180px; margin:0 auto; padding:1.6rem 1rem 1.8rem;
    display:flex; align-items:center; gap:2rem;
  }
  .hero-lockup{flex:none;}
  .hero-copy{flex:1 1 auto; min-width:0;}
  .hero p{color:var(--ink-dim); margin:0; max-width:none; line-height:1.55; font-size:.95rem;}
  /* stack the lockup above the copy on narrow screens */
  @media (max-width:720px){
    .hero{flex-direction:column; align-items:flex-start; gap:1rem; padding-bottom:1.4rem;}
  }

  /* ---------------- Controls ---------------- */
  .controls{
    max-width:1180px; margin:0 auto; padding:0 1rem 1rem;
    display:flex; flex-direction:column; gap:.75rem;
  }
  .search-field{
    display:flex; align-items:center; gap:.55rem;
    background:var(--surface-1); border:1px solid var(--outline-strong);
    border-radius:14px; padding:.65rem .9rem;
  }
  .search-field:focus-within{border-color:var(--accent-2); box-shadow:0 0 0 3px color-mix(in srgb, var(--accent-2) 20%, transparent);}
  .search-field svg{width:18px;height:18px;color:var(--ink-faint); flex:none;}
  .search-field input{
    border:none; outline:none; background:transparent; color:var(--ink);
    font-size:.95rem; width:100%; font-family:var(--font-body);
  }
  .search-field input::placeholder{color:var(--ink-faint);}

  .chip-row{
    display:flex; flex-wrap:wrap; gap:.5rem;
  }
  .chip{
    flex:none; border:1px solid var(--outline-strong); background:var(--surface-1);
    color:var(--ink-dim); padding:.45rem .95rem; border-radius:999px;
    font-size:.8rem; font-weight:600; cursor:pointer; white-space:nowrap;
    display:flex; align-items:center; gap:.4rem;
    transition:background .15s ease, color .15s ease, border-color .15s ease;
  }
  .chip .swatch{width:8px;height:8px;border-radius:50%; flex:none;}
  .chip[aria-pressed="true"]{
    background:color-mix(in srgb, var(--accent-2) 20%, var(--surface-1));
    border-color:var(--accent-2); color:var(--ink);
  }
  .chip:hover{border-color:var(--ink-faint);}

  .result-meta{display:flex; align-items:center; justify-content:space-between; gap:1rem; flex-wrap:wrap;}
  .result-meta-right{display:flex; align-items:center; gap:.85rem;}
  .result-count{font-size:.8rem; color:var(--ink-faint); font-family:var(--font-mono); font-variant-numeric:tabular-nums;}

  /* Segmented list / gallery view switch */
  .view-toggle{display:inline-flex; gap:2px; padding:2px; border:1px solid var(--outline-strong); border-radius:999px; background:var(--surface-1); flex:none;}
  .view-btn{
    width:32px; height:28px; padding:0; border:none; border-radius:999px;
    background:transparent; color:var(--ink-faint); cursor:pointer;
    display:inline-flex; align-items:center; justify-content:center;
    transition:background .15s ease, color .15s ease;
  }
  .view-btn svg{width:16px; height:16px;}
  .view-btn:hover{color:var(--ink);}
  .view-btn[aria-pressed="true"]{background:color-mix(in srgb, var(--accent-2) 22%, var(--surface-1)); color:var(--ink);}

  /* ---------------- Data list / table ---------------- */
  .listing{max-width:1180px; margin:0 auto; padding:0 1rem 5rem;}
  .grid{
    display:flex; flex-direction:column;
    /* clip (not hidden): hidden would make this a scroll container and strand
       the sticky header row 57px down from the top of the table. */
    border:1px solid var(--outline); border-radius:16px; overflow:clip;
    background:var(--surface-1); box-shadow:var(--shadow);
    /* reserve vertical space so the footer sits below the fold while the
       archive fetch is in flight — no jump when rows arrive. */
    min-height:min(70vh, 640px);
  }
  .row{
    display:grid;
    grid-template-columns: minmax(0,2.6fr) 1fr .85fr .95fr 44px;
    align-items:center;
    gap: .75rem 1rem;
    padding:.85rem 1.1rem;
    border-bottom:1px solid var(--outline);
  }
  .row:last-child{border-bottom:none;}
  .row.head{
    background:var(--surface-2); position:sticky; top:57px; z-index:10;
    font-family:var(--font-display); text-transform:uppercase; letter-spacing:.07em;
    font-size:.68rem; color:var(--ink-dim); font-weight:700;
  }
  .row.body:hover{background:var(--surface-hover);}
  .sortbtn{
    display:inline-flex; align-items:center; gap:.3rem; background:none; border:none;
    color:inherit; font:inherit; text-transform:inherit; letter-spacing:inherit; cursor:pointer; padding:0;
  }
  .sortbtn svg{width:11px;height:11px; opacity:.55;}
  .sortbtn[data-active="true"] svg{opacity:1; color:var(--accent-2);}

  .show-cell{display:flex; align-items:center; gap:.7rem; min-width:0;}
  /* The title + category block is itself the control that opens the info sheet,
     so the whole text column is a target, not just the little More link. */
  .show-text{ min-width:0; display:flex; flex-direction:column; align-items:flex-start; }
  .show-open{
    display:block; width:100%; min-width:0; text-align:left;
    border:0; padding:0; margin:0; background:none; color:inherit; font:inherit;
    cursor:pointer;
  }
  .show-open:hover .show-title,
  .show-open:focus-visible .show-title{ color:var(--accent-2); }
  /* the whole block lights up together — colour, never an underline */
  .show-open:hover ~ .more-link,
  .more-link:hover{ color:color-mix(in srgb, var(--accent-2) 70%, var(--ink)); }

  /* plain text link under the title, the visible cue for what the block does */
  .more-link{
    display:inline-block; margin-top:.25rem; padding:0; border:0; background:none;
    font-family:inherit; font-size:.74rem; font-weight:700; letter-spacing:.02em;
    color:var(--accent-2); cursor:pointer;
    transition:color .15s ease;
  }
  .show-thumb{
    position:relative; width:44px;height:44px;border-radius:9px; flex:none; overflow:hidden;
    /* station icon shows when a show has no photo (or its photo fails to load) */
    background:url("/assets/icon-256.png") center/cover no-repeat, var(--surface-2);
    box-shadow:inset 0 0 0 1.5px color-mix(in srgb, var(--c) 45%, transparent);
  }
  .show-thumb img{position:absolute; inset:0; width:100%; height:100%; object-fit:cover;}
  .show-thumb img.failed{display:none;}
  .show-title{font-weight:600; font-size:.92rem; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
  .show-cat{display:block; font-size:.74rem; color:var(--ink-faint); margin-top:.1rem;}
  .rss-badge{
    flex:none; width:20px;height:20px;border-radius:6px;
    background:color-mix(in srgb, var(--warn) 20%, transparent); color:var(--warn);
    display:flex; align-items:center; justify-content:center;
  }
  .rss-badge svg{width:12px;height:12px;}

  .cell-mono{font-family:var(--font-mono); font-variant-numeric:tabular-nums; font-size:.84rem; color:var(--ink-dim);}
  .cell-date b{color:var(--ink); font-weight:600; display:block; font-size:.86rem;}
  .cell-date span{color:var(--ink-faint); font-size:.76rem;}

  .retention{
    display:inline-flex; align-items:center; gap:.35rem;
    padding:.3rem .6rem; border-radius:999px; font-size:.76rem; font-weight:700;
    font-family:var(--font-mono); font-variant-numeric:tabular-nums; white-space:nowrap;
  }
  .retention.good{background:var(--good-bg); color:var(--good);}
  .retention.warn{background:var(--warn-bg); color:var(--warn);}
  .retention.danger{background:var(--danger-bg); color:var(--danger);}

  .play-btn{
    width:36px;height:36px;border-radius:50%;border:1px solid var(--outline-strong);
    background:var(--surface-2); color:var(--ink); display:flex; align-items:center; justify-content:center;
    cursor:pointer; transition:background .15s ease, color .15s ease, border-color .15s ease;
  }
  .play-btn:hover{background:var(--accent); border-color:var(--accent); color:var(--accent-ink);}
  .play-btn.loading{background:var(--surface-2); border-color:var(--outline-strong); cursor:default;}
  .play-btn svg{width:14px;height:14px;}
  .play-glyph{display:inline-flex; align-items:center; justify-content:center;}
  .btn-spin{
    display:inline-block; width:15px;height:15px; border-radius:50%;
    border:2px solid color-mix(in srgb, var(--ink) 22%, transparent); border-top-color:var(--accent-2);
    animation:spin .7s linear infinite;
  }
  @media (prefers-reduced-motion:reduce){ .btn-spin{animation-duration:1.4s;} }

  .empty{padding:3rem 1rem; text-align:center; color:var(--ink-faint);}

  /* Centered load state while the archive fetch resolves. Grows to fill the
     grid's reserved min-height so the spinner sits mid-panel. */
  /* NOTE: keep this scoped to .loading-panel — a bare `.loading` selector also
     matches the play buttons, which toggle a `loading` class while buffering. */
  .loading-panel{
    flex:1 1 auto;
    display:flex; flex-direction:column; align-items:center; justify-content:center;
    gap:1rem; padding:4rem 1rem; color:var(--ink-faint);
  }
  .loading-panel[hidden]{display:none;}
  .loading-spinner{
    width:40px; height:40px; border-radius:50%;
    border:3px solid color-mix(in srgb, var(--ink) 12%, transparent);
    border-top-color:var(--accent-2);
    animation:spin .7s linear infinite;
  }
  .loading-text{
    font-family:var(--font-display); font-size:.72rem; font-weight:700;
    text-transform:uppercase; letter-spacing:.12em; color:var(--ink-dim);
  }
  @media (prefers-reduced-motion:reduce){ .loading-spinner{animation-duration:1.4s;} }

  .scroll-sentinel{height:1px;}

  /* ---------------- Hamburger button ---------------- */
  .menu-btn{
    width:42px; height:42px; border-radius:12px; flex:none;
    display:inline-flex; align-items:center; justify-content:center;
    background:var(--surface-3); border:1px solid var(--outline-strong);
    color:var(--ink); cursor:pointer;
    transition:background .15s ease, border-color .15s ease;
  }
  .menu-btn:hover{ background:color-mix(in srgb, var(--ink) 6%, var(--surface-3)); border-color:var(--accent-2); }
  .menu-btn-lines{ display:flex; flex-direction:column; gap:4px; width:18px; }
  .menu-btn-lines span{ display:block; height:2px; border-radius:2px; background:currentColor; transition:transform .28s cubic-bezier(.4,0,.2,1), opacity .18s ease; }
  .menu-btn[aria-expanded="true"] .menu-btn-lines span:nth-child(1){ transform:translateY(6px) rotate(45deg); }
  .menu-btn[aria-expanded="true"] .menu-btn-lines span:nth-child(2){ opacity:0; }
  .menu-btn[aria-expanded="true"] .menu-btn-lines span:nth-child(3){ transform:translateY(-6px) rotate(-45deg); }
  @media (prefers-reduced-motion:reduce){ .menu-btn-lines span{transition:none;} }

  /* ---------------- Slide-out menu drawer ---------------- */
  .menu-scrim{
    position:fixed; inset:0; z-index:150;
    background:color-mix(in srgb, #000 55%, transparent);
    -webkit-backdrop-filter:blur(4px); backdrop-filter:blur(4px);
    opacity:0; visibility:hidden; pointer-events:none;
    transition:opacity .25s ease, visibility 0s linear .25s;
  }
  .menu-scrim.show{ opacity:1; visibility:visible; pointer-events:auto; transition:opacity .25s ease; }

  .menu-panel{
    position:fixed; top:0; right:0; z-index:160;
    height:100dvh; width:min(400px, 92vw);
    display:flex; flex-direction:column;
    background:var(--surface-1); border-left:1px solid var(--outline);
    box-shadow:-24px 0 60px rgba(0,0,0,.45);
    transform:translateX(100%); visibility:hidden;
    transition:transform .34s cubic-bezier(.4,0,.2,1), visibility 0s linear .34s;
    will-change:transform;
  }
  .menu-panel.show{ transform:translateX(0); visibility:visible; transition:transform .34s cubic-bezier(.4,0,.2,1); }
  @media (prefers-reduced-motion:reduce){
    .menu-scrim, .menu-panel{ transition-duration:0s; }
  }
  body.menu-open{ overflow:hidden; }

  .menu-head{
    flex:none; display:flex; align-items:center; justify-content:space-between; gap:1rem;
    padding:1rem 1.1rem 1rem 1.3rem; border-bottom:1px solid var(--outline);
  }
  .menu-logo{ height:22px; }
  .menu-close{
    width:38px; height:38px; flex:none; border-radius:50%;
    border:1px solid var(--outline-strong); background:var(--surface-2); color:var(--ink);
    display:flex; align-items:center; justify-content:center; cursor:pointer;
    transition:background .15s ease, color .15s ease, border-color .15s ease;
  }
  .menu-close:hover{ background:var(--accent); border-color:var(--accent); color:var(--accent-ink); }
  .menu-close svg{ width:16px; height:16px; }

  .menu-body{
    flex:1 1 auto; overflow-y:auto; -webkit-overflow-scrolling:touch;
    padding:1.4rem 1.3rem 2rem; display:flex; flex-direction:column; gap:1.7rem;
  }
  .menu-brand{ display:flex; flex-direction:column; gap:.9rem; }
  .menu-brand p{ margin:0; font-size:.84rem; color:var(--ink-dim); line-height:1.55; }

  .menu-nav{ display:flex; flex-direction:column; gap:1.5rem; }
  .menu-group h2{
    font-family:var(--font-display); text-transform:uppercase; letter-spacing:.08em;
    font-size:.66rem; font-weight:700; color:var(--ink-faint); margin:0 0 .55rem;
  }
  .menu-group ul{ list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:.1rem; }
  .menu-group a{
    display:block; padding:.55rem .65rem; margin:0 -.65rem; border-radius:9px;
    color:var(--ink); text-decoration:none; font-size:.92rem;
    transition:background .15s ease, color .15s ease;
  }
  .menu-group a:hover{ background:var(--surface-hover); color:var(--accent-2); }

  .social-row{display:flex; gap:.5rem; flex-wrap:wrap;}
  .social-btn{
    width:36px;height:36px;border-radius:50%; border:1px solid var(--outline-strong);
    display:flex; align-items:center; justify-content:center; color:var(--ink-dim);
    text-decoration:none; transition:background .15s ease, color .15s ease, border-color .15s ease;
  }
  .social-btn:hover{background:var(--accent-2); border-color:var(--accent-2); color:var(--accent-2-ink);}
  .social-btn svg{width:16px;height:16px;}

  .menu-foot{
    border-top:1px solid var(--outline); padding-top:1.2rem;
    display:flex; flex-direction:column; gap:.5rem;
  }
  .menu-foot p{ margin:0; font-size:.78rem; color:var(--ink-faint); }
  .menu-note{ line-height:1.5; }
  .menu-note a{ color:var(--ink-faint); text-decoration:underline; }

  /* ---------------- Show info sheet ---------------- */
  /* Same scrim treatment as the drawer, but the panel is a centered card. */
  .sheet-scrim{
    position:fixed; inset:0; z-index:170;
    background:color-mix(in srgb, #000 62%, transparent);
    -webkit-backdrop-filter:blur(5px); backdrop-filter:blur(5px);
    opacity:0; visibility:hidden; pointer-events:none;
    transition:opacity .22s ease, visibility 0s linear .22s;
  }
  .sheet-scrim.show{ opacity:1; visibility:visible; pointer-events:auto; transition:opacity .22s ease; }

  .sheet{
    position:fixed; z-index:180; left:50%; top:50%;
    width:min(680px, 92vw); max-height:min(88dvh, 760px);
    display:flex; flex-direction:column; overflow:hidden;
    background:var(--surface-1); color:var(--ink);
    border:1px solid var(--outline-strong); border-radius:18px;
    box-shadow:0 30px 70px -20px rgba(0,0,0,.7), var(--elev-2);
    transform:translate(-50%, -46%) scale(.97); opacity:0; visibility:hidden;
    transition:transform .22s cubic-bezier(.2,0,.2,1), opacity .22s ease, visibility 0s linear .22s;
  }
  .sheet.show{
    transform:translate(-50%, -50%) scale(1); opacity:1; visibility:visible;
    transition:transform .22s cubic-bezier(.2,0,.2,1), opacity .22s ease;
  }
  @media (prefers-reduced-motion:reduce){
    .sheet-scrim, .sheet{ transition-duration:0s; }
    .sheet{ transform:translate(-50%,-50%) scale(1); }
  }
  body.sheet-open{ overflow:hidden; }
  /* leave room for the docked player bar so the card never sits on top of it */
  body.has-player .sheet{ max-height:min(76dvh, 700px); }

  .sheet-close{
    position:absolute; top:.85rem; right:.85rem; z-index:2;
    width:36px; height:36px; border-radius:50%;
    border:1px solid var(--outline-strong); background:var(--surface-2); color:var(--ink-dim);
    display:flex; align-items:center; justify-content:center; cursor:pointer;
    transition:background .15s ease, color .15s ease, border-color .15s ease;
  }
  .sheet-close:hover{ background:var(--accent); border-color:var(--accent); color:var(--accent-ink); }
  .sheet-close svg{ width:15px; height:15px; }

  .sheet-body{
    flex:1 1 auto; min-height:0; overflow-y:auto; -webkit-overflow-scrolling:touch;
    padding:1.6rem 1.6rem 1.4rem;
    display:flex; flex-direction:column; gap:1.3rem;
  }
  /* Controls live outside the scroll area: however long the description runs,
     Play, the links and the scrubber stay put at the bottom of the card. */
  .sheet-foot{
    flex:none; display:flex; flex-direction:column; gap:.85rem;
    padding:1.1rem 1.6rem 1.3rem; border-top:1px solid var(--outline);
    background:var(--surface-1); border-radius:0 0 17px 17px;
  }
  .sheet-foot:empty{ display:none; }

  /* header: large artwork beside the title block */
  /* centred so a title with no host or description doesn't float against the
     top of the much taller artwork */
  .sheet-head{ display:flex; gap:1.3rem; align-items:center; padding-right:2.6rem; }
  .sheet-art{
    position:relative; flex:none; width:168px; height:168px; border-radius:14px; overflow:hidden;
    background:url("/assets/icon-256.png") center/cover no-repeat, var(--surface-2);
    box-shadow:inset 0 0 0 1.5px color-mix(in srgb, var(--c, var(--accent)) 45%, transparent), var(--elev-1);
  }
  .sheet-art img{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover; }
  .sheet-art img.failed{ display:none; }
  .sheet-titles{ display:flex; flex-direction:column; gap:.5rem; min-width:0; padding-top:.15rem; }
  .sheet-eyebrow{
    display:inline-flex; align-items:center; gap:.4rem; align-self:flex-start;
    font-family:var(--font-display); text-transform:uppercase; letter-spacing:.08em;
    font-size:.66rem; font-weight:700; color:var(--ink-dim);
  }
  .sheet-eyebrow .swatch{ width:8px; height:8px; border-radius:50%; background:var(--c, var(--accent)); flex:none; }
  #sheetTitle{
    font-family:var(--font-display); font-weight:700; letter-spacing:.01em;
    font-size:clamp(1.3rem, 1.05rem + 1.1vw, 1.7rem); line-height:1.15;
    margin:0; text-wrap:balance;
  }
  .sheet-host{ font-size:.9rem; color:var(--accent-2); }

  .sheet-desc-wrap{ display:flex; flex-direction:column; align-items:flex-start; gap:.4rem; }
  .sheet-desc{
    margin:0; color:var(--ink-dim); font-size:.94rem; line-height:1.6;
    /* clamped until the reader asks for the rest */
    display:-webkit-box; -webkit-box-orient:vertical; -webkit-line-clamp:7; overflow:hidden;
  }
  .sheet-desc-wrap.expanded .sheet-desc{ -webkit-line-clamp:none; overflow:visible; }
  .desc-toggle{
    padding:0; border:0; background:none; font-family:inherit;
    font-size:.78rem; font-weight:700; color:var(--accent-2); cursor:pointer;
    transition:color .15s ease;
  }
  .desc-toggle:hover{ color:color-mix(in srgb, var(--accent-2) 60%, var(--ink)); }

  /* meta list — only the rows with content are rendered at all */
  .sheet-meta{
    display:grid; grid-template-columns:auto 1fr; gap:.55rem 1.1rem;
    margin:0; padding:1.1rem 0 0; border-top:1px solid var(--outline);
    font-size:.88rem;
  }
  .sheet-meta dt{
    font-family:var(--font-display); text-transform:uppercase; letter-spacing:.07em;
    font-size:.66rem; font-weight:700; color:var(--ink-faint); padding-top:.18rem;
  }
  .sheet-meta dd{ margin:0; color:var(--ink); }
  .sheet-meta dd .mono{ font-family:var(--font-mono); font-variant-numeric:tabular-nums; }

  .sheet-actions{ display:flex; align-items:center; gap:.6rem; flex-wrap:wrap; }
  /* same scrubber markup as the docked player, sitting under the actions */
  .sheet-scrub[hidden]{ display:none; }
  /* also carries .play-btn so updatePlayButtons() keeps its glyph and label in
     step — width/height undo the round 36px icon button that class implies */
  .sheet-play{
    display:inline-flex; align-items:center; gap:.5rem; cursor:pointer;
    width:auto; height:auto;
    border:1px solid transparent; border-radius:999px; padding:.6rem 1.2rem;
    background:var(--accent); color:var(--accent-ink); font-family:inherit;
    font-size:.88rem; font-weight:700; box-shadow:var(--shadow);
    transition:background .15s ease, transform .12s ease;
  }
  .sheet-play:hover{ background:color-mix(in srgb, var(--accent) 88%, black); }
  .sheet-play:active{ transform:scale(.97); }
  .sheet-play svg{ width:15px; height:15px; }
  .sheet-link{
    display:inline-flex; align-items:center; gap:.4rem;
    border:1px solid var(--outline-strong); border-radius:999px; padding:.55rem 1rem;
    color:var(--ink-dim); text-decoration:none; font-size:.84rem; font-weight:600;
    transition:background .15s ease, color .15s ease, border-color .15s ease;
  }
  .sheet-link:hover{ background:var(--surface-hover); color:var(--accent-2); border-color:var(--accent-2); }
  .sheet-link svg{ width:14px; height:14px; }

  /* Phones: dock it to the bottom as a sheet that slides up. */
  @media (max-width:560px){
    .sheet{
      left:0; top:auto; bottom:0; width:100%; max-height:90dvh;
      border-radius:20px 20px 0 0; border-bottom:none;
      transform:translate(0, 100%) scale(1);
    }
    .sheet.show{ transform:translate(0, 0) scale(1); }
    .sheet-body{ padding:1.3rem 1.1rem 1.1rem; }
    .sheet-foot{ padding:.9rem 1.1rem calc(1.1rem + env(safe-area-inset-bottom,0px)); border-radius:0; }
    .sheet-head{ flex-direction:column; align-items:center; text-align:center; padding-right:0; gap:1rem; }
    .sheet-art{ width:min(220px, 60vw); height:min(220px, 60vw); }
    .sheet-titles{ align-items:center; }
    .sheet-actions{ justify-content:center; }
  }

  /* ================= Responsive ================= */
  @media (max-width: 900px){
    .row{grid-template-columns: 1fr auto;}
    .row.head{display:none;}
    .row.body{
      grid-template-columns: 1fr auto;
      grid-template-areas: "title play" "meta meta" "retention retention";
      row-gap:.5rem;
    }
    .show-cell{grid-area:title;}
    .cell-date{grid-area:meta; display:flex; gap:1rem; align-items:baseline;}
    .cell-duration{display:none;}
    .cell-duration.inline-meta{display:inline; grid-area:unset;}
    .retention{grid-area:retention; justify-self:start;}
    .appbar-actions .btn-label{display:none;}
    .btn-icon-label{display:none;}
    .appbar-actions .btn-donate{padding:.42rem .85rem;}
    .btn-donate .donate-label{font-size:.68rem; letter-spacing:.07em;}
    .listing{padding-bottom:6rem;}
  }
  @media (min-width: 901px){
    .cell-duration.inline-meta{display:none;}
  }
  @media (max-width:560px){
    .brand-logo{height:20px;}
    .appbar .brand-name{display:none;}
    .row.body{padding:.75rem .85rem;}
  }

  /* Phones: the appbar wraps to two rows — brand + actions on top, the live
     player on its own full-width row underneath so it isn't squashed. */
  @media (max-width:760px){
    .appbar-inner{flex-wrap:wrap; row-gap:.6rem; padding:.6rem .8rem;}
    .brand{order:1;}
    .appbar-actions{order:2; margin-left:auto;}
    /* The player is a primary control, not a strip — give it real height. */
    .live-strip{
      order:3; flex:1 1 100%; width:100%; margin-left:0;
      gap:.85rem; border-radius:16px;
      padding:.7rem 1.1rem .7rem .7rem;
    }
    .live-strip .live-play{width:56px; height:56px;}
    .live-strip .live-play svg{width:22px; height:22px; margin-left:3px;}
    .live-strip .live-play.playing svg{margin-left:0;}
    .live-strip .live-play.loading .spinner{width:24px; height:24px; border-width:3px;}
    /* room is back on a full-width row, so bring the artwork and next-up line back */
    .live-strip .live-art{display:block; width:56px; height:56px; border-radius:10px;}
    .live-strip .live-copy{gap:.1rem; line-height:1.35;}
    .live-strip .live-label{font-size:.66rem;}
    .live-strip .live-now{font-size:1rem;}
    .live-strip .live-next{display:block; font-size:.8rem;}
  }

  /* ---------------- Player bar ---------------- */
  body.has-player .listing{padding-bottom:11rem;}
  .player-bar{
    position:fixed; left:0; right:0; bottom:0; z-index:80;
    display:flex; align-items:center; gap:.85rem;
    background:color-mix(in srgb, var(--surface-2) 96%, transparent);
    backdrop-filter:blur(12px);
    border-top:1px solid var(--outline-strong);
    box-shadow:0 -6px 24px rgba(0,0,0,.35);
    padding:.6rem 1rem calc(.6rem + env(safe-area-inset-bottom,0px));
  }
  .player-bar[hidden]{display:none;}
  .player-toggle{
    width:42px;height:42px;border-radius:50%;border:none; flex:none;
    background:var(--accent); color:var(--accent-ink); display:flex; align-items:center; justify-content:center;
    cursor:pointer;
  }
  .player-toggle svg{width:18px;height:18px;}
  .player-art{
    width:44px; height:44px; border-radius:9px; flex:none; overflow:hidden;
    /* station icon shows if the playing show has no artwork */
    background:url("/assets/icon-256.png") center/cover no-repeat, var(--surface-3);
    box-shadow:inset 0 0 0 1px var(--outline);
  }
  .player-art img{width:100%; height:100%; object-fit:cover; display:block;}
  .player-art img.failed,
  .player-art img:not([src]){display:none;}
  .player-main{display:flex; flex-direction:column; justify-content:center; gap:.35rem; min-width:0; flex:1 1 auto;}
  .player-info{display:flex; flex-direction:column; min-width:0; line-height:1.3;}
  .player-title{font-weight:700; font-size:.88rem; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
  .player-sub{font-size:.74rem; color:var(--ink-dim); overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}

  /* ---- scrubber ---- */
  .player-scrub{display:flex; align-items:center; gap:.6rem;}
  .player-time{
    font-family:var(--font-mono); font-variant-numeric:tabular-nums;
    font-size:.72rem; color:var(--ink-dim); flex:none; min-width:5ch;
  }
  .player-time:last-child{text-align:right;}
  .player-range{
    -webkit-appearance:none; appearance:none;
    flex:1 1 auto; min-width:0; height:16px; margin:0;
    background:transparent; cursor:pointer;
  }
  .player-range:disabled{cursor:default; opacity:.5;}
  /* filled portion via a JS-set --pct (0–100) painted onto the track */
  .player-range::-webkit-slider-runnable-track{
    height:4px; border-radius:99px;
    background:linear-gradient(to right,
      var(--accent) 0 calc(var(--pct,0) * 1%),
      var(--outline-strong) calc(var(--pct,0) * 1%) 100%);
  }
  .player-range::-moz-range-track{height:4px; border-radius:99px; background:var(--outline-strong);}
  .player-range::-moz-range-progress{height:4px; border-radius:99px; background:var(--accent);}
  .player-range::-webkit-slider-thumb{
    -webkit-appearance:none; appearance:none;
    width:12px; height:12px; margin-top:-4px; border-radius:50%;
    background:var(--accent); box-shadow:0 1px 3px rgba(0,0,0,.4);
    transition:transform .12s ease;
  }
  .player-range::-moz-range-thumb{
    width:12px; height:12px; border:none; border-radius:50%;
    background:var(--accent); box-shadow:0 1px 3px rgba(0,0,0,.4);
  }
  .player-range:hover::-webkit-slider-thumb{transform:scale(1.2);}
  .player-range:focus-visible{outline:none;}
  .player-range:focus-visible::-webkit-slider-thumb{box-shadow:0 0 0 4px color-mix(in srgb, var(--accent) 35%, transparent);}
  .player-range:focus-visible::-moz-range-thumb{box-shadow:0 0 0 4px color-mix(in srgb, var(--accent) 35%, transparent);}
  .player-status{font-size:.74rem; color:var(--ink-faint); flex:0 1 auto; text-align:right; max-width:34ch;}
  .player-status a{color:var(--accent-2);}
  .player-close{
    width:38px; height:38px; border-radius:50%; border:none; flex:none;
    background:var(--surface-3); color:var(--ink-dim);
    display:flex; align-items:center; justify-content:center; cursor:pointer;
    box-shadow:inset 0 0 0 1px var(--outline);
    transition:background .15s ease, color .15s ease, box-shadow .15s ease, transform .12s ease;
  }
  .player-close:hover{background:var(--surface-hover); color:var(--ink); box-shadow:inset 0 0 0 1px var(--outline-strong);}
  .player-close:active{transform:scale(.92);}
  .player-close:focus-visible{outline:none; box-shadow:0 0 0 3px color-mix(in srgb, var(--accent-2) 35%, transparent);}
  .player-close svg{width:17px;height:17px;}
  @media (max-width:700px){
    .player-status{display:none;}
  }
  /* Tablet and up: the bar chrome still spans the viewport, but its controls sit in
     the same centered 1180px column as the listing instead of sprawling edge to edge. */
  @media (min-width:700px){
    .player-bar{
      padding-inline:max(1rem, calc((100% - 1180px) / 2 + 1rem));
    }
  }

  .play-btn.playing{background:var(--accent); border-color:var(--accent); color:var(--accent-ink);}
  .row-link{color:inherit; text-decoration:none;}
  .row-link:hover{text-decoration:underline;}
  .row-actions{display:flex; align-items:center; justify-content:flex-end; gap:.25rem;}
  @media (max-width:900px){
    .row-actions{grid-area:play;}
  }

  /* ================= Gallery (grid) view ================= */
  /* In grid mode the sticky column-header row is meaningless, and #rows becomes a
     responsive card grid instead of a stack of table rows. */
  body.view-grid .row.head{display:none;}
  body.view-grid #rows{
    display:grid;
    grid-template-columns:repeat(5, 1fr);
    gap:1.4rem 1.1rem;
    padding:1.4rem;
  }
  @media (max-width:1040px){ body.view-grid #rows{grid-template-columns:repeat(4, 1fr);} }
  @media (max-width:820px){ body.view-grid #rows{grid-template-columns:repeat(3, 1fr);} }
  @media (max-width:560px){ body.view-grid #rows{grid-template-columns:repeat(2, 1fr); gap:1.1rem .9rem; padding:1rem;} }

  /* The card button can't contain another button, so the More link is a sibling
     inside this wrapper, sitting in the overlay just under the card title. */
  .card-wrap{position:relative; display:block;}
  .card-more{
    position:absolute; left:.7rem; bottom:.6rem; z-index:5; margin-top:0;
    color:color-mix(in srgb, var(--accent-2) 45%, white);
    text-shadow:0 1px 3px rgba(0,0,0,.7);
  }
  .card-wrap:hover .card-more,
  .card-more:hover{ color:#fff; }

  /* The whole square is the play button; the image sits on top of the category
     placeholder, with the title, a play glyph, and a retention badge layered over
     it. No text sits below the image — the card is just the artwork. */
  .card.card-art.play-btn{
    position:relative; display:block; width:100%; height:auto; aspect-ratio:1/1;
    padding:0; border-radius:14px; overflow:hidden; cursor:pointer; text-align:left;
    border:1px solid var(--outline);
    background:url("/assets/icon-256.png") center/cover no-repeat, var(--surface-2);
    box-shadow:inset 0 0 0 1.5px color-mix(in srgb, var(--c) 45%, transparent);
    transition:transform .18s ease, box-shadow .18s ease;
  }
  /* hover is tracked on the wrapper, so the card still lifts when the pointer is
     over the title block sitting on top of it */
  .card.card-art.play-btn:hover,
  .card-wrap:hover .card.card-art.play-btn{
    background:url("/assets/icon-256.png") center/cover no-repeat, var(--surface-2);
    border-color:var(--outline); color:var(--ink);
    transform:translateY(-2px);
    box-shadow:inset 0 0 0 1.5px color-mix(in srgb, var(--c) 60%, transparent), 0 8px 22px rgba(0,0,0,.35);
  }
  .card-art img{position:absolute; inset:0; width:100%; height:100%; object-fit:cover;}
  .card-art img.failed{display:none;}

  /* Permanent gradient so the overlaid title stays legible over any artwork; it
     darkens further on hover to make the centered play glyph pop. */
  .card-fade{
    position:absolute; left:0; right:0; bottom:0; top:0; pointer-events:none;
    background:linear-gradient(to top, rgba(0,0,0,.86) 0%, rgba(0,0,0,.36) 38%, rgba(0,0,0,0) 62%);
    transition:background .18s ease;
  }
  .card-wrap:hover .card-fade,
  .card-art.play-btn:focus-visible .card-fade,
  .card-art.play-btn.playing .card-fade,
  .card-art.play-btn.loading .card-fade{
    background:linear-gradient(to top, rgba(0,0,0,.86) 0%, rgba(0,0,0,.5) 45%, rgba(0,0,0,.32) 100%);
  }

  /* a sibling of the card button, laid over its lower half: clicking the words
     opens the info sheet while the artwork behind them still plays */
  .card-overlay{
    position:absolute; left:0; right:0; bottom:0; z-index:4;
    display:flex; flex-direction:column; align-items:flex-start; gap:.15rem;
    border:0; background:none; font:inherit; text-align:left; cursor:pointer;
    /* bottom padding leaves the row for the More link below the title */
    padding:.6rem .7rem 2rem;
  }
  /* over artwork the teal is mixed toward white so it stays legible */
  .card-overlay:hover .card-title,
  .card-overlay:focus-visible .card-title{
    color:color-mix(in srgb, var(--accent-2) 55%, white);
  }
  .card-title{ transition:color .15s ease; }
  .card-eyebrow{
    font-family:var(--font-display); text-transform:uppercase; letter-spacing:.07em;
    font-size:.62rem; font-weight:700; line-height:1;
    /* var fallback keeps the eyebrow legible even if the inline --c is absent */
    color:color-mix(in srgb, var(--c, #cdd6d3) 55%, white);
    text-shadow:0 1px 2px rgba(0,0,0,.6);
  }
  .card-title{
    color:#fff; font-weight:700; font-size:.9rem; line-height:1.24;
    display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden;
    text-shadow:0 1px 3px rgba(0,0,0,.6);
  }

  .card-play{
    position:absolute; top:50%; left:50%; z-index:3;
    width:52px; height:52px; border-radius:50%;
    background:var(--accent); color:#fff;
    display:flex; align-items:center; justify-content:center;
    box-shadow:0 4px 16px rgba(0,0,0,.5);
    opacity:0; transform:translate(-50%,-50%) scale(.82);
    transition:opacity .18s ease, transform .18s ease, background .15s ease;
  }
  .card-play svg{width:19px; height:19px;}
  .card-wrap:hover .card-play,
  .card-art.play-btn:focus-visible .card-play,
  .card-art.play-btn.playing .card-play,
  .card-art.play-btn.loading .card-play{opacity:1; transform:translate(-50%,-50%) scale(1);}
  .card-art.play-btn.loading .card-play{background:var(--surface-3);}
  .card-art.play-btn .btn-spin{border-top-color:#fff;}
  /* On touch devices there's no hover, so keep the play affordance visible. */
  @media (hover:none){
    .card-play{opacity:1; transform:translate(-50%,-50%) scale(1);}
  }
  @media (prefers-reduced-motion:reduce){
    .card-art.play-btn, .card-play, .card-fade{transition:opacity .18s ease;}
    .card-art.play-btn:hover{transform:none;}
  }

  /* bottom-right, sharing the row with the More link on the left. Raised above
     the title overlay and click-through, so it never eats a tap. */
  .card-date{
    position:absolute; right:.65rem; bottom:.6rem; z-index:6; pointer-events:none;
    display:inline-flex; align-items:center; white-space:nowrap;
    background:rgba(0,0,0,.55); -webkit-backdrop-filter:blur(4px); backdrop-filter:blur(4px);
    padding:.22rem .5rem; border-radius:999px;
    font-family:var(--font-mono); font-variant-numeric:tabular-nums;
    font-size:.7rem; font-weight:600; color:#fff;
    box-shadow:0 1px 4px rgba(0,0,0,.4);
  }
