/* ─────────────────────────────────────────────────────────────
   sigzmusic.com — /music/all
   The full library: old-Spotify grouped table, left sidebar,
   full-viewport rows. Built from the approved lane-claude-b mockup.

   Tokens are the /music/css/music.css :root set, repeated here so the
   page is self-contained (it does not load the /music/ stylesheet).
   --lime is the now-playing indicator and NOTHING else.
   ───────────────────────────────────────────────────────────── */

/* Native cross-document View Transition opt-in (added 2026-08-21 with the URL
   remap). This page is served at /music; its sibling is served at /home. The
   masthead chips navigate between the two as real <a> clicks, and a
   cross-document transition needs the opt-in in BOTH documents — the other
   half lives in /music/css/enter.css, which is where the landing→/home
   cross-fade is declared too. Same three declarations, deliberately:

   - object-fit: cover — snapshots default to `fill`, and the two pages have
     different scroll heights, so `fill` taffy-stretches the snapshot.
   - 180ms linear — both pages sit on a near-identical near-black, so a short
     linear fade reads as instant with no visible seam.

   🔴 The cross-fade IS the transition. Do NOT add a JS or CSS wash on top of
   it: stacking a second layer on the native snapshots is exactly what
   produced the "taffy blob" on the landing (fixed 2026-08-21). */
@view-transition { navigation: auto; }
::view-transition-old(root),
::view-transition-new(root) {
  object-fit: cover;
  animation-duration: 180ms;
  animation-timing-function: linear;
}
@media (prefers-reduced-motion: reduce) {
  /* One frame — the navigation lands instantly, matching the landing's and
     enter.css's copies of this rule. */
  ::view-transition-old(root),
  ::view-transition-new(root) { animation-duration: 1ms; }
}

:root{
  --bg:#0B0C0F; --bg-soft:#0E0F13; --bg-raise:#14151B; --bg-hover:#1C1D25;
  --line:#23242C; --line-soft:#1A1B22;
  --text:#F2F2F4; --text-2:#A5A8B0; --text-3:#7C7F8A;
  --lime:#C6F53C;          /* now-playing indicator ONLY */
  --nc:#35E0FF;            /* current accent; player.js swaps it per release */
  /* --player, not a page-local bar height: the player bar below IS /music/'s
     bar, rules and token alike (music.css:22). --sideW is this page's own. */
  --player:84px; --sideW:220px;
  /* masthead tokens, same values as /music/css/music.css so the shared
     header measures and pads identically on both pages */
  --topbar:64px;
  --gutter:clamp(18px,4.5vw,56px);
  --ease:cubic-bezier(.22,.61,.21,1);
}
*{box-sizing:border-box;margin:0;padding:0}
html{background:var(--bg)}
body{
  font-family:"Archivo",system-ui,-apple-system,sans-serif;
  background:var(--bg); color:var(--text);
  font-size:14px; line-height:1.4;
  /* Desktop: the page itself never scrolls — the masthead is a fixed row and
     the table scrolls inside .listwrap. The bar is fixed, so its height is
     reserved with padding rather than by measuring it. */
  height:100vh; overflow:hidden;
  display:flex; flex-direction:column;
  padding-bottom:calc(var(--player) + env(safe-area-inset-bottom,0px));
  -webkit-font-smoothing:antialiased;
}
img{display:block}
button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}
a{color:inherit}
:focus-visible{outline:2px solid var(--nc); outline-offset:2px; border-radius:4px}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.skip{position:absolute;left:-9999px;top:0;z-index:200;background:var(--text);color:#0A0B0D;padding:10px 16px;font-weight:700;text-decoration:none}
.skip:focus{left:0}
.sheet[hidden]{display:none}

/* ---------- masthead: the site-wide nav bar ----------
   Every rule in this block is lifted from /music/css/music.css so the two
   pages carry one visually identical header. The only addition is a hover
   state for chips that are BUTTONS here (filters) rather than links.
   Do not "tidy" these values — they are the other page's. */
.topbar{
  position:sticky;top:0;z-index:60;
  display:flex;align-items:center;gap:12px;flex-wrap:wrap;flex:none;
  padding:13px var(--gutter);
  /* viewport-fit=cover: keep the bar clear of the status bar / notch.
     env() is 0px on desktop, so this is a no-op there. */
  padding-top:calc(13px + env(safe-area-inset-top,0px));
  /* landscape notch: left and right insets differ, pad each side with its own */
  padding-inline:max(var(--gutter),env(safe-area-inset-left,0px)) max(var(--gutter),env(safe-area-inset-right,0px));
  background:rgba(11,12,15,.86);backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);
  border-bottom:1px solid var(--line-soft);
}
.wm{font-weight:900;font-stretch:125%;font-size:22px;letter-spacing:.06em;flex:none;margin-right:4px;text-decoration:none}
.topsearch{
  display:flex;align-items:center;gap:9px;flex:0 1 300px;min-width:190px;
  background:var(--bg-raise);border:1px solid var(--line);border-radius:999px;
  padding:8px 14px;transition:border-color .15s var(--ease);
}
.topsearch:focus-within{border-color:var(--text-3)}
.topsearch svg{width:15px;height:15px;stroke:var(--text-3);fill:none;stroke-width:2;stroke-linecap:round;flex:none}
.topsearch input{flex:1;min-width:0;background:none;border:0;outline:none;color:var(--text);font:inherit;font-size:14px}
.topsearch input::placeholder{color:var(--text-3)}
.topsearch .clear-q{display:none;color:var(--text-3);font-size:16px;line-height:1;padding:2px 4px}
.topsearch .clear-q:hover{color:var(--text)}
body.searching .topsearch .clear-q{display:block}

