/* StreamForge — app-shell styles v4 (2026-09-14).
   Teardown + rebuild with agy (Google AI) research merged with in-house audit:
   bottom nav in the thumb zone, floating mini-player, one accent, no border
   cages, real type scale, two-column desktop so it never reads as a stretched
   phone page.  Class/ID contracts with app.js are preserved (see sw.js v4). */

:root {
  /* surfaces */
  --bg: #0a0c0f;
  --surface: #12161d;
  --elev: #181d26;
  --elev-2: #222936;
  --glass: rgba(16, 20, 26, 0.86);
  --line: rgba(255, 255, 255, 0.07);

  /* the ONLY accent */
  --accent: #35e0a1;
  --accent-dim: #169c46;
  --accent-glow: rgba(53, 224, 161, 0.22);
  --accent-soft: rgba(53, 224, 161, 0.14);

  /* text */
  --text: #f0f3f6;
  --text-dim: #9aa2ae;
  --text-faint: #5a6472;
  --on-accent: #041407;

  --danger: #ff5c5c;
  --warn: #ffb340;

  /* geometry */
  --radius: 12px;
  --nav-h: 62px;
  --player-h: 104px;
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);

  --shadow-dock: 0 10px 28px rgba(0, 0, 0, 0.55), 0 2px 6px rgba(0, 0, 0, 0.25);

  color-scheme: dark;
  accent-color: var(--accent);
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Inter, sans-serif;
  font-size: 16px;
  -webkit-font-smoothing: antialiased;
}

/* ------------------------------------------------------------------ shell */
body.appframe {
  display: flex;
  flex-direction: column;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
  overscroll-behavior: none;
}

svg.i { width: 24px; height: 24px; display: block; flex: none; }

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

/* ----------------------------------------------------------------- appbar */
header.appbar {
  flex: none;
  height: calc(56px + var(--safe-top));
  padding: var(--safe-top) 12px 0;
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--glass);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  border-bottom: 1px solid var(--line);
  z-index: 20;
}

.brand { display: flex; align-items: center; gap: 10px; font-weight: 700; letter-spacing: -0.01em; }
.brand img { width: 30px; height: 30px; border-radius: 8px; }
.brand span { font-size: 1rem; }
.spacer { flex: 1; }

.iconbtn {
  width: 44px;
  height: 44px;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: var(--text-dim);
  display: grid;
  place-items: center;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}
.iconbtn:hover { background: var(--elev); color: var(--text); }
.iconbtn:active { transform: scale(0.94); }
.iconbtn svg.i { width: 21px; height: 21px; }

