/* conch — private bandcamp player. Spotify-style 3-column shell. */
:root, [data-theme="light"] {
  --bg: #f6f3ee;
  --bg-card: #ffffff;
  --bg-rail: #ebe5d9;
  --bg-rail-r: #ffffff;
  --bg-player: #1a1715;
  --fg: #1a1715;
  --fg-muted: #7a7470;
  --fg-on-dark: #f6f3ee;
  --fg-on-dark-muted: #9a948e;
  --accent: #d96b2c;
  --accent-soft: #f4d8c4;
  --border: #e8e2d8;
  --skeleton: linear-gradient(90deg, #ebe6dc 0%, #f4efe5 50%, #ebe6dc 100%);
  --radius: 10px;
  --shadow: 0 1px 2px rgba(0,0,0,.04), 0 4px 12px rgba(0,0,0,.04);
  --rail-l-w: 72px;
  --rail-r-w: 360px;
  --player-h: 100px;
}
[data-theme="dark"] {
  --bg: #14110f;
  --bg-card: #221d19;
  --bg-rail: #0e0c0a;
  --bg-rail-r: #14110f;
  --bg-player: #0a0807;
  --fg: #f0ebe4;
  --fg-muted: #8a857f;
  --fg-on-dark: #f0ebe4;
  --fg-on-dark-muted: #8a857f;
  --border: #2a241f;
  --accent-soft: #4a2e1c;
  --skeleton: linear-gradient(90deg, #1e1916 0%, #29231d 50%, #1e1916 100%);
  --shadow: 0 1px 2px rgba(0,0,0,.4), 0 4px 12px rgba(0,0,0,.3);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) {
    --bg: #14110f; --bg-card: #221d19; --bg-rail: #0e0c0a; --bg-rail-r: #14110f;
    --bg-player: #0a0807;
    --fg: #f0ebe4; --fg-muted: #8a857f;
    --border: #2a241f; --accent-soft: #4a2e1c;
    --skeleton: linear-gradient(90deg, #1e1916 0%, #29231d 50%, #1e1916 100%);
    --shadow: 0 1px 2px rgba(0,0,0,.4), 0 4px 12px rgba(0,0,0,.3);
  }
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; height: 100%; }
body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, system-ui, sans-serif;
  font-size: 14px; color: var(--fg); background: var(--bg);
  -webkit-font-smoothing: antialiased;
}

/* Hide scrollbars across the app — keep scroll behavior, just invisible
 * track + thumb. Firefox uses `scrollbar-width`, WebKit uses ::-webkit-scrollbar.
 * Applied to every scrollable surface (main, rails) so the editorial look stays
 * clean. Native gesture/wheel/keyboard scroll all still work. */
* { scrollbar-width: none; -ms-overflow-style: none; }

/* ---------- scroll hints (invisible scrollbar replacement) ----------
   Scrollbars are hidden app-wide (above), so the user has no native cue
   that a panel has more content above or below the viewport. A JS helper
   (attachScrollHints) adds .has-scroll-hints to any scroll container and
   toggles .show-scroll-up / .show-scroll-down based on scrollTop. The
   ::before / ::after pseudo-elements then render small chevrons at the
   top / bottom of the visible area with a subtle gradient overlay so
   the indicator reads on light + dark themes. They're pointer-events:
   none so they don't intercept clicks. */
.has-scroll-hints { position: relative; }
.has-scroll-hints::before,
.has-scroll-hints::after {
  position: absolute; left: 0; right: 0;
  height: 24px;
  display: flex; align-items: center; justify-content: center;
  pointer-events: none;
  opacity: 0; transition: opacity 0.18s ease;
  font-size: 11px; line-height: 1; letter-spacing: 0.06em;
  color: var(--fg-muted);
  z-index: 5;
}
.has-scroll-hints::before {
  content: "\25B2";    /* ▲ */
  top: 0;
  background: linear-gradient(to bottom, rgba(127,127,127,0.22), transparent);
  padding-top: 4px; align-items: flex-start;
}
.has-scroll-hints::after {
  content: "\25BC";    /* ▼ */
  bottom: 0;
  background: linear-gradient(to top, rgba(127,127,127,0.22), transparent);
  padding-bottom: 4px; align-items: flex-end;
}
.has-scroll-hints.show-scroll-up::before { opacity: 0.85; }
.has-scroll-hints.show-scroll-down::after { opacity: 0.85; }
/* Inside the player panels, the sticky head overlaps the top hint;
   nudge the up-arrow down to the head's bottom edge. */
.settings-panel.has-scroll-hints::before,
.eq-panel.has-scroll-hints::before { top: 38px; }
*::-webkit-scrollbar { width: 0; height: 0; display: none; }
.hidden { display: none !important; }

/* ---------- login ---------- */
.login { position: fixed; inset: 0; display: grid; place-items: center; background: var(--bg); }
.login form {
  width: min(92vw, 460px); display: flex; flex-direction: column; gap: 12px;
  padding: 28px; border-radius: var(--radius);
  background: var(--bg-card); box-shadow: var(--shadow);
}
.login h1 { margin: 0; font-size: 28px; letter-spacing: -.02em; }
.login p { margin: 0; color: var(--fg-muted); }
.login input, .login button {
  font: inherit; padding: 10px 12px; border-radius: 8px;
  border: 1px solid var(--border); background: var(--bg);
}
.login input { font-family: ui-monospace, "SF Mono", Consolas, monospace; font-size: 12px; }
.login button { background: var(--accent); color: white; border: none; font-weight: 600; cursor: pointer; }
.login small { color: #c0392b; min-height: 14px; }
.login code { background: rgba(0,0,0,.05); padding: 0 4px; border-radius: 3px; }

/* ---------- app shell: 3-column grid ---------- */
.app {
  display: grid;
  grid-template-columns: var(--rail-l-w) minmax(0, 1fr) var(--rail-r-w);
  grid-template-rows: 1fr var(--player-h);
  grid-template-areas:
    "rail-l main rail-r"
    "player player player";
  height: 100vh; height: 100dvh;
  transition: grid-template-columns .2s ease;
}
.app.rail-r-collapsed { grid-template-columns: var(--rail-l-w) minmax(0, 1fr) 0; }
.rail-l   { grid-area: rail-l; background: var(--bg-rail); border-right: 1px solid var(--border); overflow-y: auto; padding: 12px 0 12px; }
.main     { grid-area: main; overflow-y: auto; }
.rail-r   { grid-area: rail-r; background: var(--bg-rail-r); border-left: 1px solid var(--border); overflow-y: auto; position: relative; }
.player   { grid-area: player; }

/* ---------- left rail (Spotify-style icon column + thumbnails) ---------- */
.rail-l { display: flex; flex-direction: column; align-items: center; gap: 6px; }
.rail-brand { font-size: 22px; color: var(--accent); padding: 6px 0 12px; }
.rail-nav { display: flex; flex-direction: column; gap: 4px; width: 100%; align-items: center; }
.rail-icon {
  width: 44px; height: 44px; border-radius: 10px;
  display: grid; place-items: center;
  color: var(--fg-muted); text-decoration: none; font-size: 18px;
  background: none; border: none; cursor: pointer; font: inherit;
  transition: background .12s ease, color .12s ease;
}
.rail-icon:hover { background: rgba(127,127,127,.12); color: var(--fg); }
.rail-icon.active { background: var(--accent); color: white; }
.rail-divider { width: 36px; height: 1px; background: var(--border); margin: 8px 0; }
.rail-thumbs { display: flex; flex-direction: column; gap: 6px; padding: 0 12px; align-items: center; flex: 1; min-height: 0; }
.rail-thumb {
  width: 44px; height: 44px; border-radius: 6px; overflow: hidden;
  position: relative; cursor: pointer; display: block;
}
.rail-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.rail-thumb-fallback { width: 100%; height: 100%; display: grid; place-items: center;
  background: linear-gradient(135deg, var(--accent) 0%, var(--bg-player) 100%);
  color: white; font-weight: 700; font-size: 16px; }
.rail-thumb.active { outline: 2px solid var(--accent); outline-offset: 1px; }
.rail-foot { display: flex; flex-direction: column; gap: 4px; padding-top: 8px; border-top: 1px solid var(--border); width: 100%; align-items: center; }

/* ---------- topbar ---------- */
.topbar {
  position: sticky; top: 0; z-index: 10;
  display: flex; align-items: center; gap: 10px;
  padding: 12px 20px; background: var(--bg);
  border-bottom: 1px solid var(--border);
}
.hamburger { display: none; background: none; border: none; font-size: 22px; cursor: pointer; color: var(--fg); }
@media (max-width: 900px) { .hamburger { display: block; } }
.topbar-nav { display: flex; gap: 2px; }
.topbar-nav .iconbtn { width: 32px; height: 32px; border-radius: 999px; background: rgba(127,127,127,.12); color: var(--fg); font-size: 16px; }
.search { flex: 1; max-width: 560px; }
.search input {
  width: 100%; padding: 10px 16px 10px 38px; border-radius: 999px;
  border: 1px solid var(--border); background: var(--bg-card); font: inherit;
  color: var(--fg);
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%237a7470'><path d='M11 6.5a4.5 4.5 0 1 1-9 0 4.5 4.5 0 0 1 9 0zm-.689 4.518a6 6 0 1 1 .707-.707l3.586 3.586-.707.707-3.586-3.586z'/></svg>");
  background-repeat: no-repeat; background-position: 12px center; background-size: 14px;
}
.topbar-rright { width: 32px; height: 32px; border-radius: 6px; }
/* Topbar icon buttons live on the main bg, NOT the dark-tinted bottom
   player. The default .iconbtn color (--fg-on-dark) is light-on-light in
   light theme; force --fg so the icons read on both themes. */
.topbar .iconbtn { color: var(--fg); opacity: .85; }
.topbar .iconbtn:hover { opacity: 1; background: rgba(127,127,127,.12); }

/* Search-suggest dropdown — appears below the topbar search input as the
 * user types. Items grouped by Albums / Artists / Tracks. Keyboard
 * navigable: ArrowUp/Down to move, Enter to select, Esc to dismiss. */
.search { position: relative; }
.suggest {
  position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 30;
  background: var(--bg-card); border: 1px solid var(--border); border-radius: 12px;
  box-shadow: 0 8px 24px rgba(0,0,0,.35); overflow: hidden;
  max-height: 60vh; overflow-y: auto;
}
.suggest[hidden] { display: none; }
.suggest-section { font-size: 10px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--fg-muted); padding: 8px 14px 2px; }
.suggest-item { display: flex; align-items: center; gap: 10px;
  padding: 7px 14px; cursor: pointer; color: var(--fg); }
.suggest-item:hover, .suggest-item[aria-selected="true"] { background: rgba(127,127,127,.12); }
.suggest-item .si-art { width: 28px; height: 28px; border-radius: 4px; object-fit: cover; background: rgba(127,127,127,.18); flex-shrink: 0; }
.suggest-item .si-glyph { width: 28px; height: 28px; border-radius: 4px; display: inline-flex; align-items: center; justify-content: center; background: rgba(127,127,127,.18); flex-shrink: 0; font-size: 14px; }
.suggest-item .si-title { flex: 1; min-width: 0; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.suggest-item .si-sub { font-size: 11px; color: var(--fg-muted); flex-shrink: 0; max-width: 40%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.suggest-item mark { background: transparent; color: var(--accent); font-weight: 600; padding: 0; }
.suggest-foot { padding: 8px 14px; border-top: 1px solid var(--border); font-size: 11px; color: var(--fg-muted); display: flex; gap: 10px; }
.suggest-foot kbd { background: rgba(127,127,127,.18); border-radius: 3px; padding: 1px 5px; font-size: 10px; }
.suggest-item .recent-rm { margin-left: auto; background: none; border: 0; color: var(--fg-muted); cursor: pointer; font-size: 14px; padding: 0 6px; line-height: 1; opacity: .6; }
.suggest-item .recent-rm:hover { opacity: 1; color: var(--accent); }

/* Filter bar — reusable row above any tracklist view (Liked, Playlist,
 * Downloads). Text filter + sort select + match counter. */
.filter-bar { display: flex; gap: 10px; align-items: center; margin: 0 0 12px;
  flex-wrap: wrap; }
.filter-bar input[type=search] {
  flex: 1; min-width: 200px; max-width: 420px;
  padding: 8px 14px 8px 34px; border-radius: 999px;
  border: 1px solid var(--border); background: var(--bg-card); color: var(--fg); font: inherit; font-size: 13px;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%237a7470'><path d='M11 6.5a4.5 4.5 0 1 1-9 0 4.5 4.5 0 0 1 9 0zm-.689 4.518a6 6 0 1 1 .707-.707l3.586 3.586-.707.707-3.586-3.586z'/></svg>");
  background-repeat: no-repeat; background-position: 12px center; background-size: 12px;
}
.filter-bar select {
  padding: 7px 10px; border-radius: 6px; border: 1px solid var(--border);
  background: var(--bg-card); color: var(--fg); font: inherit; font-size: 12px; cursor: pointer;
}
.filter-bar .filter-count { font-size: 11px; color: var(--fg-muted); margin-left: auto; }
.tracklist li.filter-hidden { display: none; }

/* Liked-state on a tracklist row. Subtle accent on the title so the user
 * can scan an album and immediately see which songs they like. The
 * heart icon button below carries the primary visual. */
.tracklist li.liked .ttitle::before { content: "♥ "; color: var(--accent); font-size: 11px; vertical-align: 1px; }
.iconbtn.like-btn { color: var(--fg-muted); font-size: 14px; line-height: 1; }
.iconbtn.like-btn.is-liked { color: var(--accent); }
.iconbtn.like-btn:hover { color: var(--accent); }

/* Per-album "♥ N liked" pill above the tracklist */
.tracklist-head { margin: 0 0 8px; }
.tracklist-head .liked-count { color: var(--accent); margin-left: 4px; }

/* On Repeat row art — leftmost square thumb instead of the track number */
.on-repeat-list .num { width: 40px; padding: 0; }
.on-repeat-art { width: 36px; height: 36px; border-radius: 4px; object-fit: cover; background: rgba(127,127,127,.18); display: block; }

/* ---------- DJ session list + status ---------- */
.dj-head h2 { margin-bottom: 4px; }
.dj-card { background: linear-gradient(180deg, rgba(217,107,44,.06), rgba(127,127,127,.04)); }
.dj-card-icon { width: 100%; aspect-ratio: 1; display: flex; align-items: center; justify-content: center;
  font-size: 64px; background: linear-gradient(135deg, rgba(217,107,44,.12), rgba(127,127,127,.08));
  border-radius: 8px 8px 0 0; }
.dj-status { padding: 14px 16px; border-radius: 10px; background: var(--bg-card);
  border-left: 4px solid var(--fg-muted); margin: 0 0 14px; }
.dj-status.ready { border-left-color: #6dc36d; }
.dj-status.processing { border-left-color: var(--accent); }
.dj-progress { height: 6px; background: rgba(127,127,127,.18); border-radius: 999px; overflow: hidden; margin-top: 10px; }
.dj-progress-bar { height: 100%; background: linear-gradient(90deg, var(--accent), #6dc36d);
  transition: width .4s ease; }
.dj-tag { font-size: 10px; padding: 2px 8px; border-radius: 999px; font-weight: 600;
  text-transform: uppercase; letter-spacing: .04em; }
.dj-tag.ok      { background: rgba(120,200,120,.18); color: #6dc36d; }
.dj-tag.running { background: rgba(217,107,44,.22); color: var(--accent); }
.dj-tag.queued  { background: rgba(120,140,220,.18); color: #8fa6e0; }
.dj-tag.pending { background: rgba(127,127,127,.18); color: var(--fg-muted); }
.dj-tag.failed  { background: rgba(192,57,43,.22); color: #e07060; cursor: help; }

/* Modal picker (used by "Add a track to this DJ session") */
.modal-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,.55); z-index: 120;
  display: flex; align-items: center; justify-content: center; }
.modal { width: min(560px, 92vw); max-height: 80vh; background: var(--bg-card);
  border: 1px solid var(--border); border-radius: 12px; display: flex; flex-direction: column;
  box-shadow: 0 16px 40px rgba(0,0,0,.5); }
.modal-head { display: flex; align-items: center; justify-content: space-between; padding: 12px 14px;
  border-bottom: 1px solid var(--border); }
.modal-search { margin: 12px 14px 8px; padding: 8px 12px; border-radius: 8px;
  border: 1px solid var(--border); background: var(--bg); color: var(--fg); font: inherit; font-size: 13px; }
.modal-list { list-style: none; margin: 0; padding: 0 6px 12px; overflow: auto; }
.modal-list li { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: 6px;
  font-size: 13px; }
.modal-list li:hover { background: rgba(127,127,127,.1); }
.modal-list li > span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Richer Add Track modal: tabbed sources + multi-select + bottom confirm. */
.add-track-modal { width: min(680px, 95vw); height: min(720px, 88vh); }
.add-track-tabs { display: flex; gap: 4px; padding: 8px 14px 0; flex-wrap: wrap; }
.add-track-tabs .att-tab {
  background: rgba(127,127,127,.08); border: 1px solid var(--border);
  color: var(--fg-muted); padding: 5px 12px; border-radius: 6px;
  font-size: 12px; cursor: pointer; font: inherit;
}
.add-track-tabs .att-tab.active { background: rgba(217,107,44,.18); color: var(--accent); border-color: var(--accent); }
.add-track-tabs .att-tab:hover { background: rgba(127,127,127,.16); }
.add-track-subnav {
  display: flex; gap: 4px; padding: 6px 14px; flex-wrap: wrap;
  border-bottom: 1px solid var(--border); max-height: 80px; overflow-y: auto;
}
.add-track-subnav[hidden] { display: none; }
.add-track-subnav .att-sub {
  background: var(--bg); border: 1px solid var(--border); color: var(--fg);
  padding: 4px 10px; border-radius: 4px; font-size: 11px; cursor: pointer; font: inherit;
  white-space: nowrap; max-width: 200px; overflow: hidden; text-overflow: ellipsis;
}
.add-track-subnav .att-sub:hover { background: rgba(127,127,127,.12); }
.att-list { flex: 1; max-height: none !important; }
.att-list li { gap: 8px; cursor: pointer; user-select: none; }
.att-list li input[type=checkbox] { margin: 0; cursor: pointer; }
.att-list li.checked { background: rgba(217,107,44,.10); }
.add-track-foot {
  padding: 12px 14px; border-top: 1px solid var(--border);
  display: flex; align-items: center; gap: 10px;
}
.add-track-foot .btn { font-size: 13px; }
.add-track-foot #att-count { flex: 1; font-size: 12px; }

/* ---------- DJ booth (two-deck view) ---------- */
.dj-booth { padding: 0; max-width: 1280px; margin: 0 auto; }
.dj-booth-head { display: flex; align-items: center; gap: 12px; margin-bottom: 18px; }
.dj-booth-head h2 { flex: 0 0 auto; margin: 0; }
.auto-dj-btn { font-size: 12px; padding: 6px 12px; }
.auto-dj-btn.active { background: var(--accent); color: var(--bg); border-color: var(--accent); }
.dj-decks { display: grid; grid-template-columns: 1fr 110px 1fr; gap: 18px; align-items: stretch;
  background: linear-gradient(180deg, rgba(20,18,16,.6), rgba(8,7,6,.85));
  border: 1px solid var(--border); border-radius: 16px; padding: 22px; }
.dj-deck { display: flex; flex-direction: column; gap: 12px;
  background: rgba(127,127,127,.04); border: 1px solid var(--border);
  border-radius: 12px; padding: 16px; }
.dj-deck-head { display: flex; align-items: center; justify-content: space-between; }
.dj-deck-head strong { font-size: 16px; letter-spacing: .04em; }
.dj-deck-head::after {
  /* Imaginary turntable platter — spinning ring when playing. Pure CSS,
   * sized to feel like a hint of the deck rather than dominate. */
  content: ""; width: 80px; height: 80px; border-radius: 50%;
  background: radial-gradient(circle at center, #2a2520 0 12%, #0e0c0a 12% 14%, #1a1715 14% 96%, #2a2520 96% 100%);
  border: 1px solid #3a3530;
  box-shadow: inset 0 0 12px rgba(0,0,0,.6), 0 4px 14px rgba(0,0,0,.4);
  position: relative;
}
.dj-deck.playing .dj-deck-head::after {
  animation: djspin 2.4s linear infinite;
}
@keyframes djspin { to { transform: rotate(360deg); } }
.dj-deck-track { padding: 8px 10px; border-radius: 8px; border: 1px solid var(--border);
  background: var(--bg-card); color: var(--fg); font: inherit; font-size: 12px; }
.dj-deck-meta { display: flex; justify-content: space-between; align-items: center; font-size: 11px;
  color: var(--fg-muted); font-variant-numeric: tabular-nums; }
.dj-bpm { color: var(--accent); font-weight: 700; letter-spacing: .04em; }
.dj-transport { display: flex; gap: 8px; }
.dj-transport .btn { flex: 1; font-size: 12px; padding: 8px 4px; }
.dj-stems { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.dj-stem { display: flex; align-items: center; justify-content: space-between;
  background: rgba(127,127,127,.08); border: 1px solid var(--border);
  border-radius: 8px; padding: 8px 12px; cursor: pointer;
  color: var(--fg-muted); text-transform: uppercase; font-size: 11px;
  letter-spacing: .06em; font-weight: 600; }
.dj-stem.on { color: var(--accent); border-color: var(--accent); background: rgba(217,107,44,.12); }
.dj-stem-led { width: 8px; height: 8px; border-radius: 50%; background: var(--fg-muted); }
.dj-stem.on .dj-stem-led { background: var(--accent); box-shadow: 0 0 8px var(--accent); }
.dj-tempo-row { display: flex; align-items: center; gap: 8px; font-size: 11px; color: var(--fg-muted); }
.dj-tempo-row label { width: 50px; }
.dj-tempo-row input[type=range] { flex: 1; }
.dj-tempo-val { width: 50px; text-align: right; font-variant-numeric: tabular-nums; }

/* Crossfader column — centered, vertical layout */
.dj-crossfader-wrap { display: flex; flex-direction: column; align-items: center; gap: 10px;
  justify-content: center; padding: 12px 0; }
.dj-crossfader-wrap label { font-size: 11px; color: var(--fg-muted); text-transform: uppercase;
  letter-spacing: .08em; }
.dj-crossfader-wrap input[type=range] {
  width: 100%; appearance: none; height: 6px; border-radius: 999px;
  background: linear-gradient(90deg, var(--accent) 0%, var(--fg-muted) 50%, var(--accent) 100%);
}
.dj-crossfader-labels { display: flex; justify-content: space-between; width: 100%;
  font-size: 11px; color: var(--fg-muted); font-weight: 600; letter-spacing: .06em; }
.dj-tips { padding: 10px 14px; background: rgba(127,127,127,.06); border-radius: 8px; line-height: 1.6; }

@media (max-width: 900px) {
  .dj-decks { grid-template-columns: 1fr; }
  .dj-crossfader-wrap { padding: 14px 0; }
}

/* Track "+" popup menu */
.add-menu {
  position: fixed; z-index: 100; min-width: 240px;
  background: var(--bg-card); border: 1px solid var(--border); border-radius: 10px;
  box-shadow: 0 12px 28px rgba(0,0,0,.5);
  padding: 6px; display: flex; flex-direction: column;
}
.add-menu-item {
  display: grid; grid-template-columns: 28px 1fr auto; align-items: center;
  gap: 4px 10px; padding: 8px 10px; border-radius: 6px;
  background: none; border: 0; color: var(--fg); cursor: pointer; text-align: left;
}
.add-menu-item:hover, .add-menu-item:focus { background: rgba(127,127,127,.14); }
.add-menu-item .ami-icon { font-size: 16px; }
.add-menu-item .ami-label { font-size: 13px; font-weight: 500; }
.add-menu-item .ami-sub { font-size: 11px; color: var(--fg-muted); grid-column: 2; grid-row: 2; }
.add-menu-sep { height: 1px; background: var(--border); margin: 4px 6px; }

/* ---------- Bug report modal ---------- */
.bug-modal {
  position: fixed; inset: 0; background: rgba(0,0,0,.62); z-index: 200;
  display: flex; align-items: center; justify-content: center;
}
.bug-modal[hidden] { display: none; }
.bug-modal-card {
  width: min(640px, 92vw); max-height: 85vh; display: flex; flex-direction: column;
  background: var(--bg-card); border: 1px solid var(--border); border-radius: 12px;
  box-shadow: 0 16px 40px rgba(0,0,0,.55);
}
.bug-modal-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 18px; border-bottom: 1px solid var(--border);
}
.bug-modal-body { padding: 16px 18px 18px; overflow-y: auto; }
.bug-field { display: block; margin: 0 0 12px; }
.bug-field > span { display: block; font-size: 12px; color: var(--fg-muted); margin-bottom: 6px; }
.bug-field textarea {
  width: 100%; padding: 10px 12px; border-radius: 8px; border: 1px solid var(--border);
  background: var(--bg); color: var(--fg); font: inherit; font-size: 13px;
  resize: vertical;
}
.bug-field-row { display: flex; align-items: center; gap: 8px; }
.bug-field-row > span { margin: 0; font-size: 13px; }
.bug-state-details { margin: 4px 0 12px; }
.bug-state-details summary { font-size: 12px; color: var(--fg-muted); cursor: pointer; }
.bug-state-pre {
  background: var(--bg); border: 1px solid var(--border); border-radius: 6px;
  padding: 8px 10px; font-size: 10.5px; line-height: 1.45; max-height: 260px; overflow: auto;
  white-space: pre-wrap; word-break: break-all;
}
.bug-modal-actions { display: flex; gap: 8px; justify-content: flex-end; }

/* ---------- views ---------- */
.view { padding: 22px 24px 28px; max-width: 1400px; margin: 0 auto; }
.view h2 { margin: 0 0 14px; font-size: 24px; letter-spacing: -.01em; }
.view h3 { margin: 22px 0 12px; font-size: 13px; text-transform: uppercase;
  letter-spacing: .08em; color: var(--fg-muted); font-weight: 600; }

.grid { display: grid; gap: 18px; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); }
.card-wrap { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.card {
  background: var(--bg-card); border-radius: var(--radius); overflow: hidden;
  box-shadow: var(--shadow); cursor: pointer; transition: transform .15s ease, opacity .15s ease;
  display: flex; flex-direction: column;
  color: var(--fg); text-decoration: none; position: relative;
}
.card:hover { transform: translateY(-2px); }
.card.loading { opacity: .5; pointer-events: none; }
.card-art {
  aspect-ratio: 1/1; display: block; width: 100%; object-fit: cover;
  background: var(--skeleton); background-size: 200% 100%; animation: shimmer 1.6s infinite linear;
}
.card-art.loaded { animation: none; }
@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }
.card-art-fallback {
  aspect-ratio: 1/1; display: grid; place-items: center; width: 100%;
  background: linear-gradient(135deg, var(--accent) 0%, var(--bg-player) 100%);
  color: white; font-size: 36px; font-weight: 700; text-transform: uppercase;
}
.card-body { padding: 10px 12px 12px; }
.card-title { font-weight: 600; line-height: 1.3; color: var(--fg);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.card-artist { color: var(--fg-muted); font-size: 12px; padding: 0 4px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  text-decoration: none; }
.card-wrap > .card-artist:hover { color: var(--accent); }
.card-kind { font-size: 10px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--accent); font-weight: 600; }

.artist-link { color: inherit; text-decoration: none; border-bottom: 1px dotted transparent; }
.artist-link:hover { color: var(--accent); border-bottom-color: currentColor; }

.empty { color: var(--fg-muted); padding: 40px 0; text-align: center; }
.muted { color: var(--fg-muted); }

/* ---------- artist view ---------- */
.artist-header {
  display: grid; grid-template-columns: 180px 1fr; gap: 24px; align-items: start;
  margin-bottom: 28px;
}
@media (max-width: 640px) { .artist-header { grid-template-columns: 100px 1fr; gap: 16px; } }
.artist-avatar {
  width: 100%; aspect-ratio: 1/1; border-radius: 999px; object-fit: cover;
  box-shadow: var(--shadow);
}
.artist-avatar.card-art-fallback { border-radius: 999px; }
.artist-meta h2 { margin: 6px 0 4px; font-size: 32px; letter-spacing: -.02em; }
.artist-bio { margin: 12px 0 8px; color: var(--fg); line-height: 1.55; max-width: 60ch; white-space: pre-wrap; }

/* ---------- album detail ---------- */
.album-detail { display: grid; gap: 28px; grid-template-columns: 240px 1fr; align-items: start; }
@media (max-width: 720px) { .album-detail { grid-template-columns: 1fr; } }
.album-art-lg { width: 100%; border-radius: var(--radius); box-shadow: var(--shadow); }
.album-info h2 { font-size: 26px; margin: 0 0 4px; letter-spacing: -.01em; }
.album-info .artist { color: var(--fg-muted); margin-bottom: 16px; }
.album-actions { display: flex; gap: 10px; flex-wrap: wrap; margin: 16px 0 22px; }
.btn { border: 1px solid var(--border); background: var(--bg-card); color: var(--fg);
  padding: 8px 14px; border-radius: 999px; cursor: pointer; font: inherit; font-weight: 600;
  text-decoration: none; display: inline-flex; align-items: center; gap: 6px; }
.btn:hover { border-color: var(--accent); color: var(--accent); }
.btn.primary { background: var(--accent); color: white; border-color: var(--accent); }
.btn.primary:hover { color: white; opacity: .9; }
.btn.small { padding: 4px 10px; font-size: 12px; font-weight: 500; }
.tier-pill { display: inline-block; padding: 3px 10px; border-radius: 999px;
  background: var(--accent-soft); color: var(--accent); font-size: 11px; font-weight: 600;
  text-transform: uppercase; letter-spacing: .04em; }
.tag-pill { display: inline-block; padding: 2px 8px; margin: 2px 2px; border-radius: 999px;
  background: rgba(127,127,127,.1); color: var(--fg-muted); font-size: 10px;
  text-transform: lowercase; letter-spacing: .02em; }

/* ---------- library sections ---------- */
.lib-section { margin: 22px 0; }
.lib-section-head { display: flex; align-items: baseline; gap: 12px; margin-bottom: 12px; }
.lib-section-head h3 { margin: 0; flex: 1; }
.lib-quick { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 14px; }
.lib-hero {
  display: flex; align-items: center; gap: 14px;
  padding: 16px 18px; border-radius: var(--radius);
  text-decoration: none; color: var(--fg);
  background: linear-gradient(135deg, var(--accent-soft), var(--bg-card));
  border: 1px solid var(--border);
  transition: transform .12s ease, box-shadow .12s ease;
}
.lib-hero:hover { transform: translateY(-2px); box-shadow: var(--shadow); }
.lib-hero.liked { background: linear-gradient(135deg, rgba(217,107,44,.22), rgba(217,107,44,.05)); }
.lib-hero.downloads { background: linear-gradient(135deg, rgba(120,200,120,.18), rgba(120,200,120,.04)); }
.lib-hero-icon { font-size: 32px; color: var(--accent); flex-shrink: 0; }
.lib-hero.downloads .lib-hero-icon { color: #6dc36d; }
.lib-hero-label { font-weight: 700; font-size: 15px; }
.lib-hero-count { font-size: 12px; color: var(--fg-muted); margin-top: 2px; }

/* ---------- stats view ---------- */
.stats-overview { display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
  gap: 12px; margin: 16px 0 24px; }
.stat-card { background: var(--bg-card); padding: 14px 16px; border-radius: var(--radius);
  box-shadow: var(--shadow); text-align: center; }
.stat-num { font-size: 26px; font-weight: 700; letter-spacing: -.02em; color: var(--accent); }
.stat-lbl { font-size: 10px; color: var(--fg-muted); text-transform: uppercase;
  letter-spacing: .06em; margin-top: 2px; font-weight: 600; }
.stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 24px; margin-bottom: 28px; }
.rank-list { list-style: none; margin: 0; padding: 0; }
.rank-list li { display: grid; grid-template-columns: 28px 1fr auto;
  gap: 10px; align-items: center; padding: 8px 4px;
  border-bottom: 1px solid var(--border); font-size: 13px; }
.rank-list li:last-child { border-bottom: none; }
.rank { color: var(--fg-muted); font-variant-numeric: tabular-nums; font-weight: 600; font-size: 11px; }
.rank-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rank-count { color: var(--accent); font-weight: 700; font-variant-numeric: tabular-nums;
  padding: 2px 8px; background: var(--accent-soft); border-radius: 999px; font-size: 11px; }
.bar-block { display: flex; flex-direction: column; gap: 6px; }
.bar-row { display: grid; grid-template-columns: 70px 1fr 32px; gap: 10px; align-items: center; font-size: 12px; }
.bar-label { color: var(--fg-muted); text-transform: capitalize; }
.bar-track { height: 8px; background: rgba(127,127,127,.12); border-radius: 4px; overflow: hidden; }
.bar-fill { height: 100%; background: var(--accent); border-radius: 4px; transition: width .3s ease; }
.bar-count { font-variant-numeric: tabular-nums; color: var(--fg-muted); text-align: right; font-size: 11px; }

/* Album metadata definition list: two-column key/value with proper alignment */
.meta-list { display: grid; grid-template-columns: max-content 1fr; gap: 4px 18px;
  margin: 14px 0 4px; color: var(--fg); font-size: 13px; }
.meta-list dt { color: var(--fg-muted); font-size: 11px; text-transform: uppercase;
  letter-spacing: .06em; align-self: center; }
.meta-list dd { margin: 0; }
.album-section { margin: 22px 0 8px; }
.album-section h4 { font-size: 11px; text-transform: uppercase; letter-spacing: .08em;
  color: var(--fg-muted); font-weight: 600; margin: 0 0 6px; }
.album-section p { color: var(--fg); white-space: pre-wrap; line-height: 1.55; margin: 0; max-width: 70ch; }

.tracklist { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--border); }
.tracklist li {
  display: grid; grid-template-columns: 28px 1fr auto auto; gap: 12px;
  align-items: center; padding: 10px 6px; border-bottom: 1px solid var(--border); cursor: pointer;
}
.tracklist li:hover { background: var(--bg-card); }
/* Track row middle cell — single grid cell containing the title + artist
   (+ optional album) so the row stays 4 columns; .ttitle and .tartist are
   independently clickable inside it. */
.trow-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Single-click selection (single click ≠ play; double click plays).
   Subtle highlight so the user knows what's targeted by row-context
   actions (e.g. future right-click / long-press menu). */
.tracklist li.selected {
  background: linear-gradient(90deg, rgba(120,160,220,.16), rgba(120,160,220,0) 70%);
  outline: 1px solid rgba(120,160,220,0.35); outline-offset: -1px;
}
/* Track title + artist name are clickable INSIDE the row: title → album
   page, artist → artist page. Cursor + hover-underline communicate that
   they're independent affordances from the row itself. */
.tracklist .ttitle, .tracklist .tartist {
  cursor: pointer; transition: color .12s ease;
}
.tracklist .ttitle:hover, .tracklist .tartist:hover {
  color: var(--accent); text-decoration: underline; text-underline-offset: 2px;
}
/* Same affordance in the queue rail's Up Next + Via Radio lists. */
.queue-list li.selected {
  background: linear-gradient(90deg, rgba(120,160,220,.18), rgba(120,160,220,0) 75%);
  outline: 1px solid rgba(120,160,220,0.35); outline-offset: -1px;
}
.queue-list .queue-title, .queue-list .queue-art-name,
.queue-list .queue-meta .queue-row-title, .queue-list .queue-meta .queue-row-artist {
  cursor: pointer; transition: color .12s ease;
}
.queue-list .queue-title:hover, .queue-list .queue-art-name:hover,
.queue-list .queue-meta .queue-row-title:hover, .queue-list .queue-meta .queue-row-artist:hover {
  color: var(--accent); text-decoration: underline; text-underline-offset: 2px;
}
/* Currently-playing row — clearly visible at a glance in any tracklist
 * (Liked, playlists, albums, downloads, On Repeat). Accent text + soft
 * accent background tint + a 3px accent stripe on the leading edge +
 * a small ▶ marker replacing the row number. Animation only runs while
 * the audio is actually playing (the body.audio-paused class freezes it). */
.tracklist li.playing {
  color: var(--accent);
  background: linear-gradient(90deg, rgba(217,107,44,.14), rgba(217,107,44,0) 60%);
  position: relative;
}
.tracklist li.playing::before {
  content: "";
  position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: var(--accent);
}
.tracklist li.playing .ttitle { font-weight: 600; }
/* Replace the row number with an animated "now playing" indicator.
 * Three vertical bars pulsing in opposing rhythms — the classic
 * iTunes/Spotify cue that this row is the live one. */
.tracklist li.playing .num { color: var(--accent); position: relative; font-size: 0; }
.tracklist li.playing .num::before,
.tracklist li.playing .num::after { font-size: initial; }
.tracklist li.playing .num > * { visibility: hidden; }
.tracklist li.playing .num {
  background-image:
    linear-gradient(var(--accent), var(--accent)),
    linear-gradient(var(--accent), var(--accent)),
    linear-gradient(var(--accent), var(--accent));
  background-repeat: no-repeat;
  background-position: 30% bottom, 50% bottom, 70% bottom;
  background-size:
    2px 35%,
    2px 70%,
    2px 50%;
  animation: nowplaying 0.9s ease-in-out infinite;
}
@keyframes nowplaying {
  0%, 100% { background-size: 2px 35%, 2px 70%, 2px 50%; }
  25%      { background-size: 2px 60%, 2px 30%, 2px 80%; }
  50%      { background-size: 2px 80%, 2px 55%, 2px 25%; }
  75%      { background-size: 2px 40%, 2px 75%, 2px 65%; }
}
body.audio-paused .tracklist li.playing .num { animation-play-state: paused; }
.tracklist .num { color: var(--fg-muted); font-variant-numeric: tabular-nums; }
.tracklist .ttitle { font-weight: 500; }
.tracklist .tdur { color: var(--fg-muted); font-variant-numeric: tabular-nums; font-size: 12px; }
.tracklist .tactions { display: flex; gap: 4px; }
/* Play-count badge inline in the title row — small accent pill */
.play-count {
  display: inline-block; margin-left: 6px;
  font-size: 10px; padding: 1px 6px; border-radius: 999px;
  background: rgba(217,107,44,.12); color: var(--accent);
  font-weight: 600; font-variant-numeric: tabular-nums;
}
.tracklist .tactions .iconbtn { width: 28px; height: 28px; font-size: 14px; padding: 0; }
.tracklist li.unavailable { opacity: .55; }
.tracklist li.unavailable .ttitle { font-style: italic; }
.tracklist li.unavailable.sourcing { opacity: .85; }
.tracklist li.unavailable.sourcing::before {
  content: "⟳ "; animation: spin 1s linear infinite; display: inline-block;
}

/* ---------- right rail = QUEUE panel ---------- */
.rail-r { padding: 0; }
.queue-head { display: flex; align-items: center; gap: 10px;
  padding: 14px 18px; border-bottom: 1px solid var(--border);
  position: sticky; top: 0; background: var(--bg-rail-r); z-index: 2; }
.queue-head strong { font-size: 14px; letter-spacing: -.01em; }
.queue-head .muted { font-size: 11px; flex: 1; }
.rail-r-close { background: none; border: none; color: var(--fg-muted);
  width: 28px; height: 28px; border-radius: 999px; cursor: pointer; font-size: 18px; }
.rail-r-close:hover { color: var(--fg); background: rgba(127,127,127,.12); }
.rail-r-inner { padding: 14px 16px 18px; }
.queue-section { margin-bottom: 20px; }
.queue-section h4 { font-size: 10px; text-transform: uppercase; letter-spacing: .08em;
  color: var(--fg-muted); font-weight: 600; margin: 0 0 8px;
  padding-bottom: 6px; border-bottom: 1px solid var(--border); }
.queue-now { display: flex; gap: 12px; align-items: center; margin-bottom: 10px; }
/* Queue rail "now playing" art — defaults bigger than before (96px),
   and respects the same data-art-size attribute so picking "large" in
   Settings scales it up everywhere consistently. */
.queue-now-art { width: 96px; height: 96px; border-radius: 8px; object-fit: cover;
  background: var(--skeleton); transition: width .15s ease, height .15s ease; }
.queue-now-art.fallback { background: linear-gradient(135deg, var(--accent), var(--bg-player));
  display: grid; place-items: center; color: white; font-size: 32px; font-weight: 700; }
body[data-art-size="small"] .queue-now-art { width: 64px; height: 64px; border-radius: 6px; }
body[data-art-size="medium"] .queue-now-art { width: 96px; height: 96px; }
body[data-art-size="large"] .queue-now-art { width: 128px; height: 128px; }
body[data-art-size="xlarge"] .queue-now-art { width: 168px; height: 168px; border-radius: 10px; }
.queue-now-meta { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.queue-now-title { font-weight: 600; font-size: 14px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.queue-now-artist { font-size: 12px; color: var(--fg-muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.queue-actions { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 4px; }
.queue-actions .btn { font-size: 11px; padding: 4px 10px; }
.queue-list { list-style: none; margin: 0; padding: 0; }
.queue-list li { display: flex; align-items: center; gap: 10px;
  padding: 6px 4px; border-radius: 6px; cursor: pointer; }
.queue-list li:hover { background: rgba(127,127,127,.06); }
.queue-list li.empty { justify-content: center; color: var(--fg-muted); font-size: 12px;
  padding: 12px 0; cursor: default; }
.queue-thumb { width: 36px; height: 36px; border-radius: 4px; flex-shrink: 0; object-fit: cover; }
.queue-thumb.fallback { background: linear-gradient(135deg, var(--accent), var(--bg-player));
  display: grid; place-items: center; color: white; font-weight: 700; font-size: 14px; }
.queue-meta { min-width: 0; flex: 1; display: flex; flex-direction: column; }
.queue-title { font-size: 13px; font-weight: 500;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.queue-sub { font-size: 11px; color: var(--fg-muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.queue-row-actions { display: flex; gap: 2px; flex-shrink: 0; opacity: 0; transition: opacity .12s ease; }
.queue-list li:hover .queue-row-actions { opacity: 1; }
.iconbtn.tiny { width: 24px; height: 24px; padding: 0; font-size: 12px;
  background: rgba(127,127,127,.1); color: var(--fg); border-radius: 4px; opacity: 1; }
.iconbtn.tiny:hover { background: rgba(127,127,127,.25); }

/* ---------- transport bar (always visible) ---------- */
.player {
  background: var(--bg-player); color: var(--fg-on-dark);
  display: grid;
  /* Right column needs more room now that it carries: lyrics, cue, mini,
   * eq, settings, radio pill, buffer pill, focus dial, via/quality/bpm
   * pills + volume. Was 1fr → 1.6fr so extras fit without overflowing
   * into the controls column. */
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr) minmax(0, 1.6fr);
  align-items: center; gap: 14px; padding: 8px 18px;
  border-top: 1px solid rgba(255,255,255,.06);
}
.player[data-empty="true"] .player-now { opacity: .4; }
.player[data-empty="true"] .player-controls,
.player[data-empty="true"] .player-extras { opacity: .55; }
.player[data-empty="true"] .iconbtn { cursor: default; }
.player-now { display: flex; align-items: center; gap: 10px; min-width: 0; }
/* Album art size is user-controllable via data-art-size on the .player
   element. Default "medium" bumps the historical 56px up to 72px because
   the art is the most visually interesting thing on screen. "small"
   restores 56px for users who want more room for the title/artist;
   "large" goes 96px for the people who really want to see the cover.
   The empty-state placeholder mirrors the same sizes. */
.player-art-wrap { position: relative; width: 72px; height: 72px; flex-shrink: 0; }
.player-art { width: 72px; height: 72px; border-radius: 8px; object-fit: cover; background: #333;
  cursor: pointer; transition: transform .12s ease, width .15s ease, height .15s ease; display: block; }
.player-art:hover { transform: scale(1.04); }
/* !important on the size overrides because the base .player-art rule
   has the same effective specificity for the img (.player-art : 0,1,1)
   as the size-attribute rule for .player-art (body[attr] .player-art :
   0,2,1). Empirically Chrome was honoring the un-specific .player-art
   rule's width even though specificity should have favored the body-
   scoped one — I suspect a quirk with intrinsic <img> sizing once src
   loads. !important sidesteps the entire dance. */
body[data-art-size="small"] .player-art-wrap,
body[data-art-size="small"] .player-art,
body[data-art-size="small"] .player-art-empty { width: 56px !important; height: 56px !important; }
body[data-art-size="large"] .player-art-wrap,
body[data-art-size="large"] .player-art,
body[data-art-size="large"] .player-art-empty { width: 96px !important; height: 96px !important; }
body[data-art-size="xlarge"] .player-art-wrap,
body[data-art-size="xlarge"] .player-art,
body[data-art-size="xlarge"] .player-art-empty { width: 120px !important; height: 120px !important; border-radius: 10px; }
/* Player bar grows / shrinks with the art so nothing overlaps. */
body[data-art-size="small"] { --player-h: 84px; }
body[data-art-size="large"] { --player-h: 124px; }
body[data-art-size="xlarge"] { --player-h: 152px; }
.player[data-empty="true"] .player-art { display: none; }
.player-art-empty {
  width: 72px; height: 72px; border-radius: 8px; display: grid; place-items: center;
  background: rgba(255,255,255,.04); color: var(--fg-on-dark-muted); font-size: 32px;
}
.player:not([data-empty="true"]) .player-art-empty { display: none; }
.player-meta { min-width: 0; }
.player-title { font-weight: 600; cursor: pointer;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  border-bottom: 1px dotted transparent; }
.player-title:hover { color: var(--accent); border-bottom-color: currentColor; }
.player[data-empty="true"] .player-title,
.player[data-empty="true"] .player-artist { cursor: default; }
.player-artist { color: var(--fg-on-dark-muted); font-size: 12px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.player-controls { display: flex; flex-direction: column; gap: 4px; align-items: center; }
.player-buttons { display: flex; gap: 4px; align-items: center; }
.iconbtn {
  background: none; border: none; color: var(--fg-on-dark);
  font-size: 16px; padding: 6px 8px; cursor: pointer; opacity: .75;
  border-radius: 999px; transition: opacity .12s ease, background .12s ease;
  display: inline-flex; align-items: center; justify-content: center;
}
.iconbtn:hover { opacity: 1; }
/* Center inline SVG icons consistently across all iconbtns. The pointer
 * events:none on the SVG means clicks always target the <button>, not the
 * child paths — important since some handlers check e.target.closest('#id'). */
.iconbtn svg { display: block; pointer-events: none; }
.iconbtn:has(svg) { display: inline-flex; align-items: center; justify-content: center; }
/* Play button: white circle, SVG icon centred via flex (no glyph-offset hacks). */
.iconbtn.play {
  background: var(--fg-on-dark); color: var(--bg-player);
  width: 36px; height: 36px; padding: 0; opacity: 1;
}
.iconbtn.play svg { display: block; }
.iconbtn.play.is-playing svg { transform: scale(.9); }
.iconbtn.liked { color: var(--accent); opacity: 1; }
/* Thumbs up/down buttons — distinct from ♥. The .active class lights them
 * up with a subtle background so the user can see which signal they last
 * gave for the current track. */
.iconbtn.thumb-btn { font-size: 14px; }
.iconbtn.thumb-btn.active { background: rgba(217,107,44,.18); opacity: 1; }
.iconbtn.thumb-btn:hover { background: rgba(127,127,127,.18); }

/* Queue row "radio" tag — appears next to titles when the item was
 * interjected by the radio AI (vs. came from the user's playlist). */
.queue-tag.interject {
  font-size: 9px; padding: 1px 6px; border-radius: 999px; margin-left: 4px;
  background: rgba(217,107,44,.22); color: var(--accent); font-weight: 700;
  text-transform: uppercase; letter-spacing: .06em; vertical-align: 1px;
}
.queue-list li.interjected { background: linear-gradient(90deg, rgba(217,107,44,.06), transparent 70%); }
/* Active state for shuffle/repeat/radio buttons: accent color + a small
 * filled dot beneath the icon, so it's obviously a "toggled-on" state. */
.iconbtn.active { color: var(--accent); opacity: 1; position: relative; }
.iconbtn.active::after {
  content: ""; position: absolute; bottom: 2px; left: 50%; transform: translateX(-50%);
  width: 4px; height: 4px; border-radius: 50%; background: var(--accent);
}
/* Repeat badges — "1" (one-track loop) and "∞" (queue loop) in the bottom
   corner of the icon. The badge already tells the user which mode is on,
   so suppress the generic .active::after dot here to avoid visual clutter. */
#player-repeat { position: relative; }
#player-repeat.active::after { display: none; }
#player-repeat-one, #player-repeat-all { color: var(--accent); pointer-events: none; }
.player-bar { display: flex; gap: 10px; align-items: center; width: 100%; max-width: 600px; }
.player-time { font-size: 11px; color: var(--fg-on-dark-muted); font-variant-numeric: tabular-nums;
  min-width: 36px; text-align: center; }
.player-extras { display: flex; gap: 6px; align-items: center; justify-content: flex-end;
  flex-wrap: wrap; min-width: 0; }
.player-extras input[type=range] { max-width: 90px; min-width: 60px; }
input[type=range] { accent-color: var(--accent); flex: 1; }
.via-pill, .quality-pill, .bpm-pill { font-size: 10px; padding: 2px 8px; border-radius: 999px;
  background: rgba(255,255,255,.08); color: var(--fg-on-dark-muted); text-transform: uppercase;
  letter-spacing: .06em; font-weight: 600; }

/* Radio toggle pill — explicit ON/OFF label + colored dot. The state is
 * unmistakable at a glance: muted grey when off, accent-color filled when
 * on, with the word RADIO ON / RADIO OFF baked in. */
.radio-pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 10px; border-radius: 999px; cursor: pointer;
  background: rgba(255,255,255,.05); color: var(--fg-on-dark-muted);
  border: 1px solid rgba(255,255,255,.1);
  font: inherit; font-size: 10px; font-weight: 700; letter-spacing: .08em;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.radio-pill-dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--fg-on-dark-muted);
  transition: background .15s ease, box-shadow .15s ease;
}
.radio-pill:hover { color: var(--fg-on-dark); border-color: rgba(255,255,255,.2); }
.radio-pill.on {
  background: rgba(217,107,44,.18); color: var(--accent);
  border-color: var(--accent);
}
.radio-pill.on .radio-pill-dot {
  background: var(--accent);
  box-shadow: 0 0 8px var(--accent), 0 0 2px var(--accent);
  animation: radio-pulse 2s ease-in-out infinite;
}
@keyframes radio-pulse {
  0%, 100% { box-shadow: 0 0 8px var(--accent), 0 0 2px var(--accent); }
  50% { box-shadow: 0 0 14px var(--accent), 0 0 4px var(--accent); }
}

/* Buffer depth pill — tells you how many tracks the radio has lined up */
.buffer-pill { font-size: 10px; padding: 2px 8px; border-radius: 999px;
  background: rgba(120,200,120,.12); color: #6dc36d;
  font-weight: 600; letter-spacing: .04em;
  font-variant-numeric: tabular-nums; }
.buffer-pill[hidden] { display: none; }

/* Focus dial — 4 stops from "Artist only" (filled) to "Wide" (open) */
.focus-dial { display: inline-flex; gap: 2px; align-items: center;
  background: rgba(255,255,255,.06); border-radius: 999px;
  border: 1px solid rgba(255,255,255,.1); padding: 2px; }
.focus-step {
  width: 22px; height: 22px; padding: 0; border-radius: 999px;
  background: transparent; border: none; color: var(--fg-on-dark-muted);
  font-size: 11px; cursor: pointer; line-height: 1;
  display: grid; place-items: center;
  transition: background .12s ease, color .12s ease;
}
.focus-step:hover { color: var(--fg-on-dark); background: rgba(255,255,255,.05); }
.focus-step.active { background: var(--accent); color: white; }
.bpm-pill { background: rgba(120,200,120,.16); color: #6dc36d; font-variant-numeric: tabular-nums; }
.vibe-pill {
  font-size: 10px; padding: 2px 8px; border-radius: 999px;
  background: rgba(180,120,220,.16); color: #c39adb;
  text-transform: uppercase; letter-spacing: .06em; font-weight: 600;
  cursor: help;
}
/* Live VU meter — thin pulsing bar in the player extras. */
/* Live audio output level. The track underneath shows the full spectrum
   (green → yellow → red) at low alpha so the visible "headroom" is hinted
   at even when the bar is small; the bar itself fills with the SAME
   gradient sized to the meter width, so the visible portion always
   shows the level's position within the spectrum (low = green only,
   mid = green+yellow, hot = green+yellow+red). Width animates with
   60ms ease so transients pop visually. */
.vu-meter {
  width: 110px; height: 7px;
  background:
    linear-gradient(to right,
      rgba(109,195,109,.16) 0%,
      rgba(220,200,80,.16) 55%,
      rgba(224,112,96,.16) 88%,
      rgba(224,112,96,.28) 100%);
  border-radius: 999px; overflow: hidden; cursor: help; align-self: center;
  position: relative;
}
.vu-bar {
  height: 100%; width: 0;
  background:
    linear-gradient(to right,
      #4eb84e 0%,
      #6dc36d 28%,
      #d8c83c 60%,
      #e89a3c 80%,
      #e07060 95%,
      #d44a3a 100%);
  background-size: 110px 100%;       /* lock gradient to METER width, not bar width */
  background-repeat: no-repeat;
  transition: width 60ms linear;
  box-shadow: 0 0 6px rgba(224,112,96,.18);
}
.sleep-pill { background: rgba(120,140,220,.18); color: #8fa6e0; font-size: 10px;
  padding: 2px 8px; border-radius: 999px; border: 0; cursor: pointer; font-weight: 600;
  letter-spacing: .04em; font-variant-numeric: tabular-nums; text-transform: uppercase; }
.sleep-pill:hover { background: rgba(120,140,220,.32); color: #b3c5ef; }
.via-pill.tor { background: rgba(217,107,44,.2); color: var(--accent); }
.via-pill.cache { background: rgba(120,200,120,.16); color: #6dc36d; }
.quality-pill.lossless { background: rgba(120,200,120,.18); color: #6dc36d; }
.quality-pill.upgraded { background: rgba(217,107,44,.2); color: var(--accent); }

/* ---------- toast notifications ---------- */
.toast-stack {
  position: fixed; bottom: calc(var(--player-h) + 16px); right: 16px; z-index: 80;
  display: flex; flex-direction: column-reverse; gap: 8px; pointer-events: none;
}
.toast {
  background: var(--bg-card); color: var(--fg); border: 1px solid var(--border);
  padding: 10px 14px; border-radius: 8px; box-shadow: var(--shadow);
  display: flex; align-items: center; gap: 10px;
  min-width: 220px; max-width: 360px; font-size: 13px;
  animation: toast-in .18s ease-out;
}
.toast.success { border-left: 3px solid var(--accent); }
.toast.error   { border-left: 3px solid #c0392b; }
.toast .toast-icon { font-size: 18px; }
@keyframes toast-in {
  from { transform: translateY(10px); opacity: 0; }
  to   { transform: translateY(0); opacity: 1; }
}
.toast.leaving { animation: toast-out .25s ease-in forwards; }
@keyframes toast-out {
  to { transform: translateY(10px); opacity: 0; }
}

/* ---------- lyrics panel ---------- */
.lyrics-panel {
  position: fixed; bottom: calc(var(--player-h) + 10px); right: 16px; z-index: 60;
  width: min(92vw, 480px); max-height: 60vh;
  display: flex; flex-direction: column;
  background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow); color: var(--fg);
}
.lyrics-panel[hidden] { display: none !important; }
.lyrics-head {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 14px; border-bottom: 1px solid var(--border); flex-shrink: 0;
}
.lyrics-head strong { font-size: 13px; flex: 1; }
.lyrics-head .muted { font-size: 10px; text-transform: uppercase; letter-spacing: .06em; }
.lyrics-body { padding: 16px 18px; overflow-y: auto; line-height: 1.7; font-size: 14px; }
.lyrics-body .lyric-line { padding: 2px 0; transition: color .15s ease, font-weight .15s ease; color: var(--fg-muted); }
.lyrics-body .lyric-line.active { color: var(--accent); font-weight: 700; }
.lyrics-body .lyric-line.passed { color: var(--fg); }
.lyrics-body .empty { color: var(--fg-muted); text-align: center; padding: 30px 0; font-size: 13px; }

/* ---------- effects panel ---------- */
.fx-panel {
  position: fixed; bottom: calc(var(--player-h) + 10px); right: 16px; z-index: 60;
  width: min(92vw, 480px); padding: 14px 16px;
  background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow); color: var(--fg);
}
.fx-panel[hidden] { display: none !important; }
.fx-panel-head { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.fx-panel-head strong { font-size: 13px; letter-spacing: .04em; text-transform: uppercase; color: var(--fg-muted); flex-shrink: 0; }
.fx-presets { display: flex; gap: 4px; flex: 1; justify-content: center; }
.fx-presets .btn { font-size: 11px; padding: 4px 10px; }
.fx-rows { display: flex; flex-direction: column; gap: 10px; }
.fx-row { display: grid; grid-template-columns: 110px 1fr 60px; align-items: center;
  gap: 12px; font-size: 12px; }
.fx-row label { color: var(--fg); }
.fx-row input[type=range] { accent-color: var(--accent); }
.fx-row select { padding: 4px 8px; border-radius: 6px; border: 1px solid var(--border);
  background: var(--bg); color: var(--fg); font: inherit; font-size: 12px; }
.fx-val { font-variant-numeric: tabular-nums; color: var(--fg-muted); font-size: 11px; text-align: right; }

/* ---------- equalizer + settings panels ---------- */
.eq-panel, .settings-panel {
  position: fixed; bottom: calc(var(--player-h) + 10px); right: 16px; z-index: 60;
  width: min(92vw, 540px); padding: 14px 16px;
  background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow);
  color: var(--fg);
  /* Cap to viewport so the panel never overflows off-screen. The body
     scrolls inside; the head stays pinned via position: sticky below.
     16px breathing room above the panel + the existing 10px below the
     player gives ~26px of margin total. */
  max-height: calc(100vh - var(--player-h) - 36px);
  overflow-y: auto;
  /* Invisible scrollbar — user can still scroll via wheel/touch/drag,
     but the visual chrome is hidden so the panel looks clean. */
  scrollbar-width: none;          /* Firefox */
  -ms-overflow-style: none;       /* legacy IE/Edge */
}
.eq-panel::-webkit-scrollbar,
.settings-panel::-webkit-scrollbar { width: 0; height: 0; display: none; } /* Chrome/Safari */
.eq-panel[hidden], .settings-panel[hidden] { display: none !important; }
.eq-panel-head, .settings-head {
  display: flex; align-items: center; gap: 12px; margin-bottom: 12px;
  /* Pin the head so the title + close button stay reachable while the
     body scrolls. Negative top + matching bg keeps it flush with the
     panel's existing padding instead of leaving a gap. */
  position: sticky; top: -14px; background: var(--bg-card); z-index: 1;
  padding-top: 14px; margin-top: -14px;
}
.eq-panel-head strong, .settings-head strong { flex-shrink: 0; font-size: 13px; letter-spacing: .04em; text-transform: uppercase; color: var(--fg-muted); }
.eq-panel select { padding: 4px 8px; border-radius: 6px; border: 1px solid var(--border);
  background: var(--bg); color: var(--fg); font: inherit; font-size: 12px; }
.eq-panel .eq-toggle { display: flex; gap: 6px; align-items: center; font-size: 12px; color: var(--fg-muted); margin-left: auto; }
.eq-panel .iconbtn, .settings-panel .iconbtn { color: var(--fg); width: 24px; height: 24px; font-size: 14px; }
.eq-bands { display: grid; grid-template-columns: repeat(10, 1fr); gap: 8px; }
.eq-band { display: flex; flex-direction: column; align-items: center; gap: 4px; font-size: 10px; color: var(--fg-muted); }
.eq-band input[type=range] { writing-mode: vertical-lr; direction: rtl;
  -webkit-appearance: slider-vertical; appearance: slider-vertical;
  width: 8px; height: 100px; padding: 0; accent-color: var(--accent); }
.eq-band .eq-label { font-variant-numeric: tabular-nums; }
.eq-band .eq-val { font-size: 9px; opacity: .7; }

.settings-section { font-size: 10px; text-transform: uppercase; letter-spacing: .1em;
  color: var(--fg-muted); font-weight: 600; padding: 12px 0 4px;
  border-top: 1px solid var(--border); margin-top: 4px; }
.settings-section:first-of-type { border-top: none; margin-top: 0; }
.settings-row { display: grid; grid-template-columns: 1fr auto; align-items: center;
  gap: 4px 12px; padding: 10px 0; border-bottom: 1px solid var(--border); }
.settings-row:last-child { border-bottom: none; }
.settings-row > span:first-child { font-weight: 600; grid-column: 1; }
.settings-row > span.muted { font-size: 11px; grid-column: 1; }
.settings-row > input { grid-column: 2; grid-row: 1 / span 2; }
.settings-row.disabled { opacity: .5; }

/* Disliked items section: chips with × undo */
.dislike-block { padding: 6px 0; }
.dislike-block-h { font-size: 10px; color: var(--fg-muted); text-transform: uppercase;
  letter-spacing: .06em; margin-bottom: 4px; font-weight: 600; }
.dislike-chips { display: flex; flex-wrap: wrap; gap: 4px; }
.dislike-chip { display: inline-flex; align-items: center; gap: 2px;
  background: rgba(192,57,43,.12); color: #c0392b;
  padding: 3px 4px 3px 8px; border-radius: 999px; font-size: 11px; font-weight: 600; }
.dislike-undo { background: none; border: none; color: inherit; cursor: pointer;
  width: 18px; height: 18px; border-radius: 999px; padding: 0; font-size: 14px;
  display: inline-grid; place-items: center; opacity: .7; }
.dislike-undo:hover { opacity: 1; background: rgba(192,57,43,.2); }

/* ---------- mini player mode (?mini=1 popup) ---------- */
.mini-mode .rail-l, .mini-mode .main, .mini-mode .rail-r,
.mini-mode .topbar, .mini-mode #login,
.mini-mode .toast-stack, .mini-mode .lyrics-panel,
.mini-mode .eq-panel, .mini-mode .settings-panel { display: none !important; }
.mini-mode .app { grid-template-columns: 1fr; grid-template-rows: 1fr; grid-template-areas: "player"; }
.mini-mode .player { padding: 8px 12px; }
.mini-mode .player-extras { display: none; }
.mini-mode body { overflow: hidden; }

/* ---------- mobile ---------- */
@media (max-width: 900px) {
  .app { grid-template-columns: 0 minmax(0,1fr) 0;
    grid-template-areas: "main main main" "player player player"; }
  /* Drawer scrim — covers the page when either side rail is open, so the
     drawer reads as a clear modal overlay rather than just "a panel
     floating on top of the page". Tap the scrim to dismiss. */
  .drawer-scrim {
    position: fixed; inset: 0; background: rgba(0,0,0,.55);
    z-index: 45; opacity: 0; visibility: hidden;
    transition: opacity .2s ease, visibility .2s ease;
  }
  body.drawer-open .drawer-scrim { opacity: 1; visibility: visible; }
  body.drawer-open { overflow: hidden; }
  .rail-l { position: fixed; inset: 0 auto 0 0; width: 72vw; max-width: 260px; z-index: 50;
    transform: translateX(-100%); transition: transform .2s ease; flex-direction: column; align-items: stretch; padding: 16px 14px; gap: 4px;
    overflow-y: auto; -webkit-overflow-scrolling: touch; }
  .rail-l.open { transform: translateX(0); box-shadow: 0 0 60px rgba(0,0,0,.45); }
  .rail-l .iconbtn { width: 100%; height: 44px; justify-content: flex-start; padding: 0 12px; border-radius: 8px; }
  /* Rail-l on mobile expands from icon-only (72px desktop) to a labeled
     drawer. Make nav items full-width rows with the glyph on the left
     and a label (sourced from the existing title attr) on the right. */
  .rail-l .rail-brand { text-align: left; padding: 0 4px 8px; font-size: 20px; }
  .rail-l .rail-nav { gap: 2px; align-items: stretch; }
  .rail-l .rail-icon {
    width: 100%; height: 44px;
    display: flex; align-items: center; justify-content: flex-start;
    gap: 14px; padding: 0 12px; border-radius: 8px;
    font-size: 16px; color: var(--fg);
  }
  .rail-l .rail-icon::after {
    content: attr(title);
    font-size: 14px; color: var(--fg-muted); font-weight: 500;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .rail-l .rail-icon.active::after { color: white; }
  .rail-l .rail-divider { width: 100%; margin: 8px 0 6px; }
  .rail-l .rail-thumbs { padding: 0; align-items: stretch; gap: 2px; }
  .rail-l .rail-thumb { width: 100%; height: 44px; border-radius: 6px;
    display: flex; align-items: center; gap: 10px; padding: 4px; overflow: visible;
    text-decoration: none; color: var(--fg); }
  .rail-l .rail-icon { text-decoration: none; }
  .rail-l .rail-thumb img { width: 36px; height: 36px; flex-shrink: 0; border-radius: 6px; }
  .rail-l .rail-thumb-fallback { width: 36px; height: 36px; flex-shrink: 0; }
  .rail-l .rail-thumb::after {
    content: attr(title);
    font-size: 13px; color: var(--fg); font-weight: 500;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    flex: 1; min-width: 0;
  }
  .rail-l .rail-foot { align-items: stretch; padding-top: 10px; gap: 2px; }
  .rail-r { position: fixed; inset: 0 0 var(--player-h) auto; width: 88vw; max-width: 360px; z-index: 50;
    transform: translateX(100%); transition: transform .2s ease; }
  .rail-r:not([hidden]).open { transform: translateX(0); box-shadow: 0 0 60px rgba(0,0,0,.45); }

  /* Topbar — tighten so all right-side icons fit on a 393px Pixel 5 viewport.
     Forward/back nav rarely used on phones; hide. Right icons get a slight
     size reduction and tighter gap. Search input shrinks with placeholder
     swapped to a short version via JS. */
  .topbar { padding: 8px 10px; gap: 6px; }
  .topbar-nav { display: none; }
  .search { flex: 1 1 auto; min-width: 0; }
  .search input { padding: 8px 12px 8px 32px; background-size: 12px; background-position: 10px center; font-size: 13px; }
  .topbar-rright { width: 36px; height: 36px; min-width: 36px; }
  .topbar .iconbtn svg { width: 14px; height: 14px; }
  /* Phone player: ditch the 3-column desktop grid entirely. Flex-column
     so the three sections stack vertically without colliding. Explicit
     order so .player-extras (which has no order: rule by default → 0)
     doesn't render BEFORE .player-now and shove the art into column 2.
     Bug 2026-05-24: thumbs/like emojis "floating outside the dark
     container" + play button cut off were both manifestations of
     this mis-ordering. */
  .player {
    display: flex; flex-direction: column;
    grid-template-columns: none; grid-template-areas: none;
    padding: 8px 10px; gap: 6px; align-items: stretch;
  }
  .player-now { order: 1; gap: 6px; }
  .player-now .player-title { font-size: 13px; }
  .player-now .player-artist { font-size: 11px; }
  /* Save-offline cloud — useful but rare day-to-day; reachable from
     Settings → Advanced + the Liked Songs page. Reclaim its ~44px so
     the title has room to read. */
  .player-now > #player-offline { display: none; }
  /* Tighter thumb buttons so the title doesn't get clipped to "Nothing…" */
  .player-now .iconbtn { padding: 4px 4px; }
  .player-now .iconbtn.thumb-btn { min-width: 40px; min-height: 40px; font-size: 16px; }
  .player-controls { order: 2; flex-direction: row; gap: 8px;
    justify-content: center; flex-wrap: wrap; }
  .player-extras { order: 3; }
  /* On a phone the player is a 4-row vertical stack: now (art+title+
     thumbs) → controls (prev/play/next + shuffle + repeat) → seek
     bar → extras (mute, vol, settings). Each row is ~52-64px so the
     player ends up ~220-240px tall. Set --player-h tall enough that
     the page content below it doesn't peek through. */
  body { --player-h: 232px; }
  body[data-art-size="small"]  { --player-h: 216px; }
  body[data-art-size="large"]  { --player-h: 252px; }
  body[data-art-size="xlarge"] { --player-h: 280px; }
  /* Art shrinks on phones so the title has room to read; xlarge stays
     prominent if the user explicitly chose it. */
  body[data-art-size="medium"] .player-art-wrap,
  body[data-art-size="medium"] .player-art,
  body[data-art-size="medium"] .player-art-empty { width: 56px; height: 56px; }
  body:not([data-art-size]) .player-art-wrap,
  body:not([data-art-size]) .player-art,
  body:not([data-art-size]) .player-art-empty { width: 56px; height: 56px; }
  /* Mobile player controls — keep the essentials reachable from the phone
     so the user doesn't have to open a side rail to mute / change volume /
     open settings. Hide the chrome that's redundant (lyrics, EQ button —
     EQ is also accessible from Settings; quality/bpm/vibe pills; the
     radio focus dial — it's also in Settings; mini-player — desktop-only). */
  .player-extras { display: flex; gap: 4px; align-items: center; justify-content: flex-end;
    flex-wrap: wrap; min-width: 0; flex-shrink: 1; }
  .player-extras > #player-lyrics,
  .player-extras > #player-cue,
  .player-extras > #player-mini,
  .player-extras > #player-eq,
  .player-extras > #player-fx,
  .player-extras > #player-radio,
  .player-extras > #radio-buffer-depth,
  .player-extras > #focus-dial,
  .player-extras > #player-via,
  .player-extras > #player-quality,
  .player-extras > #player-bpm,
  .player-extras > #player-vibe { display: none; }
  /* Sleep pill stays visible only when actively armed (its [hidden] attr
     controls that). VU + mute + vol + settings are the essentials. Spread
     them across the row so they're easy to thumb-reach. */
  .player-extras { justify-content: space-between; padding: 0 4px; }
  .player-extras > #vu-meter { width: 50px; }
  .player-extras > #player-vol { flex: 1 1 auto; max-width: 180px; min-width: 80px; height: 32px; }
  /* Player play button — give it a clear accent so it reads as the
     primary affordance on a phone where the other buttons all look
     the same shade of muted grey. */
  .iconbtn.play { background: var(--accent, #c87437); color: #fff; }
  .iconbtn.play:active { transform: scale(0.95); }
  .iconbtn.play svg { width: 18px; height: 18px; }
  /* .player-bar is nested inside .player-controls (a flex-column) so it
     stacks under the play/next/prev row automatically. Re-show it and
     remove the desktop max-width so it can span the available column. */
  .player-bar { display: flex; width: 100%; padding: 0 4px; gap: 6px; max-width: none; }
  .player-controls { order: 2; }
  .player-now { order: 1; }
  /* Touch targets — Apple/Material both want ≥44px on touch. Bump every
     interactive control inside this block. Desktop sizes stay as declared. */
  .iconbtn { min-width: 44px; min-height: 44px; }
  .iconbtn.tiny { min-width: 40px; min-height: 40px; padding: 6px; font-size: 14px; }
  .iconbtn.small { min-width: 40px; min-height: 40px; padding: 6px; }
  .iconbtn.thumb-btn { min-width: 44px; min-height: 44px; font-size: 18px; }
  .btn.small { padding: 12px 16px; font-size: 13px; min-height: 44px; }
  /* Player play/next/prev are .iconbtn so caught above. The play button is
     .iconbtn.play (a circle) — keep its visual size but add hit padding. */
  .iconbtn.play { width: 48px; height: 48px; min-width: 48px; min-height: 48px; }
  /* DJ booth controls — stem toggles, transport, cue. */
  .dj-stem, .dj-deck-btn, [data-deck-play], [data-deck-cue] {
    min-height: 44px; padding: 10px 14px; }
  /* Radio focus dial pills — visible on the settings panel even when
     hidden from the player extras. Bump them too. */
  .focus-step { min-width: 36px; min-height: 36px; padding: 6px 8px; }
  /* Tracklist row tap targets — the entire row is clickable. */
  .tracklist li[data-idx] { min-height: 48px; padding: 8px 12px; }
  .tracklist .tactions .iconbtn { min-width: 40px; min-height: 40px; }
}

/* Phone: hide the VU meter — saves horizontal space in .player-extras */
@media (max-width: 480px) { #vu-meter { display: none; } }