.topctl{display:flex;align-items:center;gap:10px;min-width:0;overflow-x:auto;scrollbar-width:none}
.topctl::-webkit-scrollbar{display:none}
.chips{display:flex;gap:6px;flex:none}
.chip{
  display:inline-flex;align-items:center;justify-content:center;
  flex:none;padding:7px 15px;border-radius:999px;font-size:13px;font-weight:650;
  color:var(--text-2);background:var(--bg-raise);border:1px solid var(--line);
  text-decoration:none;
  transition:color .13s var(--ease),background .13s var(--ease),border-color .13s var(--ease);
}
a.chip:hover{color:var(--text);background:var(--bg-hover)}
/* the filter chips are buttons on this page; same hover, minus the pressed one */
button.chip:hover{color:var(--text);background:var(--bg-hover)}
.chip[aria-current="page"],.chip[aria-pressed="true"]{background:var(--text);color:#0A0B0D;border-color:var(--text)}
.chip[aria-pressed="true"]:hover{background:var(--text);color:#0A0B0D}
.chip[aria-current="page"]{cursor:default}
.top-actions{margin-left:auto;display:flex;align-items:center;gap:8px;flex:none}
.btn{
  display:inline-flex;align-items:center;gap:8px;
  padding:8px 16px;border-radius:999px;font-size:13px;font-weight:700;
  background:var(--bg-raise);border:1px solid var(--line);color:var(--text);
  transition:background .13s var(--ease),border-color .13s var(--ease),transform .13s var(--ease);
}
.btn:hover{background:var(--bg-hover);border-color:var(--text-3);transform:translateY(-1px)}
.btn svg{width:15px;height:15px;fill:currentColor;flex:none}
.btn .stroke,.icon-btn .stroke{fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
#qCount{
  min-width:20px;height:20px;border-radius:10px;display:inline-grid;place-items:center;
  background:var(--bg-hover);font-size:11.5px;font-weight:800;padding:0 6px;font-variant-numeric:tabular-nums;
}

/* ---------- app shell: sidebar + full-bleed table + fixed bar ---------- */
.shell{
  display:grid;
  grid-template-columns:var(--sideW) minmax(0,1fr);
  flex:1 1 auto;
  min-height:0;
}

/* ---------- sidebar ---------- */
aside.side{
  background:var(--bg-soft);
  border-right:1px solid var(--line);
  overflow-y:auto; overflow-x:hidden;
  padding:20px 12px 24px;
  min-width:0;
}
.side h3{
  font-size:10px; font-weight:700; letter-spacing:.12em; text-transform:uppercase;
  color:var(--text-3); padding:0 10px 8px;
}
.side .group + .group{margin-top:22px;padding-top:18px;border-top:1px solid var(--line-soft)}
.side ul{list-style:none;display:flex;flex-direction:column;gap:2px}
.navitem{
  display:block; width:100%; text-align:left;
  padding:8px 10px; border-radius:6px;
  font-size:13px; font-weight:600; color:var(--text-2);
  text-decoration:none; white-space:nowrap;
}
.navitem:hover{background:var(--bg-hover);color:var(--text)}
.navitem[aria-pressed="true"],.navitem[aria-current="true"]{background:var(--bg-hover);color:var(--text)}
.navitem[aria-pressed="true"]{box-shadow:inset 2px 0 0 var(--text)}
.sortitem[aria-pressed="true"]{box-shadow:inset 2px 0 0 var(--nc)}

/* ---------- main column ---------- */
.main{display:grid;grid-template-rows:auto auto minmax(0,1fr);min-width:0;min-height:0}
header.page{
  padding:22px 24px 16px;
  border-bottom:1px solid var(--line-soft);
  background:linear-gradient(180deg,var(--bg-soft),var(--bg));
}
.head-row{display:flex;align-items:center;gap:18px;flex-wrap:wrap}
.playall{
  width:56px;height:56px;border-radius:50%;
  background:var(--text); color:var(--bg);
  display:grid;place-items:center; flex:none;
  transition:transform .12s var(--ease);
}
.playall:hover{transform:scale(1.06)}
.playall svg{width:22px;height:22px;fill:var(--bg)}
.head-meta h1{font-size:26px;font-weight:800;letter-spacing:-.02em}
.head-meta p{color:var(--text-2);font-size:13px;margin-top:2px}
.head-meta .by{color:var(--text);font-weight:600}

/* ---------- column header ---------- */
.colhead{
  background:var(--bg); border-bottom:1px solid var(--line);
  color:var(--text-3); font-size:11px; font-weight:600;
  letter-spacing:.08em; text-transform:uppercase;
}
.grid{
  display:grid; align-items:center; gap:14px;
  grid-template-columns:36px 40px minmax(0,2.2fr) minmax(0,1fr) 110px 76px 60px 32px;
  padding:8px 24px;
}
.colhead .dur{text-align:right}
.colhead .plays,.grid .plays{text-align:right}
.clockic{width:14px;height:14px;fill:currentColor;display:inline-block;vertical-align:-2px}

/* ---------- scrolling list region (full viewport width beside the sidebar) ---------- */
.listwrap{overflow-y:auto;overflow-x:hidden;min-height:0;min-width:0}

/* ---------- sections ---------- */
.sec{margin-top:6px}
.sec-head{
  display:flex;align-items:baseline;gap:10px;
  padding:16px 24px 6px;
  border-bottom:1px solid var(--line-soft);
}
.sec-head h2{font-size:15px;font-weight:700;letter-spacing:-.01em}
.sec-head .tint{width:8px;height:8px;border-radius:2px;flex:none;align-self:center}
.sec-head .sub{color:var(--text-2);font-size:12px}
ul.rows{list-style:none}
/* nothing here sets a display on ul.rows, but state that the attribute wins
   anyway — an author `display` would silently defeat the UA [hidden] rule */
ul.rows[hidden]{display:none}


/* ---------- album preview heading (the Album sort's section head) ----------
   The record above its own tracklist: art, name set large, kind · year · track
   count beneath. Mix-year and flat headings keep the slim tinted line above. */
.sec-head.rec-head{align-items:center;gap:14px;padding:22px 24px 8px}
.sec-cov{
  position:relative;width:52px;height:52px;border-radius:5px;flex:none;overflow:hidden;
  background:linear-gradient(140deg,rgba(255,255,255,.16),rgba(0,0,0,.42)),var(--row-accent,var(--text-3));
}
.sec-cov img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.sec-txt{display:flex;flex-direction:column;gap:3px;min-width:0}
.sec-head.rec-head h2{font-size:19px;font-weight:800;letter-spacing:-.02em}

/* ---------- collapsible sections (2026-08-19) ----------
   Records ship closed; the heading IS the control. The button is an absolute
   overlay across the whole heading — nothing else in a heading is clickable —
   with the chevron at its right edge.
   These rules sit AFTER the .sec-head / .sec-head.rec-head padding above on
   purpose: .sec-head.foldable is the same specificity (0,2,0), so source order
   is what decides the padding, and the phone blocks below re-state it for the
   same reason. */
.sec-head.foldable{position:relative;padding-right:56px;cursor:pointer}
.sec-fold{
  position:absolute;inset:0;z-index:1;display:flex;align-items:center;justify-content:flex-end;
  padding-right:24px;color:var(--text-2);border-radius:0;
}
.sec-fold:hover{color:var(--text)}
.sec-chev{display:grid;place-items:center;width:24px;height:24px}
.sec-chev svg{
  width:20px;height:20px;fill:none;stroke:currentColor;stroke-width:2.2;
  stroke-linecap:round;stroke-linejoin:round;transition:transform .18s var(--ease,ease);
}
.sec-fold[aria-expanded="true"] .sec-chev svg{transform:rotate(180deg)}

/* ---------- rows ---------- */
li.row{border-radius:0;position:relative}
.rowbtn{
  width:100%; text-align:left;
  color:var(--text);
}
.rowbtn:hover,.rowbtn:focus-visible{background:var(--bg-hover)}
.idxcell{position:relative;color:var(--text-2);font-variant-numeric:tabular-nums;font-size:13px;text-align:center}
.pg{position:absolute;inset:0;display:none;place-items:center}
.pg svg{width:12px;height:12px;fill:var(--text)}
.rowbtn:hover .pg,.rowbtn:focus-visible .pg{display:grid}
.rowbtn:hover .idxnum,.rowbtn:focus-visible .idxnum{visibility:hidden}
.tcell{min-width:0}
.tname{font-weight:600;font-size:14px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.rec{color:var(--text-2);font-size:13px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.rowbtn:hover .rec{text-decoration:underline;text-decoration-color:var(--row-accent,var(--text-3));text-underline-offset:3px}
.date{color:var(--text-2);font-size:13px;white-space:nowrap}
.plays{color:var(--text-2);font-size:13px;font-variant-numeric:tabular-nums}
.dur{color:var(--text-2);font-size:13px;text-align:right;font-variant-numeric:tabular-nums}

/* ---------- queue "+" on a row ----------
   A sibling of .rowbtn, not a child: the row is itself a <button> and a
   button cannot nest. It sits over the empty .qslot column the row grid
   reserves, so it never covers the duration. */
.qadd{
  position:absolute;z-index:1;top:50%;right:14px;transform:translateY(-50%);
  width:26px;height:26px;border-radius:50%;display:grid;place-items:center;
  color:var(--text-3);font-size:16px;line-height:1;
  opacity:0;transition:opacity .14s,color .14s,background .14s;
}
li.row:hover .qadd,.qadd:focus-visible{opacity:1}
@media (hover:none){.qadd{opacity:1}}
.qadd:hover{color:var(--text);background:var(--bg-hover)}

/* ---------- cover thumb ----------
   Real art when the slug ships a cover, otherwise a plain accent-tinted
   square — never an external request. The <img> sits on top of the tint,
   so a 404 (removed by the capture-phase error listener) reveals it. */
.thumb{
  position:relative;width:40px;height:40px;border-radius:4px;flex:none;
  overflow:hidden;background:linear-gradient(140deg,rgba(255,255,255,.16),rgba(0,0,0,.42)),var(--row-accent,var(--text-3));
}
.thumb img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}

/* now playing */
li.playing .tname{color:var(--lime)}
li.playing .idxnum{display:none}
li.playing .rowbtn{background:var(--bg-raise)}
li.playing .rowbtn:hover{background:var(--bg-hover)}
li.playing .pg{display:none !important}
.eq{position:absolute;inset:0;display:none;align-items:flex-end;justify-content:center;gap:2px;padding-bottom:13px}
li.playing .eq{display:flex}
.eq i{width:3px;background:var(--lime);height:6px;border-radius:1px}
@keyframes eqb{0%,100%{height:4px}50%{height:13px}}
li.playing:not(.paused) .eq i{animation:eqb 1s ease-in-out infinite}
li.playing:not(.paused) .eq i:nth-child(2){animation-delay:.25s}
li.playing:not(.paused) .eq i:nth-child(3){animation-delay:.5s}
@media (prefers-reduced-motion:reduce){
  .eq i{animation:none !important;height:8px}
  .playall{transition:none}
}

/* ---------- loading / error states ---------- */
.state{padding:34px 24px;color:var(--text-2);font-size:13px;max-width:60ch}
.state h2{font-size:15px;font-weight:700;color:var(--text);letter-spacing:-.01em;margin-bottom:6px}
.state p{margin-top:6px}
.state .retry{
  margin-top:14px;padding:8px 16px;border-radius:999px;
  background:var(--text);color:#0A0B0D;font-size:12px;font-weight:700;
  letter-spacing:.06em;text-transform:uppercase;
}
.skel{display:flex;flex-direction:column;gap:10px;padding:20px 24px}
.skel i{display:block;height:40px;border-radius:4px;background:var(--bg-raise);opacity:.6}
.skel i:nth-child(2){opacity:.45}
.skel i:nth-child(3){opacity:.32}
.skel i:nth-child(4){opacity:.22}
.skel i:nth-child(5){opacity:.14}

/* ---------- player bar ----------
   🔴 2026-08-19: this whole block is /music/css/music.css:421-498 (the
   "── player bar ──" section) LIFTED VERBATIM, plus the .cov trio it depends
   on (music.css:155-165) — Luc's complaint was that the two bars looked
   different, and the only way that stays fixed is for the rules to be the
   same rules. The markup in this page's index.html was aligned to
   /music/index.html:163-206 to match. Do not "tidy" any value here: if a
   number changes on /music/, change it here in the same pass.

   The old page-local bar (.bar/.np/.ctl/.ppl/.seek/.track) is GONE — .bar is
   the SEEK TRACK in this vocabulary, not the footer. */
.cov{
  position:relative;display:block;aspect-ratio:1;border-radius:6px;overflow:hidden;
  background:linear-gradient(150deg,color-mix(in srgb,var(--acc,var(--nc)) 42%,#0B0C0F),#0B0C0F 78%);
  box-shadow:0 18px 50px rgba(0,0,0,.55);
}
.cov-fb{
  position:absolute;inset:0;display:grid;place-items:center;text-align:center;
  padding:12px;font-weight:850;font-stretch:118%;font-size:13px;letter-spacing:.12em;
  color:rgba(255,255,255,.85);text-transform:uppercase;line-height:1.3;
}
.cov img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}

.player{
  position:fixed;left:0;right:0;bottom:0;height:var(--player);z-index:80;
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.4fr) minmax(0,1fr);
  align-items:center;gap:20px;
  /* the bottom inset keeps the controls off the home indicator; 0px on desktop */
  padding:0 max(clamp(14px,2.5vw,28px),env(safe-area-inset-right,0px)) env(safe-area-inset-bottom,0px) max(clamp(14px,2.5vw,28px),env(safe-area-inset-left,0px));
  background:rgba(11,12,15,.92);backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);
  border-top:1px solid var(--line);
}
.p-now{display:flex;align-items:center;gap:14px;min-width:0}
.p-now .cov{width:54px;height:54px;border-radius:5px;box-shadow:none;flex:none}
.p-now-txt{min-width:0}
.p-t{font-weight:650;font-size:14.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.p-s{color:var(--text-3);font-size:12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
body.playing .p-t{color:var(--lime)}
.p-mid{display:flex;flex-direction:column;align-items:center;gap:7px;min-width:0}
.p-btns{display:flex;align-items:center;gap:16px}
.icon-btn{display:grid;place-items:center;width:36px;height:36px;border-radius:50%;color:var(--text-2);transition:color .13s,background .13s;flex:none}
/* player.js hides unsupported controls via the hidden attribute; display:grid above would defeat it */
.icon-btn[hidden]{display:none}
.icon-btn:hover{color:var(--text);background:var(--bg-hover)}
.icon-btn svg{width:17px;height:17px;fill:currentColor}
.p-toggle{width:44px;height:44px;border-radius:50%;background:var(--text);color:#0A0B0D;display:grid;place-items:center;transition:transform .13s var(--ease)}
.p-toggle:hover{transform:scale(1.06)}
.p-toggle svg{width:17px;height:17px;fill:currentColor}
.p-toggle .ic-pause{display:none}
body.playing .p-toggle .ic-play{display:none}
body.playing .p-toggle .ic-pause{display:block}
.p-scrub{display:flex;align-items:center;gap:10px;width:100%;max-width:520px}
.p-scrub span{font-size:11px;color:var(--text-3);font-variant-numeric:tabular-nums;min-width:34px}
.p-scrub span:last-child{text-align:right}
/* touch-action:none so a horizontal drag on the bar scrubs instead of being
   swallowed by the page's scroll gesture */
.bar{flex:1;height:4px;border-radius:2px;background:#2A2B33;position:relative;cursor:pointer;touch-action:none}
.bar .fill{position:absolute;left:0;top:0;bottom:0;width:0%;border-radius:2px;background:var(--lime);transition:width .18s linear}
/* the thumb: a white dot riding the end of the fill, so the position is
   readable at a glance and there is something to grab */
.bar .fill::after{
  content:"";position:absolute;right:-6px;top:50%;
  width:12px;height:12px;margin-top:-6px;border-radius:50%;
  background:#FFF;box-shadow:0 1px 6px rgba(0,0,0,.55);
  transition:transform .12s var(--ease);
}
.p-right{display:flex;align-items:center;justify-content:flex-end;gap:6px}
.vol{
  width:88px;height:4px;-webkit-appearance:none;appearance:none;border-radius:2px;
  background:linear-gradient(var(--lime),var(--lime)) no-repeat #2A2B33;background-size:72% 100%;cursor:pointer;
}
.vol::-webkit-slider-thumb{-webkit-appearance:none;width:12px;height:12px;border-radius:50%;background:var(--text)}
.vol::-moz-range-thumb{width:12px;height:12px;border:0;border-radius:50%;background:var(--text)}

/* player.js error banner (injected into #player) */
.player-error{
  position:absolute;left:50%;transform:translateX(-50%);bottom:calc(100% + 10px);
  display:flex;align-items:center;gap:12px;max-width:min(92vw,520px);
  background:#2A1417;border:1px solid #5B2630;color:#FFD9DE;
  border-radius:999px;padding:9px 14px 9px 18px;font-size:13px;
}
.player-error-close{color:inherit;opacity:.7}
.player-error-close:hover{opacity:1}

/* ---------- non-blocking notice ---------- */
.notice{
  position:fixed;left:50%;transform:translateX(-50%);
  bottom:calc(var(--player) + 14px);z-index:20;
  max-width:min(520px,92vw);
  background:var(--bg-raise);border:1px solid var(--line);
  border-left:3px solid #FF6B6B;
  color:var(--text);font-size:12px;line-height:1.35;
  padding:9px 13px;border-radius:6px;
  box-shadow:0 8px 24px rgba(0,0,0,.5);
  opacity:0;pointer-events:none;transition:opacity .18s var(--ease);
}
.notice.show{opacity:1}
@media (prefers-reduced-motion:reduce){.notice{transition:none}}

/* ---------- queue drawer ----------
   Lifted from /music/css/music.css, with this page's tokens: the panel hangs
   between the masthead and the fixed player bar. .cov there is .thumb here. */
.queue{
  position:fixed;top:calc(var(--topbar) + 12px);bottom:calc(var(--player) + 12px);
  right:max(12px,env(safe-area-inset-right,0px));
  width:min(360px,calc(100vw - 24px - env(safe-area-inset-left,0px) - env(safe-area-inset-right,0px)));z-index:70;
  background:#101116;border:1px solid var(--line);border-radius:14px;
  box-shadow:0 24px 70px rgba(0,0,0,.6);
  transform:translateX(calc(100% + 24px));transition:transform .28s var(--ease);
  display:flex;flex-direction:column;overflow:hidden;
}
.queue.open{transform:translateX(0)}
.q-head{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:16px 18px;border-bottom:1px solid var(--line-soft)}
.q-head h2{font-size:11px;font-weight:800;letter-spacing:.24em;color:var(--text-3)}
.q-head .q-clear{font-size:11px;font-weight:700;letter-spacing:.12em;color:var(--text-3)}
.q-head .q-clear:hover{color:var(--text)}
.q-list{flex:1;overflow-y:auto;padding:8px}
.q-row{
  display:grid;grid-template-columns:40px minmax(0,1fr) auto auto;gap:12px;align-items:center;
  width:100%;text-align:left;padding:8px;border-radius:8px;color:var(--text-2);cursor:pointer;
  transition:background .13s var(--ease);
}
.q-row:hover{background:var(--bg-raise);color:var(--text)}
.q-row .thumb{width:40px;height:40px;border-radius:4px;box-shadow:none}
.q-row .qt{display:block;font-size:13.5px;font-weight:600;color:var(--text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.q-row .qs{display:block;font-size:11.5px;color:var(--text-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.q-row.now .qt{color:var(--lime)}
.q-row .qd{font-size:12px;font-variant-numeric:tabular-nums;color:var(--text-3)}
.q-row .qx{width:26px;height:26px;border-radius:50%;display:grid;place-items:center;color:var(--text-3);font-size:14px;opacity:0;transition:opacity .14s,color .14s,background .14s}
.q-row:hover .qx,.qx:focus-visible{opacity:1}
@media (hover:none){.q-row .qx{opacity:1}}
.q-row .qx:hover{color:var(--text);background:var(--bg-hover)}
.q-empty{padding:30px 20px;color:var(--text-3);font-size:13px;line-height:1.7}
.q-empty b{color:var(--text-2)}
@media (prefers-reduced-motion:reduce){
  .queue{transition:none}
  .q-row,.qadd,.q-row .qx{transition:none}
}

/* player.js injects `.is-pending::after` at runtime (a pulsing underline)
   while a track's manifest mints. Luc wants NO loading animation on the round
   play button, so this (0,2,0) override suppresses the injected (0,1,0) rule
   entirely — every visual property it sets is neutralised. */
.p-toggle.is-pending::after{content:none;animation:none;background:none;border:0}

/* ---------- narrower desktop: trim columns before anything overflows ---------- */
@media (max-width:1100px){
  :root{--sideW:190px}
  .grid{grid-template-columns:36px 40px minmax(0,2fr) minmax(0,1fr) 96px 60px 32px;gap:12px}
  .colhead .plays,.grid .plays{display:none}
  .vol{width:64px}
}

/* ---------- header wraps before the table does (same line as /music/) ---------- */
@media (max-width:1020px){
  .topsearch{order:3;flex:1 1 100%}
  .topctl{order:4}
}

/* ---------- mobile: sidebar collapses to a horizontal chip/sort row on top ---------- */
@media (max-width:700px){
  /* ══ PHONE SHELL ═══════════════════════════════════════════════════
     The masthead is the same pinned 53px bar as /music/ — wordmark +
     search only — and it hides on scroll-down / returns on scroll-up.
     For that to work the DOCUMENT has to be the scroller (on desktop the
     table scrolls inside .listwrap and the page never moves), so the
     100vh/overflow:hidden app shell is unwound here and everything
     scrolls as one column under a sticky bar.
     all-app.js moves .topctl (the chips) down into the sidebar strip, so
     the pinned surface stays one 44px row. If that move never happens —
     no module, or it failed — the chips simply stay in the header on
     their own row: every rule that REMOVES something is gated on
     html.mshell, exactly like /music/. */
  html{--topbar:calc(53px + env(safe-area-inset-top,0px))}
  body{
    height:auto;overflow:visible;display:block;
    padding-bottom:calc(var(--player) + env(safe-area-inset-bottom,0px));
  }
  .shell{display:block;min-height:0}
  .main{display:block}
  .listwrap{overflow:visible}

  .topbar{
    gap:8px 10px;padding:4px var(--gutter);
    padding-top:calc(4px + env(safe-area-inset-top,0px));
    padding-inline:max(var(--gutter),env(safe-area-inset-left,0px)) max(var(--gutter),env(safe-area-inset-right,0px));
    transition:transform .2s var(--ease);will-change:transform;
  }
  /* the bar is sticky, so it keeps its box in the flow: translating it
     moves no other pixel and neither the hide nor the reveal can jump
     the layout. */
  .topbar.is-hidden{transform:translateY(-100%)}
  @media (prefers-reduced-motion:reduce){
    /* all-app.js never sets .is-hidden when motion is reduced; this is the
       belt-and-braces if the class outlives a mid-scroll change. */
    .topbar{transition:none}
    .topbar.is-hidden{transform:none}
  }
  .wm{font-size:19px;margin-right:0}
  .topsearch{order:1;flex:1 1 0;min-width:0;min-height:44px;padding:0 14px}
  /* 16px or iOS Safari zooms the whole page on focus and the layout jumps */
  .topsearch input{font-size:16px}
  .topsearch .clear-q{padding:0 8px;min-height:44px;font-size:20px;line-height:44px}
  /* header-resident fallback layout: search on its own row, chips under it */
  .top-actions{order:2;flex:none;margin-left:0}
  .topctl{order:3;flex:1 1 100%;overflow-x:auto;overscroll-behavior-x:contain}
  /* the queue is gone from the phone, same as /music/: both buttons and the
     panel leave, and setQueueOpen() refuses to open it. */
  .mshell #queueTopBtn,#queueBtn,.queue{display:none}
  .btn{min-height:44px;min-width:44px;padding:0 13px;gap:6px;font-size:0}
  .btn svg{width:18px;height:18px}
  #qCount{font-size:11.5px}
  .chip{padding:0 15px;min-height:44px}

  .shell{grid-template-columns:minmax(0,1fr);grid-template-rows:auto minmax(0,1fr)}
  aside.side{
    border-right:0;border-bottom:1px solid var(--line);
    padding:10px 12px;
    overflow-x:auto;overflow-y:hidden;
    display:flex;align-items:center;gap:8px;
    -webkit-overflow-scrolling:touch;
  }
  /* chips, once moved, ride the same horizontal strip as the sort items */
  .side > .topctl{flex:none;overflow:visible}
  .side > .topctl + .group{padding-left:10px;border-left:1px solid var(--line)}
  .side .group{display:flex;align-items:center;gap:8px;flex:none}
  .side .group + .group{margin-top:0;padding-top:0;border-top:0;padding-left:10px;border-left:1px solid var(--line)}
  .side h3{padding:0;font-size:10px;flex:none}
  .side ul{flex-direction:row;gap:6px}
  .navitem{
    padding:6px 12px;border-radius:999px;
    background:var(--bg-raise);border:1px solid var(--line-soft);
    font-size:12px;
  }
  .navitem[aria-pressed="true"],.navitem[aria-current="true"]{background:var(--text);color:var(--bg);box-shadow:none;border-color:var(--text)}
  header.page{padding:16px 14px 12px}
  .head-meta h1{font-size:22px}
  .grid{grid-template-columns:36px 40px minmax(0,1fr) 52px;gap:12px;padding:8px 14px}
  .sec-head{padding:14px 14px 6px}
  .sec-head.rec-head{padding:16px 14px 8px;gap:12px}
  /* re-state the chevron's gutter: the two rules above are the same
     specificity and later in source than .sec-head.foldable */
  .sec-head.foldable{padding-right:46px}
  .sec-fold{padding-right:14px}
  .sec-cov{width:44px;height:44px}
  .sec-head.rec-head h2{font-size:17px}
  .state,.skel{padding:24px 14px}
  .colhead .rec,.colhead .date,.colhead .plays,.colhead .qslot,
  .grid .rec,.grid .date,.grid .plays,.grid .qslot{display:none}
  .qadd{display:none}
  /* the player bar's phone layout, same moves as music.css:687-734 minus the
     sheet (this page has no expanded view): now-playing + transport, no
     scrubber row and no aux cell, 44px targets. */
  .player{
    grid-template-columns:minmax(0,1fr) auto;
    gap:0 10px;
    padding-top:6px;padding-bottom:calc(6px + env(safe-area-inset-bottom,0px));
  }
  .p-now{gap:10px}
  .p-now .cov{width:44px;height:44px}
  .p-mid{gap:0}
  .p-mid .p-scrub{display:none}
  .p-btns{gap:4px}
  .icon-btn{width:44px;height:44px}
  .p-right{display:none}
}
@media (max-width:420px){
  .grid{grid-template-columns:40px minmax(0,1fr) 52px;gap:10px;padding:8px 12px}
  .colhead .idxcell,.grid .idxcell{display:none}
  .playall{width:48px;height:48px}
  .sec-head{padding:14px 12px 6px}
  .sec-head.rec-head{padding:16px 12px 8px}
  .sec-head.foldable{padding-right:44px}
  .sec-fold{padding-right:12px}
}