/* ------------------------------------------------------------------- main */
main {
  flex: 1;
  overflow-y: auto;
  overscroll-behavior-y: contain;
  -webkit-overflow-scrolling: touch;
  padding: 16px 16px calc(var(--nav-h) + var(--safe-bottom) + 24px);
  scrollbar-width: thin;
  scrollbar-color: #2a313b transparent;
}
body.playing main { padding-bottom: calc(var(--nav-h) + var(--safe-bottom) + var(--player-h) + 28px); }
main::-webkit-scrollbar { width: 8px; }
main::-webkit-scrollbar-thumb { background: #262d37; border-radius: 4px; }

/* ------------------------------------------------------------ bottom nav */
.tabs {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  height: calc(var(--nav-h) + var(--safe-bottom));
  padding-bottom: var(--safe-bottom);
  display: flex;
  justify-content: space-around;
  align-items: stretch;
  background: var(--glass);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  border-top: 1px solid var(--line);
  z-index: 30;
}

.tab {
  appearance: none;
  -webkit-appearance: none;
  border: none;
  background: transparent;
  font: inherit;
  min-width: 64px;
  padding: 6px 10px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  color: var(--text-faint);
  cursor: pointer;
  border-radius: 10px;
  transition: color 0.15s ease;
}
.tab svg.i { width: 24px; height: 24px; }
.tab span { font-size: 11px; font-weight: 500; letter-spacing: 0.01em; }
.tab:hover { color: var(--text-dim); }
.tab.active { color: var(--accent); }
.tab.active span { font-weight: 600; }

/* ------------------------------------------------------------------ views */
.view { display: none; }
.view.active { display: block; }

/* ------------------------------------------------------------------- home */
.home-greeting {
  font-size: clamp(24px, 6vw, 30px);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.15;
  margin: 4px 0 18px;
}

/* quick-access grid: artwork-left tiles */
.quick-grid { display: grid; grid-template-columns: 1fr; gap: 8px; margin: 0 0 26px; }
@media (min-width: 560px) { .quick-grid { grid-template-columns: 1fr 1fr; } }

.quick-tile {
  display: flex;
  align-items: center;
  gap: 12px;
  height: 56px;
  background: var(--surface);
  border-radius: 8px;
  overflow: hidden;
  cursor: pointer;
  min-width: 0;
  transition: background 0.15s ease;
}
.quick-tile:hover { background: var(--elev); }
.quick-tile:active { transform: scale(0.99); }
.quick-tile img { width: 56px; height: 56px; object-fit: cover; flex: none; display: block; }
.quick-meta { min-width: 0; padding-right: 12px; }
.quick-meta .t {
  font-size: 13px;
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.quick-meta .a {
  font-size: 11px;
  font-weight: 400;
  color: var(--text-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* shelves */
.shelf { margin: 0 0 28px; }
.shelf-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 34px;
  margin: 0 0 12px;
}
.shelf-head h2, .hsec-title {
  font-size: 18px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--text);
  margin: 0;
}
.shelf-nav { display: none; gap: 6px; }
.shelf-btn {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: none;
  background: rgba(255, 255, 255, 0.06);
  color: var(--text-dim);
  display: grid;
  place-items: center;
  cursor: pointer;
}
.shelf-btn svg.i { width: 16px; height: 16px; }
.shelf-btn:hover { background: var(--elev-2); color: var(--text); }
@media (pointer: fine) {
  .shelf:hover .shelf-nav { display: flex; }
}

.shelf-row {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: clamp(134px, 38vw, 154px);  /* ~2.3 cards + peek */
  gap: 12px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  overscroll-behavior-x: contain;  /* horizontal swipe must not trigger back-nav */
  padding-bottom: 4px;
  scrollbar-width: none;
  contain: layout paint;
}
.shelf-row::-webkit-scrollbar { display: none; }
.shelf-row > .card { scroll-snap-align: start; }

.card { cursor: pointer; min-width: 0; }
.card-art {
  position: relative;
  aspect-ratio: 1 / 1;
  border-radius: 10px;
  overflow: hidden;
  background: var(--elev);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.28);
}
.card-art img { width: 100%; height: 100%; object-fit: cover; display: block; }
.card-fmt {
  position: absolute;
  top: 6px;
  left: 6px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  background: var(--accent-glow);
  color: var(--accent);
  backdrop-filter: blur(6px);
  border-radius: 4px;
  padding: 2px 6px;
}
.card-rank {
  position: absolute;
  bottom: 6px;
  left: 6px;
  font-size: 11px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  background: rgba(0, 0, 0, 0.72);
  color: #fff;
  border-radius: 4px;
  padding: 2px 6px;
}
.card-title {
  margin-top: 8px;
  font-size: 13px;
  font-weight: 700;
  line-height: 1.35;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.card-sub {
  font-size: 12px;
  color: var(--text-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
@media (hover: hover) {
  .card:hover .card-art { box-shadow: 0 0 0 2px var(--accent-dim), 0 4px 12px rgba(0, 0, 0, 0.28); }
}

/* ------------------------------------------------------------------ rows */
.results { display: grid; gap: 2px; }

.row {
  display: grid;
  grid-template-columns: 48px 1fr auto;
  gap: 12px;
  align-items: center;
  padding: 6px 10px;
  border-radius: 8px;
  cursor: pointer;
  min-height: 60px;
  transition: background 0.15s ease;
}
.row:hover { background: var(--surface); }
.row:active { background: var(--elev); }
.row img { width: 48px; height: 48px; border-radius: 6px; object-fit: cover; background: var(--elev); }
.row .meta { min-width: 0; }
.row .meta .t { font-size: 14px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.row .meta .a { color: var(--text-dim); font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.badge {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
  padding: 3px 8px;
  border-radius: 999px;
  background: var(--elev);
  color: var(--text-dim);
}
.badge.lossless { background: var(--accent-glow); color: var(--accent); }

.empty { text-align: center; color: var(--text-dim); padding: 56px 16px; line-height: 1.6; font-size: 14px; }
.empty b { color: var(--text); font-size: 15px; }

/* ----------------------------------------------------------------- search */
.searchwrap {
  position: sticky;
  top: 0;
  z-index: 4;
  padding: 4px 0 12px;
  background: linear-gradient(180deg, var(--bg) 82%, transparent);
}
.searchpill {
  display: flex;
  align-items: center;
  gap: 10px;
  height: 46px;
  padding: 0 16px;
  border-radius: 999px;
  background: var(--surface);
  border: 1px solid var(--line);
  transition: border-color 0.15s ease;
}
.searchpill:focus-within { border-color: var(--accent-dim); }
.searchpill .lens { width: 18px; height: 18px; color: var(--text-dim); }
.searchpill input {
  flex: 1;
  min-width: 0;
  border: none;
  background: transparent;
  color: var(--text);
  font-size: 15px;
  outline: none;
  height: 100%;
}
.searchpill input::-webkit-search-cancel-button { -webkit-appearance: none; }

/* ----------------------------------------------------------------- status */
.statuscard {
  background: var(--surface);
  border-radius: 14px;
  padding: 16px;
  display: grid;
  gap: 10px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.28);
}
.kv { display: flex; justify-content: space-between; align-items: baseline; font-size: 13px; gap: 12px; }
.kv span:first-child { color: var(--text-dim); }
.kv b { font-variant-numeric: tabular-nums; }
.pill { padding: 3px 10px; border-radius: 999px; font-size: 11px; font-weight: 600; background: var(--elev); }
.pill.ok { background: var(--accent-glow); color: var(--accent); }
.pill.bad { background: rgba(255, 92, 92, 0.15); color: var(--danger); }

/* ----------------------------------------------------------------- player */
.player {
  position: fixed;
  left: 10px;
  right: 10px;
  bottom: calc(var(--nav-h) + var(--safe-bottom) + 10px);
  padding: 10px 12px calc(10px + 4px);
  background: rgba(22, 27, 34, 0.94);
  backdrop-filter: blur(24px);
  -webkit-backdrop-filter: blur(24px);
  border: 1px solid var(--line);
  border-radius: 14px;
  box-shadow: var(--shadow-dock);
  display: grid;
  grid-template-columns: 48px 1fr auto;
  gap: 4px 12px;
  align-items: center;
  z-index: 40;
}
.player[hidden] { display: none; }  /* author display would beat UA [hidden] */

/* the audio element drives playback but is never visible; on the desktop grid
   an unstyled <audio> would become a phantom grid item */
audio#audio { display: none; }

.player img { width: 48px; height: 48px; border-radius: 8px; object-fit: cover; background: var(--elev); }
.player .info { min-width: 0; }
.player .info .t { font-size: 13px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.player .info .a { color: var(--text-dim); font-size: 11px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.acq {
  font-size: 11px;
  color: var(--text-dim);
  margin-top: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.acq .ok { color: var(--accent); }
.acq .busy { color: var(--warn); }
.acq .bad { color: var(--danger); }

.controls { display: flex; align-items: center; gap: 2px; }
.ctl {
  background: transparent;
  border: none;
  color: var(--text);
  width: 44px;
  height: 44px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  cursor: pointer;
}
.ctl svg.i { width: 20px; height: 20px; }
.ctl:hover { background: var(--elev); }
.ctl.primary {
  width: 44px;
  height: 44px;
  background: var(--accent);
  color: var(--on-accent);
}
.ctl.primary svg.i { width: 22px; height: 22px; }
.ctl.primary:hover { background: #22e56b; }
.ctl:disabled { opacity: 0.35; }

.seekwrap { grid-column: 1 / -1; display: flex; align-items: center; gap: 8px; margin-top: 2px; }
.seekwrap input[type=range] {
  flex: 1;
  appearance: none;
  -webkit-appearance: none;
  height: 4px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--accent) var(--pct, 0%), var(--elev-2) var(--pct, 0%));
  outline: none;
}
.seekwrap input[type=range]::-webkit-slider-thumb {
  appearance: none;
  -webkit-appearance: none;
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background: #fff;
  border: none;
}
.time { font-size: 11px; color: var(--text-dim); font-variant-numeric: tabular-nums; min-width: 34px; text-align: center; }

/* ------------------------------------------------------------------ toast */
.toast {
  position: fixed;
  left: 50%;
  transform: translateX(-50%) translateY(-140%);
  top: calc(12px + var(--safe-top));
  background: var(--elev-2);
  border: 1px solid var(--line);
  color: var(--text);
  padding: 10px 16px;
  border-radius: 12px;
  z-index: 60;
  transition: transform 0.28s ease;
  font-size: 14px;
  max-width: 90vw;
  box-shadow: var(--shadow-dock);
}
.toast.show { transform: translateX(-50%) translateY(0); }

.spinner {
  width: 26px;
  height: 26px;
  border: 3px solid #26303c;
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
  margin: 24px auto;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ------------------------------------------------------------------ login */
.loginbody {
  display: grid;
  place-items: center;
  padding: calc(20px + var(--safe-top)) 20px 20px;
  min-height: 100vh;
  min-height: 100dvh;
  background: radial-gradient(1000px 500px at 50% -10%, #14211a, var(--bg));
}
.card {
  width: 100%;
  max-width: 380px;
  background: var(--surface);
  border-radius: 20px;
  padding: 26px 22px;
  display: grid;
  gap: 14px;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.45);
}
.card .logo { display: grid; place-items: center; gap: 8px; margin-bottom: 4px; }
.card .logo img { width: 62px; height: 62px; border-radius: 16px; }
.card h1 { margin: 0; font-size: 1.25rem; text-align: center; }
.card p.sub { margin: 0; color: var(--text-dim); font-size: 0.88rem; text-align: center; }
.field { display: grid; gap: 6px; }
.field label { font-size: 0.8rem; color: var(--text-dim); letter-spacing: 0.3px; }
.field input {
  padding: 13px 14px;
  border-radius: 11px;
  border: 1px solid var(--line);
  background: var(--bg);
  color: var(--text);
  font-size: 1rem;
  outline: none;
  width: 100%;
}
.field input:focus { border-color: var(--accent-dim); }
.field input.totp { letter-spacing: 8px; font-size: 1.15rem; text-align: center; }
.remember {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 2px 0 12px;
  font-size: 13px;
  color: var(--text-dim);
  cursor: pointer;
  user-select: none;
}
.remember input { width: 16px; height: 16px; flex: none; accent-color: var(--accent); }
button.submit, a.submit {
  margin-top: 4px;
  padding: 14px;
  border: none;
  border-radius: 12px;
  background: var(--accent);
  color: var(--on-accent);
  font-weight: 700;
  font-size: 1rem;
  cursor: pointer;
  text-align: center;
  text-decoration: none;
  display: block;
}
button.submit:hover, a.submit:hover { background: #22e56b; }
button.submit:disabled { opacity: 0.6; }
.err {
  color: var(--danger);
  font-size: 0.85rem;
  min-height: 18px;
  text-align: center;
  background: rgba(255, 92, 92, 0.09);
  border-radius: 8px;
  padding: 5px 8px;
  display: none;
}
.err.show { display: block; }
.hint { color: var(--text-dim); font-size: 0.74rem; text-align: center; line-height: 1.5; margin: 0; }

/* ---------------------------------------------------------------- desktop */
@media (min-width: 940px) {
  body.appframe {
    display: grid;
    grid-template-columns: 236px 1fr;
    grid-template-rows: auto 1fr auto;
    grid-template-areas:
      "header header"
      "nav main"
      "player player";
    height: 100vh;
    height: 100dvh;
  }

  header.appbar { grid-area: header; height: 64px; padding: 0 20px; }
  .tabs {
    grid-area: nav;
    position: static;
    height: auto;
    padding: 16px 10px;
    flex-direction: column;
    justify-content: flex-start;
    align-items: stretch;
    gap: 4px;
    background: transparent;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    border-top: none;
    border-right: 1px solid var(--line);
  }
  .tab {
    flex-direction: row;
    justify-content: flex-start;
    gap: 14px;
    min-width: 0;
    padding: 12px 14px;
    border-radius: 10px;
    font-size: 15px;
  }
  .tab span { font-size: 15px; }
  .tab.active { background: var(--elev); color: var(--text); }
  .tab.active svg.i { color: var(--accent); }

  main {
    grid-area: main;
    padding: 28px 40px 40px;
  }

  .player {
    grid-area: player;
    position: static;
    left: auto;
    right: auto;
    bottom: auto;
    margin: 0;
    border-radius: 0;
    border-left: none;
    border-right: none;
    border-bottom: none;
    grid-template-columns: 320px 1fr auto;
    grid-template-rows: none;
    padding: 10px 24px;
  }
  .player .seekwrap { grid-column: 1 / -1; }
  .shelf-row { grid-auto-columns: 172px; }
  .quick-grid { grid-template-columns: 1fr 1fr 1fr; }
  body.playing main { padding-bottom: 40px; }
}

/* --------------------------------------------------------------- motion */
@media (prefers-reduced-motion: reduce) {
  * { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }
  .shelf-row { scroll-snap-type: none; }
}

/* ---- admin (2026-09-14) ---- */

.adminbar { display: flex; justify-content: flex-end; margin: 0 0 12px; }
.adminbar .submit { margin: 0; padding: 10px 16px; }

.adminform {
  display: grid;
  gap: 10px;
  background: var(--surface);
  border-radius: 14px;
  padding: 16px;
  margin: 0 0 14px;
}
.adminfield { display: grid; gap: 4px; }
.adminfield label { font-size: 12px; color: var(--text-dim); }
.adminfield input, .adminfield select {
  padding: 10px 12px;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: var(--bg);
  color: var(--text);
  font-size: 15px;
  outline: none;
  width: 100%;
}
.adminfield input:focus, .adminfield select:focus { border-color: var(--accent-dim); }
.adminrow { display: flex; gap: 10px; align-items: center; }
.adminrow .submit { margin: 0; padding: 11px 16px; }

.userrow {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 10px;
  background: var(--surface);
  border-radius: 12px;
  padding: 12px;
  margin: 0 0 8px;
}
.userrow .meta { min-width: 0; }
.userrow .meta .t { font-size: 14px; font-weight: 600; }
.userrow .meta .a { color: var(--text-dim); font-size: 12px; margin-top: 2px; }
.userchips { display: flex; gap: 6px; align-items: flex-start; }
.chip {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  padding: 3px 8px;
  border-radius: 999px;
  background: var(--elev);
  color: var(--text-dim);
}
.chip-admin { background: var(--accent-glow); color: var(--accent); }
.chip-ok { color: var(--accent); }
.chip-bad { background: rgba(255, 92, 92, 0.15); color: var(--danger); }

.useracts { grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: 6px; }
.ubtn {
  border: 1px solid var(--line);
  background: transparent;
  color: var(--text-dim);
  font-size: 12px;
  font-weight: 600;
  padding: 7px 10px;
  border-radius: 8px;
  cursor: pointer;
}
.ubtn:hover { background: var(--elev); color: var(--text); }
.ubtn-primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.ubtn-danger { color: var(--danger); }
.ubtn-danger:hover { background: rgba(255, 92, 92, 0.12); color: var(--danger); }

.pwreset { grid-column: 1 / -1; display: flex; gap: 8px; }
.pwreset input {
  flex: 1;
  min-width: 0;
  padding: 9px 12px;
  border-radius: 8px;
  border: 1px solid var(--line);
  background: var(--bg);
  color: var(--text);
  outline: none;
}

.adminsecret {
  background: var(--surface);
  border: 1px solid rgba(30, 215, 96, 0.35);
  border-radius: 12px;
  padding: 14px;
  margin: 0 0 14px;
}
.adminsecret .t { font-weight: 700; font-size: 14px; margin-bottom: 8px; }
.secretbox {
  background: var(--bg);
  border-radius: 8px;
  padding: 10px;
  overflow-x: auto;
  font-size: 12px;
  color: var(--accent);
  white-space: pre-wrap;
  word-break: break-all;
  margin: 0 0 8px;
}

/* Dashboard Upgrade */
.home-hero-container {
  padding: 32px 24px;
  background: linear-gradient(135deg, rgba(30,215,96,0.15) 0%, rgba(10,12,15,0) 100%);
  border-bottom: 1px solid var(--line);
  margin-bottom: 16px;
  border-radius: 0 0 24px 24px;
}
#homeGreeting {
  font-size: 2rem;
  font-weight: 800;
  letter-spacing: -0.03em;
  margin-bottom: 24px;
  background: -webkit-linear-gradient(#fff, #9aa2ae);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}
.quick-tile {
  background: var(--elev);
  border: 1px solid var(--line);
  transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1), background 0.2s;
}
.quick-tile:hover {
  transform: translateY(-2px);
  background: var(--elev-2);
}
.shelf-row .card {
  transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}
.shelf-row .card:hover {
  transform: translateY(-4px);
}



.shelf { content-visibility: auto; contain-intrinsic-size: 1000px 240px; contain-intrinsic-size: auto 1000px auto 240px; }

/* ==================================================================
   StreamForge dashboard v5 (2026-09-14) — Spotify-class home.
   Appended to styles.css; every rule here WINS the cascade over the
   v4 base because it lands later at equal specificity.

   Performance contract (low-end Android, no GPU blur budget):
   - ZERO backdrop-filter. The v4 chrome (appbar, tabs, player) and the
     .card-fmt chip blurred every scrolling frame underneath; they are
     neutralised below with opaque surfaces painted once.
   - Only `transform` and `opacity` transition (compositor properties).
     No shadow/colour is ever animated; hover shadows swap in one paint.
   - Hero is layered radial/linear gradients: one paint, then free.
   - Card-level content-visibility completes Path A: of the 450 home
     cards, only the viewport-proximate ones are laid out and painted.
   ================================================================== */

:root {
  --gutter: 16px;                        /* main's inline padding, shared */
  --chrome: #0d1015;                     /* solid appbar/nav/player chrome */
  --card-shadow: 0 6px 18px rgba(0, 0, 0, 0.42);
  --pop: cubic-bezier(0.22, 0.61, 0.36, 1);
  /* hero mood stops — set per time of day by app.js via [data-mood] */
  --hero-0: #10241a;
  --hero-1: #1d4a2c;
  --hero-2: #1f4a4a;
}
@media (min-width: 940px) {
  :root { --gutter: 40px; }
}

/* ------------------------------------------------- de-blur the chrome
   The single biggest GPU win on the Android device: three fixed layers
   were blur(20-24px)-ing the entire scrolling surface every frame. */
header.appbar,
.tabs {
  background: var(--chrome);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
.player {
  background: #151a21;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

/* -------------------------------------------------------------- hero */
.home-hero-container {
  position: relative;
  margin: calc(-1 * var(--gutter)) calc(-1 * var(--gutter)) 22px;
  padding: 16px var(--gutter) 20px;
  border-radius: 0 0 22px 22px;
  border-bottom: 1px solid var(--line);
  overflow: hidden;
  background:
    radial-gradient(110% 80% at 88% -12%, var(--hero-2) 0%, transparent 55%),
    radial-gradient(120% 95% at -8% 12%, var(--hero-1) 0%, transparent 58%),
    radial-gradient(90% 60% at 20% 0%, rgba(255, 255, 255, 0.06) 0%, transparent 60%),
    linear-gradient(180deg, var(--hero-0) 0%, var(--bg) 96%);
}

/* time-of-day palettes (set by app.js on [data-mood]) */
.home-hero-container[data-mood='morning'] {
  --hero-0: #2b2410;
  --hero-1: #57441a;
  --hero-2: #1d4a2c;
}
.home-hero-container[data-mood='afternoon'] {
  --hero-0: #10241a;
  --hero-1: #1d4a2c;
  --hero-2: #1f4a4a;
}
.home-hero-container[data-mood='evening'] {
  --hero-0: #191633;
  --hero-1: #3a2a63;
  --hero-2: #143a5a;
}
.home-hero-container[data-mood='late'] {
  --hero-0: #0d1126;
  --hero-1: #26224e;
  --hero-2: #173a56;
}

/* the greeting: solid white, bigger, tighter (replaces the old
   gradient-text hack — crisper and one less paint path) */
#homeGreeting {
  font-size: clamp(26px, 7.2vw, 34px);
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1.08;
  margin: 2px 0 4px;
  color: #fff;
  background: none;
  -webkit-text-fill-color: #fff;
}
.home-greeting { margin: 2px 0 4px; }

/* "Jump back in" caption inside the hero */
#homeHero .hsec-title {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.62);
  margin: 18px 2px 10px;
}

/* -------------------------------------------------- quick-access grid
   2 columns on mobile, 3 on desktop (beats the v4 1-col/2-col rules by
   cascade order). Tiles float translucent over the hero gradient. */
.quick-grid {
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin: 0;
}
@media (min-width: 940px) {
  .quick-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.quick-tile {
  height: 60px;
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.07);
  transition: background 0.16s ease, transform 0.16s var(--pop);
}
.quick-tile:hover {
  background: rgba(255, 255, 255, 0.13);
  transform: translateY(-2px);
}
.quick-tile img {
  width: 58px;
  height: 58px;
  border-radius: 11px 0 0 11px;
  box-shadow: 3px 0 10px rgba(0, 0, 0, 0.35);
}
.quick-meta { padding-right: 6px; }
.quick-meta .t { color: #fff; }
.quick-meta .a { color: rgba(255, 255, 255, 0.62); }

/* hover-reveal play affordance (pointer devices only; touch users tap
   the tile itself, exactly like Spotify's shortcuts) */
.quick-play {
  flex: none;
  width: 30px;
  height: 30px;
  margin-right: 10px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--on-accent);
  display: grid;
  place-items: center;
  opacity: 0;
  transform: translateX(6px);
  transition: opacity 0.16s ease, transform 0.16s var(--pop);
  pointer-events: none;
}
.quick-play svg.i { width: 14px; height: 14px; }
@media (hover: hover) {
  .quick-tile:hover .quick-play { opacity: 1; transform: none; }
}

/* ------------------------------------------------------------ shelves
   Edge bleed: cards align with the page gutter and scroll edge-to-edge
   like a native app, instead of stopping inside the padding. */
.shelf-row {
  margin-inline: calc(-1 * var(--gutter));
  padding-inline: var(--gutter);
  scroll-padding-inline: var(--gutter);
  grid-auto-columns: clamp(140px, 41vw, 158px);
}
@media (min-width: 940px) {
  .shelf-row { grid-auto-columns: 180px; }
}

/* DOM-4: card-level content-visibility is REVERSED.  These cards are the
   scroll-snap children of a `scroll-snap-type: x mandatory` row: a skipped
   card carried an estimated size, and when it was revealed that estimate
   snapped to the real one, dragging every following snap target out from
   under the finger.  The shelf-level rule above still virtualises, which is
   where the actual win was.
   DOM-5: the shelf's intrinsic size guessed a 1000px WIDTH for an element
   that is container-width, so first paint could overflow and snap back.
   Realistic width, measured height. */
.shelf { contain-intrinsic-size: auto 360px auto 276px; }

/* -------------------------------------------------------------- cards */
.card-art {
  border-radius: 12px;
  box-shadow: var(--card-shadow);
}

/* FLAC chip: solid dark glass-look, no blur filter */
.card-fmt {
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  background: rgba(8, 11, 14, 0.82);
  color: #35e06c;
}

/* the play overlay — injected by app.js as
   <button class="card-play"><svg class="i"><use href="#i-play"/></svg></button> */
.card-play {
  position: absolute;
  right: 8px;
  bottom: 8px;
  width: 42px;
  height: 42px;
  border: none;
  border-radius: 50%;
  background: var(--accent);
  color: var(--on-accent);
  display: grid;
  place-items: center;
  cursor: pointer;
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.5);
  opacity: 0;
  transform: translateY(10px) scale(0.86);
  transition: opacity 0.18s ease, transform 0.18s var(--pop), background 0.15s ease;
  pointer-events: none;
}
.card-play svg.i { width: 18px; height: 18px; }
.card-play:active { transform: scale(0.9); background: #22e56b; }

@media (hover: hover) {
  .card:hover .card-play,
  .card:focus-visible .card-play,
  .card-play:focus-visible {
    opacity: 1;
    transform: none;
    pointer-events: auto;
  }
  .card-play:hover { background: #22e56b; }
}
/* touch devices: persistent 38px badge — the card reads as playable
   without waiting for a long-press, and the card itself still plays */
@media (hover: none) {
  .card-play {
    opacity: 1;
    transform: none;
    pointer-events: auto;
    width: 38px;
    height: 38px;
    right: 7px;
    bottom: 7px;
  }
}

/* circular-artist variant, ready for future artist shelves:
   app.js adds `card--round` when a section id contains "artist" */
.card--round .card-art { border-radius: 50%; }
.card--round .card-rank { left: 50%; transform: translateX(-50%); }
.card--round .card-title,
.card--round .card-sub { text-align: center; }

/* ==================================================================
   StreamForge dashboard v7 (2026-09-14) -- mixed layouts, not rows.

   Appended to styles.css; every rule here wins the cascade over v4/v5.
   Layout grammar, all driven by app.js from the payload's `kind`:
     .sf-hero        one giant featured banner (personal shelf, item #1)
     .quick-grid     the Spotify-style tile grid (rest of that shelf)
     (.chart-duo / .chart-row vertical lists -- removed in patch15, see
      the CSS-6 note below; nothing has emitted those nodes since patch14)
     .shelf--mix     mood carousels get a distinct accent treatment
   Performance contract (low-end Android, v5 rules still apply):
     - zero backdrop-filter; the hero wash is one image paint under a
       plain gradient overlay -- no filters, no masks
     - only transform/opacity transition
     - (the chart rows this used to promise were removed in patch15)
   ================================================================== */

/* ---------------------------------------------------------- hero block */
#homeHero { display: grid; gap: 18px; }

.sf-hero {
  position: relative;
  display: grid;
  grid-template-columns: 88px 1fr auto;
  gap: 12px;
  align-items: center;
  padding: 14px;
  border: 1px solid var(--line);
  border-radius: 18px;
  background:
    linear-gradient(135deg, var(--accent-soft, rgba(30, 215, 96, 0.10)), transparent 46%),
    var(--elev, #181d26);
  overflow: hidden;
  cursor: pointer;
}
/* decorative artwork wash, faded into the panel by a plain gradient */
.sf-hero-wash {
  position: absolute;
  top: 0;
  right: 0;
  width: 64%;
  height: 100%;
  object-fit: cover;
  opacity: 0.17;
  pointer-events: none;
}
.sf-hero::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, rgba(24, 29, 38, 0.96) 6%, rgba(24, 29, 38, 0) 64%);
  pointer-events: none;
}
.sf-hero-art {
  position: relative;
  z-index: 1;
  width: 88px;
  height: 88px;
  border-radius: 14px;
  object-fit: cover;
  background: var(--surface, #12161d);
  box-shadow: 0 10px 26px rgba(0, 0, 0, 0.5);
}
.sf-hero-body { position: relative; z-index: 1; min-width: 0; }
.sf-hero-kicker {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 6px;
}
.sf-hero-title {
  font-size: clamp(19px, 5.4vw, 26px);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.12;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.sf-hero-sub {
  margin-top: 5px;
  font-size: 12.5px;
  color: var(--text-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.sf-hero-play {
  position: relative;
  z-index: 1;
  width: 48px;
  height: 48px;
  border: none;
  border-radius: 50%;
  background: var(--accent);
  color: var(--on-accent, #041407);
  display: grid;
  place-items: center;
  box-shadow: 0 10px 24px var(--accent-glow);
  transition: transform 0.16s var(--pop, cubic-bezier(0.22, 0.61, 0.36, 1));
  cursor: pointer;
}
.sf-hero-play svg.i { width: 20px; height: 20px; }
.sf-hero-play:active { transform: scale(0.92); }
@media (min-width: 560px) {
  .sf-hero { grid-template-columns: 116px 1fr auto; gap: 16px; padding: 18px; }
  .sf-hero-art { width: 116px; height: 116px; }
  .sf-hero-play { width: 54px; height: 54px; }
  .sf-hero-play svg.i { width: 22px; height: 22px; }
}
.sf-hero:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* CSS-6 (patch15): the v7 vertical chart list is deleted in full -- the
   two-up wrapper, its heading, subtitle, list wrapper, every row, the rank,
   the per-row text block, the hover play affordance and the toggle.  Nothing
   has emitted those nodes since patch14 moved charts into Bento panels, so
   every rule here was inert: ~150 lines parsed and matched on every repaint
   for nothing.  .shelf--mix, immediately below, IS still live and was left
   alone. */

/* ------------------------------------- mood shelves keep the carousel */
.shelf--mix .shelf-head h2 {
  color: var(--text);
  text-transform: none;
  font-size: 15px;
  font-weight: 800;
  letter-spacing: -0.01em;
}
.shelf--mix .shelf-head h2::before {
  content: '';
  display: inline-block;
  width: 18px;
  height: 4px;
  border-radius: 2px;
  margin-right: 8px;
  background: var(--accent);
  vertical-align: 4px;
}

/* ==================================================================
   StreamForge dashboard v8 (2026-09-14) -- charts rank the artwork.

   Appended to styles.css; every rule here wins the cascade over v4/v5/v7.
   (patch15 deleted the v7 vertical chart list that this block once promised
   to keep for rollback -- nothing emits it, and dead CSS is not free.  See
   the CSS-6 note below.)

   patch15: the ranked-carousel rules this block introduced, and the
   "Regional" kicker, are deleted -- patch14 had already moved charts and
   regional picks into Bento panels, so those selectors matched nothing.
   What survives v8 is the stacked shelf head (.shelf-head-box /
   .shelf-kicker / .shelf-sub), still rendered by makeShelf() and makeBento().

   Performance contract (low-end Android, v5 rules still apply):
     - zero backdrop-filter; the chart scrim and the hero wash are plain
       gradients
     - only transform/opacity transition
     - text-shadow on the rank is a one-off paint, not a per-frame cost
   ================================================================== */

/* ------------------------------------------- shelf head: stacked box */
.shelf-head-box {
  display: grid;
  gap: 2px;
  min-width: 0;
}
.shelf-kicker {
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
}
.shelf-sub {
  font-size: 12px;
  color: var(--text-dim);
}

/* CSS-6 (patch15): the ranked-carousel rules -- the chart-scoped shelf-row
   width, the .card-art radius, its ::after scrim, the giant .card-rank, the
   .card-play z-index and the podium nth-child -- and the regional kicker
   are deleted with the Bento move.  .shelf-head-box, .shelf-kicker and
   .shelf-sub above are still rendered and stay. */

/* ==================================================================
   StreamForge patch13 (2026-09-14) -- a queue you can see, playlists.

   Appended to styles.css; every rule here wins the cascade over
   v4/v5/v8.

   Queue sheet: slides up over the player (mobile) / docks bottom-right
   (desktop).  The playing row is highlighted, played rows are dimmed,
   everything from queueIndex+1 sits under it.

   Performance contract (low-end Android, v5 rules still apply):
     - zero backdrop-filter in this block; the scrim is one flat colour
       and the sheet is opaque
     - only transform/opacity transition
     - every [hidden] element here carries its own display:none, because
       .queue { display:flex } would otherwise beat the UA rule (the v4
       lesson: that is how an empty panel stays on screen forever)
   ================================================================== */

/* ------------------------- player aux buttons: queue + add to playlist */
.ctl.aux {
  width: 34px;
  height: 34px;
  flex: 0 0 auto;
  color: var(--text-dim);
}
.ctl.aux svg.i { width: 18px; height: 18px; }
.ctl.aux:hover { color: var(--text); background: var(--elev); }
.ctl.aux.on { color: var(--accent); }
.ctl.aux.busy { color: var(--accent); }

/* --------------------------------------------- queue sheet + its scrim */
.scrim {
  position: fixed;
  inset: 0;
  background: rgba(4, 6, 9, 0.62);
  opacity: 0;
  transition: opacity 0.22s ease;
  z-index: 44;
}
.scrim.open { opacity: 1; }
.scrim[hidden] { display: none; }

.queue {
  position: fixed;
  left: 10px;
  right: 10px;
  bottom: calc(var(--nav-h) + var(--safe-bottom) + var(--player-h) + 18px);
  max-width: 560px;
  margin: 0 auto;
  max-height: min(62vh, 560px);
  display: flex;
  flex-direction: column;
  background: #151a21;
  border: 1px solid var(--line);
  border-radius: 16px;
  box-shadow: var(--shadow-dock);
  opacity: 0;
  transform: translateY(18px) scale(0.99);
  transition: opacity 0.22s ease, transform 0.22s var(--pop, ease);
  overflow: hidden;
  z-index: 45;
}
.queue.open { opacity: 1; transform: translateY(0) scale(1); }
.queue[hidden] { display: none; }
.queue-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 10px 10px 16px;
  border-bottom: 1px solid var(--line);
}
.queue-titles { flex: 1; min-width: 0; }
.queue-title { font-size: 15px; font-weight: 800; letter-spacing: -0.01em; }
.queue-sub { font-size: 12px; color: var(--text-dim); }
.queue-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  padding: 6px 6px 10px;
}
.qrow-now { background: var(--accent-glow); }
.qrow-now .badge { background: var(--accent); color: var(--on-accent); }
.qrow-past { opacity: 0.45; }
.queue .empty { padding: 30px 16px; }

/* ------------------------------------- playlists (top of Library view) */
.pl-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin: 4px 2px 8px;
}
.pl-head .hsec-title { margin: 0; }
.pl-hint { font-size: 13px; color: var(--text-faint); padding: 2px 2px 14px; }
.pl-list { display: grid; gap: 2px; margin-bottom: 20px; }
.pl-art {
  width: 48px;
  height: 48px;
  border-radius: 8px;
  background: var(--elev);
  display: grid;
  place-items: center;
  color: var(--text-dim);
}
.pl-art svg.i { width: 20px; height: 20px; }
.pl-new { display: flex; gap: 8px; margin: 0 2px 10px; }
/* author display beats the UA [hidden] rule -- the .player lesson, again */
.pl-new[hidden] { display: none; }
#plTracks[hidden] { display: none; }
.pl-new input {
  flex: 1;
  min-width: 0;
  background: var(--elev);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 10px 12px;
  color: var(--text);
  font-size: 14px;
}
.pl-tracks-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin: 0 2px 6px;
}
.pl-tracks-head .hsec-title { margin: 0; }
.pl-del {
  width: 34px;
  height: 34px;
  flex: 0 0 auto;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: var(--text-faint);
  display: grid;
  place-items: center;
  cursor: pointer;
}
.pl-del svg.i { width: 16px; height: 16px; }
.pl-del:hover { color: #ff6f6f; background: var(--elev); }

@media (min-width: 940px) {
  .queue {
    left: auto;
    right: 24px;
    bottom: 24px;
    width: 460px;
    max-height: 70vh;
  }
}
@media (prefers-reduced-motion: reduce) {
  .queue, .scrim { transition: none; }
}

/* ==================================================================
   StreamForge patch14 (2026-09-14) -- charts become Bento, search gains
   public playlists.

   Home: kind:"chart" and kind:"regional" sections stop being carousels.
   Each renders as a surfaced PANEL -- the Bento card -- holding a dense
   two-column ranked tracklist: rank down the left, art beside it, 10
   rows above the fold, "Show all N" beneath, a play FAB in the head.
   That is the Spotify-desktop/Tidal chart pattern; the page stops
   reading as rows of posters.

   Search: pill tabs switch ONE query between Tracks and Public
   playlists (cover cards).  Opening a card renders that playlist's
   tracks inside the Search view.

   Performance contract (low-end Android, v5 rules still apply):
     - zero backdrop-filter; panel surfaces are flat colour + one
       gradient, painted once
     - only transform/opacity transition
     - rows carry content-visibility, so a 50-row panel costs nothing
       off-screen
     - every [hidden] element here owns its display:none, because an
       author display beats the UA rule (the v4 lesson, twice now)
   ================================================================== */

/* ------------------------------------------------- bento: the run of panels */
.bento-wrap {
  display: grid;
  gap: 22px;
  margin: 0 0 28px;
}

/* ----------------------------------------------------- bento: one panel */
.bento {
  min-width: 0;
  padding: 14px 14px 8px;
  border: 1px solid var(--line);
  border-radius: 18px;
  background:
    linear-gradient(160deg, var(--accent-soft, rgba(30, 215, 96, 0.07)), transparent 42%),
    var(--surface);
}
.bento-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  padding: 0 4px 12px;
}
.bento-head-box { display: grid; gap: 2px; min-width: 0; }
.bento-kicker {
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
}
.bento-title {
  font-size: 18px;
  font-weight: 800;
  letter-spacing: -0.015em;
  line-height: 1.2;
  color: var(--text);
  margin: 0;
}
.bento-sub { font-size: 12px; color: var(--text-dim); }
.bento-play {
  flex: none;
  width: 40px;
  height: 40px;
  border: none;
  border-radius: 50%;
  background: var(--accent);
  color: var(--on-accent);
  display: grid;
  place-items: center;
  cursor: pointer;
  box-shadow: 0 8px 20px var(--accent-glow);
  transition: transform 0.16s var(--pop, ease);
}
.bento-play svg.i { width: 18px; height: 18px; }
.bento-play:active { transform: scale(0.9); }

/* the dense ranked tracklist: two columns, phones and desktop alike */
.bento-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 2px 18px;
}
.bento-row {
  display: grid;
  grid-template-columns: 22px 38px 1fr auto;
  gap: 10px;
  align-items: center;
  padding: 6px 8px;
  border-radius: 10px;
  cursor: pointer;
  min-width: 0;
  content-visibility: auto;
  contain-intrinsic-size: auto 50px;
  transition: background 0.14s ease;
}
.bento-row:hover { background: var(--elev); }
.bento-rank {
  font-size: 13.5px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: var(--text-faint);
  text-align: center;
}
.bento-row--top .bento-rank { color: var(--accent); }
.bento-row img {
  width: 38px;
  height: 38px;
  border-radius: 8px;
  object-fit: cover;
  background: var(--elev);
  box-shadow: 0 3px 10px rgba(0, 0, 0, 0.3);
}
.bento-meta { min-width: 0; }
.bento-meta .t {
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.bento-meta .a {
  font-size: 11.5px;
  color: var(--text-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.bento-dur {
  font-size: 10.5px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--text-faint);
}
.bento-dur--flac { color: var(--accent); }
.bento-foot { padding: 8px 4px 6px; }
.bento-more {
  border: 1px solid var(--line);
  border-radius: 999px;
  background: transparent;
  color: var(--text-dim);
  font-size: 12.5px;
  font-weight: 700;
  padding: 7px 14px;
  cursor: pointer;
}
.bento-more:hover { color: var(--text); background: var(--elev); }

/* phones: tighter rank/art so two columns still leave real title room
   (360px devices: ~80px of title per row -- tight, but that is what a
   dense chart is; below 380px the panel collapses to one column) */
@media (max-width: 559px) {
  .bento { padding: 12px 10px 6px; }
  .bento-grid { gap: 2px 10px; }
  .bento-row { grid-template-columns: 18px 34px 1fr auto; gap: 8px; padding: 5px 6px; }
  .bento-rank { font-size: 12.5px; }
  .bento-row img { width: 34px; height: 34px; border-radius: 7px; }
  .bento-meta .t { font-size: 12.5px; }
  .bento-meta .a { font-size: 11px; }
}
@media (max-width: 379px) {
  .bento-grid { grid-template-columns: 1fr; }   /* tiny phones: one column */
}
@media (min-width: 940px) {
  .bento { padding: 18px 18px 10px; }
  .bento-title { font-size: 20px; }
  .bento-grid { gap: 2px 36px; }
  .bento-row { grid-template-columns: 26px 44px 1fr auto; gap: 12px; }
  .bento-row img { width: 44px; height: 44px; border-radius: 9px; }
  .bento-row--top .bento-rank { font-size: 15px; }
}

/* -------------------------------------------- search: tracks vs playlists */
.searchtabs {
  display: flex;
  gap: 8px;
  padding: 2px 0 12px;
}
.searchtabs[hidden] { display: none; }
.stab {
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--text-dim);
  font-size: 13px;
  font-weight: 700;
  padding: 8px 14px;
  border-radius: 999px;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}
.stab:hover { color: var(--text); }
.stab.active {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
}
.results[hidden] { display: none; }   /* .results {display:grid} beats UA [hidden] */

/* ------------------------------------------------- search: playlist cards */
.plcards {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
  padding: 2px 0 12px;
}
.plcards[hidden] { display: none; }
@media (min-width: 560px) { .plcards { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 940px) { .plcards { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 20px; } }
.plcard { cursor: pointer; min-width: 0; }
.plcard-art {
  position: relative;
  aspect-ratio: 1 / 1;
  border-radius: 12px;
  overflow: hidden;
  background: var(--elev);
  box-shadow: var(--card-shadow);
}
.plcard-art img { width: 100%; height: 100%; object-fit: cover; display: block; }
.plcard-play {
  position: absolute;
  right: 8px;
  bottom: 8px;
  width: 38px;
  height: 38px;
  border: none;
  border-radius: 50%;
  background: var(--accent);
  color: var(--on-accent);
  display: grid;
  place-items: center;
  cursor: pointer;
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.5);
}
.plcard-play svg.i { width: 16px; height: 16px; }
.plcard-play:active { transform: scale(0.92); }
@media (hover: hover) {
  .plcard-play {
    opacity: 0;
    transform: translateY(8px) scale(0.88);
    pointer-events: none;
    transition: opacity 0.16s ease, transform 0.16s var(--pop, ease);
  }
  .plcard:hover .plcard-play,
  .plcard-play:focus-visible { opacity: 1; transform: none; pointer-events: auto; }
}
.plcard-title {
  margin-top: 8px;
  font-size: 13px;
  font-weight: 700;
  line-height: 1.35;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.plcard-sub {
  font-size: 12px;
  color: var(--text-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* -------------------------------------------- search: an opened playlist */
#plDetail[hidden] { display: none; }
.pldetail-back {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  border: none;
  background: transparent;
  color: var(--text-dim);
  font-size: 13px;
  font-weight: 700;
  padding: 2px 8px 10px 2px;
  cursor: pointer;
}
.pldetail-back svg.i { width: 18px; height: 18px; }
.pldetail-back:hover { color: var(--text); }
.pldetail-hero {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 0 2px 16px;
}
.pldetail-art {
  flex: none;
  width: 92px;
  height: 92px;
  border-radius: 14px;
  object-fit: cover;
  background: var(--elev);
  box-shadow: var(--card-shadow);
}
.pldetail-box { flex: 1; min-width: 0; }
.pldetail-title {
  font-size: clamp(18px, 5vw, 24px);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.15;
  margin: 2px 0 4px;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.pldetail-sub { font-size: 12.5px; color: var(--text-dim); }
.pldetail-play {
  flex: none;
  width: 48px;
  height: 48px;
  border: none;
  border-radius: 50%;
  background: var(--accent);
  color: var(--on-accent);
  display: grid;
  place-items: center;
  cursor: pointer;
  box-shadow: 0 10px 24px rgba(30, 215, 96, 0.3);
  transition: transform 0.16s var(--pop, ease);
}
.pldetail-play svg.i { width: 20px; height: 20px; }
.pldetail-play:active { transform: scale(0.92); }
.pldetail-list { padding-bottom: 8px; }
@media (prefers-reduced-motion: reduce) {
  .bento-play, .pldetail-play, .plcard-play { transition: none; }
}

/* ==================================================================
   StreamForge patch15 (2026-09-14) -- Phase-4 frontend audit.

   [hidden] is now authoritative; the shell is capped on big desks; the
   queue sheet can no longer be pushed off a short screen.  Every rule here
   lands last, so it wins the cascade over v4/v5/v7/v8/patch13/patch14 at
   equal specificity -- that is the same mechanism this file has used since
   v5, and it is why the fixes are appended rather than edited in.

   Performance contract (low-end Android, unchanged):
     - zero backdrop-filter added
     - only transform/opacity transition
     - content-visibility stays on .shelf and .bento-row; it is OFF on the
       scroll-snap children, where it was causing the jumps (DOM-4)
   ================================================================== */

/* ------------------------------------------------- CSS-1 / CSS-2: [hidden]
   The UA stylesheet's [hidden] { display:none } loses to ANY author display
   declaration, whatever the specificity.  That is how .tab { display:flex }
   kept the Admin tab visible to non-admins (CSS-1) and .adminform
   { display:grid } left the add-user form permanently open (CSS-2) -- and
   how this file accumulated seven one-off copies of the same fix (.player,
   .queue, .scrim, .results, .plcards, .pl-new, #plDetail, .searchtabs).
   One !important rule retires the class of bug instead of waiting for the
   next `display:` to defeat it.  Nothing in this app hides a box it also
   transitions: the queue sheet un-hides first and animates with .open. */
[hidden] { display: none !important; }

/* ------------------------------------------------ DOM-2: library pager */
.lib-more { display: flex; justify-content: center; padding: 10px 0 4px; }

/* ---------------------------------------------------- CSS-3: ultra-wide
   There was no upper bound anywhere, so on a 2560px+ desk the shell went
   full bleed: hero wash edge to edge, shelves stretching to 40-character
   titles, the player rail as wide as the monitor.  Cap the frame and centre
   it.  Capping body.appframe rather than main keeps the nav rail, the app
   bar and the docked player inside the same edges, and .tabs/.player are
   position:static on desktop so they follow the frame. */
@media (min-width: 1600px) {
  body.appframe {
    max-width: 1680px;
    margin: 0 auto;
    border-left: 1px solid var(--line);
    border-right: 1px solid var(--line);
  }
  /* The queue sheet is position:fixed, so on a centred frame its viewport
     right edge is no longer the frame's.  Pull it in by half the slack:
     (100vw - 1680px) / 2 + 24px == 50% - 816px. */
  .queue { right: calc(50% - 816px); }
}

/* ------------------------------------------- CSS-4 / CSS-5: queue clipping
   .queue's bottom offset is nav(62) + safe-bottom + player(104) + 18, but
   its max-height was min(62vh, 560px) with no reference to that offset.  On
   a 360px-tall landscape phone that is a 223px sheet sitting 184px up:
   47px of it -- including its own close button -- off the top of the
   screen, and the sheet's body zero-height.  Cap it by the space that
   actually exists above the player instead. */
.queue {
  max-height: min(62vh, 560px);
  max-height: min(calc(100dvh - var(--nav-h) - var(--safe-bottom) - var(--player-h) - 34px),
                  min(62vh, 560px));
}
@media (min-width: 940px) {
  /* CSS-5: the docked sheet, same arithmetic for a short desktop window. */
  .queue {
    max-height: min(calc(100dvh - 24px - var(--safe-bottom) - var(--player-h) - 34px), 70vh);
  }
}

/* ==================================================================
   StreamForge v25 (2026-10) -- True Light & Dark Themes, Home Filter
   Chips, Desktop Quick-Playlist Rail, 2x2 Mosaic Playlist Cards,
   3-Tier Playlist Hub (Mine / Community / Auto-Mixes) & Universal
   + Add-to-Playlist Modal.
   ================================================================== */

/* ------------------------------------------- 1. Light & Dark Theme System */
:root,
html[data-theme="dark"] {
  color-scheme: dark;
  --player-bg: #151a21;
  --modal-bg: #151a21;
  --scrollbar-thumb: #262d37;
}

html[data-theme="light"] {
  color-scheme: light;
  --bg: #f3f6fa;
  --surface: #ffffff;
  --elev: #ebf0f6;
  --elev-2: #dfe7f1;
  --glass: rgba(255, 255, 255, 0.88);
  --chrome: #ffffff;
  --player-bg: #ffffff;
  --modal-bg: #ffffff;
  --line: rgba(15, 23, 42, 0.09);
  --accent: #10b981;
  --accent-dim: #059669;
  --accent-glow: rgba(16, 185, 129, 0.14);
  --text: #0f172a;
  --text-dim: #475569;
  --text-faint: #64748b;
  --on-accent: #ffffff;
  --danger: #e11d48;
  --warn: #d97706;
  --card-shadow: 0 6px 20px rgba(15, 23, 42, 0.07);
  --shadow-dock: 0 12px 32px rgba(15, 23, 42, 0.14);
  --scrollbar-thumb: #cbd5e1;
  --hero-0: #e0f2fe;
  --hero-1: #d1fae5;
  --hero-2: #ede9fe;
}

html[data-theme="light"] body[data-tod="morning"] {
  --hero-0: #fef3c7;
  --hero-1: #fde68a;
  --hero-2: #d1fae5;
}
html[data-theme="light"] body[data-tod="afternoon"] {
  --hero-0: #e0e7ff;
  --hero-1: #ddd6fe;
  --hero-2: #cffafe;
}
html[data-theme="light"] body[data-tod="evening"] {
  --hero-0: #e0e7ff;
  --hero-1: #fae8ff;
  --hero-2: #d1fae5;
}

html[data-theme="light"] .loginbody {
  background: radial-gradient(1000px 500px at 50% -10%, rgba(16, 185, 129, 0.16), var(--bg));
}
html[data-theme="light"] #homeGreeting,
html[data-theme="light"] .home-greeting {
  color: var(--text);
  -webkit-text-fill-color: var(--text);
  background: none;
}
html[data-theme="light"] .quick-meta .t {
  color: var(--text);
}
html[data-theme="light"] .quick-tile {
  background: rgba(255, 255, 255, 0.85);
  border: 1px solid var(--line);
  box-shadow: 0 2px 8px rgba(15, 23, 42, 0.04);
}
html[data-theme="light"] .quick-tile:hover {
  background: #ffffff;
}
html[data-theme="light"] .player,
html[data-theme="light"] .queue,
html[data-theme="light"] .pl-modal {
  background: var(--player-bg);
}
html[data-theme="light"] .bento {
  background:
    linear-gradient(160deg, rgba(16, 185, 129, 0.08), rgba(16, 185, 129, 0) 45%),
    var(--surface);
  box-shadow: var(--card-shadow);
}
html[data-theme="light"] .card-fmt {
  background: rgba(15, 23, 42, 0.78);
  color: #34d399;
}

.player { background: var(--player-bg, var(--surface)); }
.queue { background: var(--modal-bg, var(--surface)); }
main { scrollbar-color: var(--scrollbar-thumb, #2a313b) transparent; }
main::-webkit-scrollbar-thumb { background: var(--scrollbar-thumb, #262d37); }

/* ------------------------------------------- 2. Home Filter Chips Bar */
.home-top-bar {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-bottom: 14px;
}
.home-filters {
  display: flex;
  align-items: center;
  gap: 8px;
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  padding: 2px 0 4px;
}
.home-filters::-webkit-scrollbar { display: none; }
.fchip {
  flex: 0 0 auto;
  height: 34px;
  padding: 0 15px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--text-dim);
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
  transition: transform 0.12s ease;
}
.fchip:hover {
  color: var(--text);
  background: var(--elev);
}
.fchip:active { transform: scale(0.96); }
.fchip.active {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
  box-shadow: 0 4px 14px var(--accent-glow);
}

/* ------------------------------------------- 3. Desktop Sidebar Playlists Rail */
.nav-rail-section {
  display: none;
}
@media (min-width: 940px) {
  .nav-rail-section {
    display: flex;
    flex-direction: column;
    margin-top: 18px;
    padding-top: 14px;
    border-top: 1px solid var(--line);
    min-height: 0;
    flex: 1;
  }
  .nav-rail-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 10px 8px;
    font-size: 11px;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-faint);
  }
  .nav-rail-new {
    width: 26px;
    height: 26px;
    border-radius: 6px;
    border: none;
    background: transparent;
    color: var(--text-dim);
    display: grid;
    place-items: center;
    cursor: pointer;
  }
  .nav-rail-new:hover {
    background: var(--elev);
    color: var(--accent);
  }
  .nav-rail-new svg.i { width: 15px; height: 15px; }
  .nav-rail-list {
    display: flex;
    flex-direction: column;
    gap: 2px;
    overflow-y: auto;
    scrollbar-width: thin;
    padding-right: 2px;
  }
  .nav-pl-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 7px 10px;
    border-radius: 8px;
    border: none;
    background: transparent;
    color: var(--text-dim);
    font-size: 13px;
    font-weight: 600;
    text-align: left;
    cursor: pointer;
    min-width: 0;
    transition: background 0.14s ease, color 0.14s ease;
  }
  .nav-pl-item:hover {
    background: var(--elev);
    color: var(--text);
  }
  .nav-pl-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex: 0 0 8px;
    background: var(--accent);
  }
  .nav-pl-dot.smart { background: #a855f7; }
  .nav-pl-dot.comm { background: #3b82f6; }
  .nav-pl-name {
    flex: 1;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .nav-pl-cnt {
    font-size: 11px;
    color: var(--text-faint);
    font-variant-numeric: tabular-nums;
  }
}

/* ------------------------------------------- 4. 3-Tier Playlist Hub & Mosaic Cards */
.pl-head-titles {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.pl-head-sub {
  font-size: 12.5px;
  color: var(--text-dim);
}
.pl-head .submit {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 9px 14px;
  border-radius: 999px;
  font-size: 13px;
  width: auto;
}
.pl-head .submit svg.i { width: 16px; height: 16px; }

.pl-subtabs {
  margin-top: 8px;
  margin-bottom: 14px;
  flex-wrap: wrap;
}
.pl-subtabs .stab {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.pl-subtabs .stab svg.i { width: 15px; height: 15px; }

.pl-new {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 14px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 14px;
  margin-bottom: 16px;
}
.pl-new-inputs {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 10px;
}
.pl-new-opts {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px;
}
.pl-opt {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: var(--text-dim);
  cursor: pointer;
}
.pl-opt input {
  accent-color: var(--accent);
  width: 16px;
  height: 16px;
}
.pl-subhead {
  font-size: 14px;
  font-weight: 800;
  color: var(--text-dim);
  margin: 14px 2px 10px;
  letter-spacing: -0.01em;
}

.pl-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 12px;
  margin-bottom: 18px;
}
.pl-card-tile {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 14px;
  cursor: pointer;
  min-width: 0;
  content-visibility: auto;
  contain-intrinsic-size: auto 80px;
  transition: transform 0.14s var(--pop, ease);
}
.list .row {
  content-visibility: auto;
  contain-intrinsic-size: auto 60px;
}
.pl-card-tile:hover {
  background: var(--elev);
  border-color: var(--accent-glow);
  transform: translateY(-1px);
}
.pl-mosaic {
  width: 58px;
  height: 58px;
  flex: 0 0 58px;
  border-radius: 10px;
  overflow: hidden;
  background: var(--elev-2);
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
  gap: 1px;
  place-items: center;
  color: var(--text-dim);
}
.pl-mosaic.single {
  grid-template-columns: 1fr;
  grid-template-rows: 1fr;
}
.pl-mosaic img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.pl-mosaic svg.i { width: 24px; height: 24px; }
.pl-tile-meta {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.pl-tile-title {
  font-size: 14px;
  font-weight: 700;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.pl-tile-sub {
  font-size: 12px;
  color: var(--text-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.pl-tile-badges {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  margin-top: 2px;
}
.pl-pill {
  font-size: 10px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  padding: 2px 7px;
  border-radius: 999px;
  background: var(--accent-glow);
  color: var(--accent);
}
.pl-pill.comm {
  background: rgba(59, 130, 246, 0.16);
  color: #60a5fa;
}
.pl-pill.smart {
  background: rgba(168, 85, 247, 0.16);
  color: #c084fc;
}

/* Opened Playlist Drawer */
#plTracks {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: 16px;
  margin-bottom: 22px;
}
.pl-drawer-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin: 8px 0 12px;
}
.pl-act-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 34px;
  padding: 0 13px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--elev);
  color: var(--text);
  font-size: 12.5px;
  font-weight: 700;
  cursor: pointer;
}
.pl-act-btn:hover { border-color: var(--accent); }
.pl-act-btn.primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
}
.pl-act-btn.danger:hover {
  border-color: var(--danger);
  color: var(--danger);
}
.pl-act-btn svg.i { width: 15px; height: 15px; }

/* Library section divider & search filter */
.lib-divider {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin: 24px 2px 10px;
  padding-top: 16px;
  border-top: 1px solid var(--line);
}
.lib-divider .hsec-title { margin: 0; }
.lib-filter-wrap {
  flex: 1;
  max-width: 320px;
  min-width: 200px;
}
.lib-filter-wrap input {
  width: 100%;
  height: 36px;
  padding: 0 14px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--text);
  font-size: 13px;
}

/* Row quick-add (+) button */
.row-actions {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.row-add-btn {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 1px solid transparent;
  background: transparent;
  color: var(--text-dim);
  display: grid;
  place-items: center;
  cursor: pointer;
  flex: 0 0 32px;
}
.row-add-btn:hover {
  background: var(--elev-2);
  color: var(--accent);
  border-color: var(--line);
}
.row-add-btn svg.i { width: 16px; height: 16px; }

/* Universal Add-to-Playlist Modal */
.pl-modal {
  position: fixed;
  left: 12px;
  right: 12px;
  bottom: calc(var(--nav-h) + var(--safe-bottom) + 24px);
  max-width: 460px;
  margin: 0 auto;
  max-height: min(68vh, 520px);
  display: flex;
  flex-direction: column;
  background: var(--modal-bg, var(--surface));
  border: 1px solid var(--line);
  border-radius: 16px;
  box-shadow: var(--shadow-dock);
  z-index: 60;
  overflow: hidden;
}
@media (min-width: 940px) {
  .pl-modal {
    bottom: auto;
    top: 50%;
    transform: translateY(-50%);
  }
}
.pl-modal-new {
  display: flex;
  gap: 8px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--line);
}
.pl-modal-new input {
  flex: 1;
  min-width: 0;
  height: 36px;
  padding: 0 12px;
  border-radius: 8px;
  border: 1px solid var(--line);
  background: var(--elev);
  color: var(--text);
  font-size: 13px;
}
.pl-modal-new .submit {
  width: auto;
  padding: 0 14px;
  height: 36px;
  font-size: 12.5px;
  border-radius: 8px;
}

/* ------------------------------------------- v31 Settings, DSP, Lyrics & Player Upgrades */
:root[data-theme="amoled"] {
  --bg: #000000;
  --bg-top: #000000;
  --surface: #07080a;
  --surface-hi: #0e1015;
  --elev: #13161d;
  --modal-bg: #080a0d;
  --glass: rgba(5, 6, 8, 0.92);
  --player-glass: rgba(4, 5, 7, 0.96);
}

body.compact-rows .results .row {
  padding: 5px 10px;
  min-height: 44px;
}
body.compact-rows .results .row img {
  width: 34px;
  height: 34px;
  border-radius: 6px;
}

.sleep-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: 999px;
  background: var(--accent-soft);
  color: var(--accent);
  font-size: 11.5px;
  font-weight: 700;
  cursor: pointer;
  margin-right: 4px;
}
.sleep-pill[hidden] { display: none; }

.info-top-row {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}
.player-vis {
  flex: none;
  width: 56px;
  height: 16px;
  opacity: 0.9;
}
body.hide-vis .player-vis { display: none; }

.ctl.aux-ctl {
  position: relative;
  width: 32px;
  height: 32px;
  color: var(--text-dim);
}
.ctl.aux-ctl.active,
.ctl.aux-ctl.on,
.ctl.aux.active,
.ctl.aux.on {
  color: var(--accent);
}
.rep-badge {
  position: absolute;
  top: 2px;
  right: 2px;
  font-size: 9px;
  font-weight: 800;
  background: var(--accent);
  color: var(--on-accent);
  border-radius: 99px;
  padding: 0 3.5px;
  line-height: 12px;
}
.rep-badge[hidden] { display: none; }

.vol-wrap {
  display: none;
  align-items: center;
  gap: 4px;
  margin-left: 2px;
}
@media (min-width: 780px) {
  .vol-wrap { display: inline-flex; }
}
.vol-slider {
  width: 76px;
  height: 4px;
  accent-color: var(--accent);
  cursor: pointer;
}

/* Library Toolbar */
.lib-title-group {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}
.lib-quick-btns {
  display: flex;
  align-items: center;
  gap: 8px;
}
.lib-Quick-btns .ubtn,
.lib-quick-btns .ubtn,
.queue-actions .ubtn {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 32px;
  padding: 0 11px;
  font-size: 12px;
  border-radius: 999px;
}
.lib-quick-btns .ubtn svg.i,
.queue-actions .ubtn svg.i {
  width: 14px;
  height: 14px;
}
.lib-toolbar {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  width: 100%;
}
.lib-fmt-chips {
  display: flex;
  gap: 6px;
}
.lib-sort-select {
  height: 34px;
  min-width: 150px;
}

/* Settings & DSP Page */
.cfg-container {
  max-width: 1180px;
  margin: 0 auto;
  padding-bottom: 48px;
}
.cfg-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 16px;
  margin-top: 14px;
}
@media (min-width: 920px) {
  .cfg-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .cfg-card--wide {
    grid-column: 1 / -1;
  }
}
.cfg-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: 18px;
  box-shadow: var(--card-shadow);
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.cfg-card-head {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--line);
}
.cfg-card-head > svg.i {
  width: 22px;
  height: 22px;
  color: var(--accent);
  flex: none;
  margin-top: 2px;
}
.cfg-card-head h3 {
  margin: 0;
  font-size: 15px;
  font-weight: 700;
}
.cfg-card-head p {
  margin: 2px 0 0;
  font-size: 12px;
  color: var(--text-dim);
}
.cfg-head-actions {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
.cfg-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
}
.cfg-label {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 180px;
  flex: 1;
}
.cfg-label b {
  font-size: 13.5px;
  font-weight: 600;
}
.cfg-label span {
  font-size: 11.8px;
  color: var(--text-dim);
}
.cfg-select {
  height: 36px;
  padding: 0 12px;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: var(--elev);
  color: var(--text);
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
}
.cfg-range {
  width: 160px;
  accent-color: var(--accent);
  cursor: pointer;
}

/* Toggle Switch */
.cfg-switch {
  position: relative;
  display: inline-block;
  width: 44px;
  height: 24px;
  flex: none;
}
.cfg-switch input {
  opacity: 0;
  width: 0;
  height: 0;
}
.cfg-slider {
  position: absolute;
  cursor: pointer;
  inset: 0;
  background: var(--elev);
  border: 1px solid var(--line);
  border-radius: 999px;
  transition: background 0.18s ease, border-color 0.18s ease;
}
.cfg-slider::before {
  content: "";
  position: absolute;
  width: 18px;
  height: 18px;
  left: 2px;
  top: 2px;
  border-radius: 50%;
  background: var(--text-dim);
  transition: transform 0.18s ease, background 0.18s ease;
}
.cfg-switch input:checked + .cfg-slider {
  background: var(--accent-soft);
  border-color: var(--accent);
}
.cfg-switch input:checked + .cfg-slider::before {
  transform: translateX(20px);
  background: var(--accent);
}

/* 6-Band Parametric Equalizer */
.eq-bands {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 10px;
  padding: 14px 10px;
  background: var(--elev);
  border: 1px solid var(--line);
  border-radius: 14px;
  align-items: center;
  justify-items: center;
}
.eq-bands.disabled {
  opacity: 0.48;
}
.eq-band {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  width: 100%;
}
.eq-val {
  font-size: 11px;
  font-weight: 700;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}
.eq-freq {
  font-size: 11px;
  font-weight: 600;
  color: var(--text-dim);
}
.eq-band input[type="range"] {
  writing-mode: vertical-lr;
  direction: rtl;
  width: 22px;
  height: 110px;
  accent-color: var(--accent);
  cursor: pointer;
}

/* Accent Swatches & Sleep Timer */
.accent-swatches {
  display: flex;
  align-items: center;
  gap: 8px;
}
.swatch {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--sw);
  border: 2px solid transparent;
  cursor: pointer;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.swatch:hover { transform: scale(1.12); }
.swatch.active {
  border-color: var(--text);
  box-shadow: 0 0 0 2px var(--surface), 0 0 12px var(--sw);
}
.sleep-btn-group {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.kbd-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 14px;
  font-size: 12px;
  color: var(--text-dim);
}
.kbd-grid kbd {
  display: inline-block;
  padding: 2px 6px;
  border-radius: 5px;
  background: var(--elev);
  border: 1px solid var(--line);
  color: var(--text);
  font-size: 11px;
  font-family: inherit;
  font-weight: 700;
}

/* Queue & Lyrics Drawers */
.queue-actions {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-left: auto;
  margin-right: 6px;
  flex-wrap: wrap;
}
.lyrics-track-meta {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}
.lyrics-track-meta img {
  width: 42px;
  height: 42px;
  border-radius: 8px;
  object-fit: cover;
}
.lyrics-body {
  flex: 1;
  overflow-y: auto;
  padding: 20px 22px 36px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  scroll-behavior: smooth;
}
.lrc-line,
.lyric-line {
  font-size: 17px;
  font-weight: 700;
  line-height: 1.45;
  color: var(--text-dim);
  opacity: 0.52;
  cursor: pointer;
  transition: color 0.2s ease, opacity 0.2s ease, transform 0.2s ease;
  transform-origin: left center;
}
.lrc-line:hover,
.lyric-line:hover {
  opacity: 0.85;
  color: var(--text);
}
.lrc-line.past,
.lyric-line.past {
  opacity: 0.36;
}
.lrc-line.active,
.lyric-line.active {
  color: var(--accent);
  opacity: 1;
  transform: scale(1.04);
}
.lrc-plain {
  white-space: pre-wrap;
  font-size: 14.5px;
  line-height: 1.65;
  color: var(--text);
}


