/* Musika - Spotify-style dark theme */
* { margin: 0; padding: 0; box-sizing: border-box; }
:root {
  /* OBSIDIAN & AURORA — premium: depth + restraint. Ink-navy surfaces, matured violet,
     aurora teal, champagne gold for premium moments. Magenta demoted to flourishes. */
  --bg: #0b0c14;
  --bg-elev: #141626;
  --bg-hi: #1e2036;
  --green: #8b5cf6;      /* primary accent (var name kept to avoid churn) */
  --green-hi: #b79cff;
  --neon: #2dd4bf;       /* aurora teal */
  --neon2: #e550b8;      /* magenta, quieter */
  --gold: #e8b45a;       /* champagne — premium moments only */
  --accent: #8b5cf6;
  --text: #f4f2ff;
  --text-dim: #9a97ad;
  --bar: #3d3f55;
  --beat: 0.12; /* live music pulse 0..1, set per-frame by renderer.js -> drives app-wide glow */
  --pad-x: 24px; /* ONE horizontal gutter: content padding + shelf full-bleed derive from it */
  /* adaptive heights: scale with the device + respect notches/home bars */
  --nav-h: calc(56px + env(safe-area-inset-bottom));
  --player-h: clamp(92px, 15vh, 112px); /* pill = art row + full-width scrub row */
}
html, body { height: 100%; }
body {
  font-family: "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  background: var(--bg);
  color: var(--text);
  overflow: hidden;
  -webkit-user-select: none;
  user-select: none;
}
/* immersive living background: slow shifting neon haze */
body::before {
  content: ""; position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background:
    radial-gradient(120vmax 80vmax at 15% -10%, rgba(139,92,246,.10), transparent 55%),
    radial-gradient(100vmax 70vmax at 110% 10%, rgba(45,212,191,.06), transparent 50%),
    radial-gradient(120vmax 90vmax at 50% 120%, rgba(90,60,180,.09), transparent 55%);
  background-size: 200% 200%;
  animation: bgDrift 30s ease-in-out infinite;
}
@keyframes bgDrift {
  0%,100% { background-position: 0% 0%, 100% 0%, 50% 100%; }
  50%     { background-position: 20% 30%, 80% 20%, 40% 80%; }
}
.app { position: relative; z-index: 1; }
button { font-family: inherit; cursor: pointer; border: none; background: none; color: inherit; }

.app {
  display: grid;
  grid-template-columns: 1fr;
  grid-template-rows: 1fr auto;
  grid-template-areas: "content" "player";
  height: 100vh;
  height: 100dvh; /* adaptive: handles mobile browser chrome / any screen height */
}

/* ---------- Sidebar ---------- */
.sidebar {
  grid-area: sidebar;
  background: #000;
  padding: 20px 12px;
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.brand { display: flex; align-items: center; gap: 10px; padding: 0 8px; }
.brand-dot {
  width: 30px; height: 30px; border-radius: 50%;
  background: var(--green);
  box-shadow: 0 0 14px rgba(168,85,247,0.55);
}
.brand-name { font-size: 22px; font-weight: 800; letter-spacing: -0.5px; }

.nav-links { list-style: none; display: flex; flex-direction: column; gap: 4px; }
.nav-links li {
  display: flex; align-items: center; gap: 14px;
  padding: 9px 10px; border-radius: 6px;
  color: var(--text-dim); font-weight: 700; font-size: 14px;
  transition: color .15s;
}
.nav-links li:hover { color: var(--text); }
.nav-links li.active { color: var(--text); }
.nav-links .ico { font-size: 18px; width: 20px; text-align: center; }

.lib-actions { display: flex; flex-direction: column; gap: 8px; padding: 0 6px; }
.lib-btn {
  background: var(--bg-hi); color: var(--text);
  padding: 10px 12px; border-radius: 8px; font-weight: 700; font-size: 13px;
  text-align: left; transition: background .15s, transform .05s;
}
.lib-btn:hover { background: #3a3a3a; }
.lib-btn:active { transform: scale(.98); }

.playlists { flex: 1; overflow-y: auto; padding: 6px; display: flex; flex-direction: column; gap: 2px; }
.pl { display: flex; align-items: center; gap: 10px; padding: 8px; border-radius: 6px; color: var(--text-dim); font-size: 13px; font-weight: 600; }
.pl:hover { color: var(--text); background: var(--bg-elev); }
.pl.liked .pl-ico {
  width: 26px; height: 26px; border-radius: 4px;
  display: grid; place-items: center;
  background: linear-gradient(135deg, #4500c0, #b3a7ff); color: #fff;
}
.pl.active { color: var(--green); }
.sidebar-foot { color: #6a6a6a; font-size: 11px; padding: 0 8px; }

/* ---------- Content ---------- */
.content {
  grid-area: content;
  background: linear-gradient(180deg, rgba(255,255,255,.06) 0%, transparent 240px);
  overflow-y: auto;
  padding: 0 var(--pad-x) 24px;
}
.topbar {
  position: sticky; top: 0; z-index: 5;
  display: flex; align-items: center; gap: 16px;
  padding: 14px 0; margin: 0 -24px; padding-left: 24px; padding-right: 24px;
  background: rgba(18,18,18,0);
  backdrop-filter: blur(6px);
}
.nav-arrows { display: flex; gap: 8px; }
.round {
  width: 32px; height: 32px; border-radius: 50%;
  background: rgba(0,0,0,0.6); color: var(--text);
  font-size: 18px; display: grid; place-items: center;
}
.search-wrap { flex: 1; max-width: 360px; }
#search {
  width: 100%; padding: 10px 14px; border-radius: 20px;
  background: var(--bg-hi); color: var(--text); font-size: 13px; outline: none; border: 1px solid transparent;
}
#search:focus { border-color: #555; }
.user-pill {
  margin-left: auto; display: flex; align-items: center; gap: 8px;
  background: #000; padding: 4px 10px 4px 4px; border-radius: 20px; font-weight: 700; font-size: 13px;
}
.user-dot {
  width: 26px; height: 26px; border-radius: 50%; background: var(--green);
  color: #000; display: grid; place-items: center; font-weight: 800;
}

.hero { padding: 14px 0 18px; }
.hero h1 { font-size: 30px; font-weight: 800; letter-spacing: -1px; }
.hero .sub { color: var(--text-dim); margin-top: 6px; font-size: 14px; }

/* ---------- Track list ---------- */
.tl-head {
  display: grid; grid-template-columns: 40px 1fr 1fr 60px;
  gap: 12px; padding: 6px 14px; border-bottom: 1px solid #2a2a2a;
  color: var(--text-dim); font-size: 12px; text-transform: uppercase; letter-spacing: 1px;
}
.tl-rows { margin-top: 6px; }
.row {
  display: grid; grid-template-columns: 40px 1fr 1fr 60px;
  gap: 12px; align-items: center; padding: 8px 14px; border-radius: 6px;
  font-size: 14px; color: var(--text-dim); cursor: default;
}
.row:hover { background: var(--bg-hi); }
.row:hover .c-idx .num { display: none; }
.row:hover .c-idx .pico { display: inline; }
.row.playing { color: var(--green); }
.c-idx .pico { display: none; color: var(--text); }
.c-title { display: flex; flex-direction: column; min-width: 0; } /* min-width:0 = grid items may SHRINK: long titles ellipsize instead of shoving the + off-screen */
.c-title .tt { color: var(--text); font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.row.playing .c-title .tt { color: var(--green); }
.c-title .ta { font-size: 12px; cursor: pointer; }
.c-title .ta:active { color: var(--green-hi); }
#npArtist, .np-big-artist, .top-s { cursor: pointer; }
#npArtist:active, .np-big-artist:active { color: var(--green-hi); }
.c-album, .c-dur { font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.empty-state { text-align: center; padding: 70px 20px; color: var(--text-dim); }
.empty-art { font-size: 56px; margin-bottom: 12px; opacity: .5; }
.empty-state h2 { color: var(--text); margin-bottom: 8px; }
.empty-state p { font-size: 14px; }
.empty-state b { color: var(--text); }

/* ---------- Player bar ---------- */
.player {
  grid-area: player;
  /* the pill's BODY lives on ::before so its edge can go liquid (clip-path) and
     bulge past the box (inset -8px). --pillclip is set per-frame from the real FFT. */
  background: none;
  display: grid; grid-template-columns: 1fr 2fr 1fr; align-items: center;
  padding: 0 16px; gap: 16px;
}
.player::before {
  content: ""; position: absolute; inset: -10px; z-index: -1;
  background: linear-gradient(180deg, rgba(34,36,58,.96), rgba(17,18,30,.98));
  box-shadow: inset 0 1px 0 rgba(255,255,255,.10); /* glass hairline, survives the clip */
  clip-path: var(--pillclip, inset(10px round 18px));
  will-change: clip-path;
}
.np { display: flex; align-items: center; gap: 12px; min-width: 0; }
.np-art {
  width: 56px; height: 56px; border-radius: 6px; flex-shrink: 0;
  background: var(--bg-hi); display: grid; place-items: center; font-size: 22px; color: var(--text-dim);
}
.np-meta { min-width: 0; }
.np-title { font-size: 14px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.np-artist { font-size: 12px; color: var(--text-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.like { color: var(--text-dim); font-size: 18px; }
.like.on { color: var(--green); }

.controls { display: flex; flex-direction: column; align-items: center; gap: 8px; }
.ctrl-btns { display: flex; align-items: center; gap: 20px; }
.ctrl { color: var(--text-dim); font-size: 16px; transition: color .12s, transform .05s; }
.ctrl:hover { color: var(--text); }
.ctrl.ghost.on { color: var(--green); }
.ctrl.play {
  width: 36px; height: 36px; border-radius: 50%; background: #fff; color: #000;
  display: grid; place-items: center; font-size: 15px;
}
.ctrl.play:hover { transform: scale(1.06); }

.scrub { display: flex; align-items: center; gap: 10px; width: 100%; max-width: 520px; }
.t { font-size: 11px; color: var(--text-dim); width: 36px; text-align: center; }

.bar {
  -webkit-appearance: none; appearance: none; height: 4px; border-radius: 2px;
  background: var(--bar); flex: 1; outline: none; cursor: pointer;
}
.bar::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none; width: 12px; height: 12px;
  border-radius: 50%; background: #fff; opacity: 0; transition: opacity .12s;
}
.bar:hover::-webkit-slider-thumb { opacity: 1; }
.bar:hover { background: linear-gradient(to right, var(--green) var(--p, 0%), var(--bar) var(--p, 0%)); }

.extras { display: flex; align-items: center; gap: 8px; justify-content: flex-end; }
.vol { max-width: 110px; }
.vol-ico { color: var(--text-dim); font-size: 14px; }

/* ---------- Browse view (Audius) ---------- */
.hidden { display: none !important; }
.source-toggle { display: flex; gap: 8px; margin-top: 14px; }
.src-btn {
  padding: 8px 16px; border-radius: 20px; background: var(--bg-hi); color: var(--text-dim);
  font-weight: 700; font-size: 13px; transition: background .15s, color .15s;
}
.src-btn:hover { color: var(--text); }
.src-btn.active { background: var(--green); color: #000; }
.browse-search { margin-top: 14px; }
#audiusSearch, #hubStationSearch {
  width: 100%; max-width: 420px; padding: 11px 16px; border-radius: 22px;
  background: var(--bg-hi); color: var(--text); font-size: 14px; outline: none; border: 1px solid transparent;
}
#audiusSearch:focus, #hubStationSearch:focus { border-color: #555; }
#hubStationSearch { margin-bottom: 10px; }

.genre-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
  gap: 16px; padding: 8px 0 20px;
}
.genre-tile {
  position: relative; height: 90px; border-radius: 8px; padding: 14px;
  font-size: 17px; font-weight: 800; color: #fff; cursor: pointer; overflow: hidden;
  box-shadow: 0 4px 10px rgba(0,0,0,0.3); transition: transform .12s;
}
.genre-tile:hover { transform: scale(1.03); }
.genre-tile::after {
  content: "♪"; position: absolute; right: -6px; bottom: -14px;
  font-size: 52px; opacity: 0.25; transform: rotate(25deg);
}

.genre-chips { display: flex; flex-wrap: wrap; gap: 8px; padding: 0 0 14px; }
.chip {
  padding: 7px 14px; border-radius: 18px; background: var(--bg-hi); color: var(--text-dim);
  font-size: 13px; font-weight: 600; white-space: nowrap; transition: background .12s, color .12s;
}
.chip:hover { color: var(--text); background: #3a3a3a; }
.chip.active { background: #fff; color: #000; }
.results-head { display: flex; align-items: center; gap: 14px; padding: 6px 0 12px; }
.results-head h2 { font-size: 22px; font-weight: 800; }
.row.online .c-title .ta { color: var(--text-dim); }
.loading { padding: 30px 14px; color: var(--text-dim); font-size: 14px; }
.load-more {
  display: block; margin: 16px auto 28px; padding: 11px 28px; border-radius: 22px;
  background: transparent; border: 1px solid #5a5a5a; color: var(--text);
  font-weight: 700; font-size: 13px; transition: background .15s, transform .05s;
}
.load-more:hover { background: var(--bg-hi); border-color: #888; }
.load-more:active { transform: scale(.97); }
.load-more:disabled { opacity: .6; }

/* now-playing artwork */
.np-art.has-art { background-size: cover; background-position: center; font-size: 0; }

/* ============================================================
   GAMIFIED + IMMERSIVE + TACTILE  (Musika)
   ============================================================ */
* { -webkit-tap-highlight-color: transparent; }

/* --- SOLID tactile press: everything clickable springs on press --- */
.nav-links li, .lib-btn, .src-btn, .chip, .genre-tile, .ctrl, .round,
.load-more, .pl, .like, .user-pill, .row {
  transition: transform .09s cubic-bezier(.2,.8,.3,1.4), background .15s ease, box-shadow .18s ease, color .12s ease;
  will-change: transform;
}
.nav-links li:active, .lib-btn:active, .src-btn:active, .chip:active,
.genre-tile:active, .round:active, .load-more:active, .pl:active,
.like:active, .user-pill:active, .row:active {
  transform: scale(.93);
  filter: brightness(1.12);
}
.ctrl:active { transform: scale(.86); }
.ctrl.play:active { transform: scale(.84); box-shadow: 0 0 0 6px rgba(168,85,247,.25); }

/* --- ripple: a "confirmed" pulse from the tap point --- */
.genre-tile, .lib-btn, .src-btn, .chip, .load-more, .ctrl.play, .nav-links li {
  position: relative; overflow: hidden;
}
.ripple {
  position: absolute; border-radius: 50%; pointer-events: none;
  background: rgba(255,255,255,.35); transform: scale(0);
  animation: ripple .6s cubic-bezier(.2,.7,.3,1) forwards;
}
@keyframes ripple { to { transform: scale(2.4); opacity: 0; } }

/* --- genre tiles: lift + glow + staggered entrance --- */
.genre-tile { animation: popIn .35s cubic-bezier(.2,.9,.3,1.3) both; }
.genre-tile:hover { transform: translateY(-5px) scale(1.04); box-shadow: 0 10px 26px rgba(0,0,0,.5), 0 0 22px rgba(255,255,255,.08); }
@keyframes popIn { from { opacity: 0; transform: translateY(14px) scale(.9); } to { opacity: 1; transform: none; } }
.genre-grid .genre-tile:nth-child(1){animation-delay:.02s} .genre-grid .genre-tile:nth-child(2){animation-delay:.05s}
.genre-grid .genre-tile:nth-child(3){animation-delay:.08s} .genre-grid .genre-tile:nth-child(4){animation-delay:.11s}
.genre-grid .genre-tile:nth-child(5){animation-delay:.14s} .genre-grid .genre-tile:nth-child(6){animation-delay:.17s}
.genre-grid .genre-tile:nth-child(7){animation-delay:.20s} .genre-grid .genre-tile:nth-child(8){animation-delay:.23s}

/* --- rows fade/slide in --- */
.tl-rows .row { animation: rowIn .25s ease both; }
@keyframes rowIn { from { opacity: 0; transform: translateX(-8px); } to { opacity: 1; transform: none; } }

/* --- view transition --- */
#libraryView, #browseView { animation: viewIn .3s ease both; }
@keyframes viewIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* --- now playing: living glow + equalizer on the playing row --- */
/* the whole bottom pill is the subwoofer: HARD neon glow + bass thump, on the REAL kick */
.player {
  position: relative; z-index: 30;
  /* drop-shadow (NOT box-shadow) so the glow hugs the LIQUID clipped silhouette,
     rippling with every bulge of the pill edge. Two layers max (battery). */
  filter: drop-shadow(0 6px 16px rgba(0, 0, 0, .5))
    drop-shadow(0 0 calc(3px + var(--beat) * 24px) rgba(168, 85, 247, calc(0.24 + var(--beat) * 0.62)));
  will-change: transform, filter;
  /* HIDDEN until something actually plays — then pops in with a spring */
  opacity: 0; pointer-events: none;
  transform: translateY(36px) scale(.94);
  transition: transform .5s cubic-bezier(.22,1.45,.36,1), opacity .3s ease;
}
.player.show {
  opacity: 1; pointer-events: auto;
  transform: translateY(calc(var(--beat) * -2.2px));
}
/* once the entrance spring lands, kill the transition — the beat thump must SNAP, not ease */
.player.settled { transition: none; }
.np-art {
  box-shadow: 0 0 calc(8px + var(--beat) * 34px) rgba(168,85,247, calc(0.12 + var(--beat) * 0.8));
  transform: translate(var(--shakeX, 0px), var(--shakeY, 0px)) scale(calc(1 + var(--beat) * 0.09));
  will-change: transform, box-shadow;
}
.ctrl.play {
  box-shadow: 0 0 calc(6px + var(--beat) * 38px) rgba(192,132,252, calc(0.25 + var(--beat) * 0.7));
  transform: scale(calc(1 + var(--beat) * 0.10));
  will-change: transform, box-shadow;
}
#dur, #durBig { cursor: pointer; }
.row.playing .c-idx .num, .row.playing .c-idx .pico { display: none; }
.row.playing .c-idx::before {
  content: ""; display: inline-block; width: 14px; height: 12px;
  background:
    linear-gradient(var(--green),var(--green)) 0 100%/3px 60% no-repeat,
    linear-gradient(var(--green),var(--green)) 5px 100%/3px 100% no-repeat,
    linear-gradient(var(--green),var(--green)) 10px 100%/3px 40% no-repeat;
  animation: eq .9s ease-in-out infinite alternate;
}
@keyframes eq {
  0%   { background-size: 3px 40%, 3px 80%, 3px 30%; }
  100% { background-size: 3px 90%, 3px 30%, 3px 70%; }
}

/* ============================================================
   HARDSTYLE  -  high-energy, bold motion
   ============================================================ */
/* punchy tap (overshoot) on the main controls */
@keyframes punch { 0%{transform:scale(.88);} 55%{transform:scale(1.05);} 100%{transform:scale(1);} }
.genre-tile:active, .src-btn:active, .lib-btn:active, .chip:active, .load-more:active { animation: punch .22s ease; }

/* bolder, springier tile entrance (overrides the gentle popIn) */
.genre-tile { animation: tileIn .42s cubic-bezier(.18,.9,.25,1.5) both; }
@keyframes tileIn { 0%{ opacity:0; transform: translateY(22px) scale(.84) rotate(-2deg);} 100%{ opacity:1; transform:none;} }

/* brand dot heartbeat */
.brand-dot { animation: dotPulse 2.4s ease-in-out infinite; }
@keyframes dotPulse { 0%,100%{ box-shadow:0 0 10px rgba(168,85,247,.5);} 50%{ box-shadow:0 0 24px rgba(168,85,247,.95);} }

/* now-playing artwork + play button: NO timer loops — the REAL beat (--beat, per-frame FFT)
   drives every glow, so the pulse lands exactly on the kick, never on a 1.9s clock. */
.ctrl.play { position: relative; }
.ctrl.play::after {
  content:""; position:absolute; inset:-4px; border-radius:50%; pointer-events:none;
  box-shadow: 0 0 0 calc(var(--beat) * 10px) rgba(192,132,252, calc(.34 - var(--beat) * .3));
}

/* playing row: neon EQ glow + lit lane */
.row.playing { background: linear-gradient(90deg, rgba(168,85,247,.12), transparent 60%); }
.row.playing .c-idx::before { filter: drop-shadow(0 0 5px rgba(192,132,252,.85)); }

/* hero greeting: slow chrome shine (same descender rule as greet-card h1) */
.hero h1 {
  line-height: 1.18; padding-bottom: 0.08em;
  background: linear-gradient(90deg,#fff 20%,#9be7b4 50%,#fff 80%);
  background-size: 220% 100%;
  -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
  animation: shine 7s linear infinite;
}
@keyframes shine { to { background-position: 220% 0; } }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}

/* ============================================================
   MOBILE / PWA  -  fully ADAPTIVE to any screen
   (dvh + clamp() + CSS-var stacking + safe-area; no fixed px)
   ============================================================ */
@media (max-width: 760px) {
  :root { --pad-x: clamp(12px, 4vw, 20px); }
  .app {
    grid-template-columns: 1fr;
    grid-template-rows: 1fr;
    grid-template-areas: "content";
    height: 100dvh;
  }
  /* sidebar -> floating glass bottom tab bar */
  .sidebar {
    grid-area: unset; position: fixed; inset: auto 0 0 0; z-index: 40;
    height: var(--nav-h);
    flex-direction: row; align-items: center; justify-content: space-around;
    padding: 0 clamp(8px, 4vw, 24px) env(safe-area-inset-bottom);
    background: rgba(8, 8, 11, .92); backdrop-filter: blur(20px);
    border-top: 1px solid rgba(255, 255, 255, .07); gap: 0;
  }
  .brand, .lib-actions, .playlists, .sidebar-foot { display: none; }
  .nav-links { flex-direction: row; gap: 0; width: 100%; justify-content: space-around; }
  .nav-links li { flex-direction: column; gap: 3px; font-size: clamp(10px, 3vw, 12px); padding: 6px clamp(10px, 5vw, 24px); }
  .nav-links .ico { font-size: clamp(20px, 6vw, 26px); transition: transform .15s, text-shadow .2s; }
  .nav-links li.active { color: var(--neon); }
  .nav-links li.active .ico { transform: translateY(-2px) scale(1.12); text-shadow: 0 0 14px rgba(192, 132, 252, .7); }

  /* floating glass player card, stacked above the nav on ANY screen.
     The pill IS the subwoofer: it glows hard and pumps (scale from the bottom edge)
     on the real FFT kick via --beat — no timer loops. */
  .player {
    grid-area: unset; position: fixed; z-index: 30;
    left: clamp(8px, 3vw, 18px); right: clamp(8px, 3vw, 18px);
    bottom: calc(env(safe-area-inset-bottom) + 10px);
    border-radius: 18px;
    background: none; /* body lives on ::before (liquid clip layer) */
    box-shadow: none; /* glow comes from the drop-shadow filter -> follows the liquid edge */
    /* TWO shadow layers, not three: each animated drop-shadow is a full repaint (battery) */
    filter: drop-shadow(0 8px 18px rgba(0, 0, 0, .55))
      drop-shadow(0 0 calc(3px + var(--beat) * 26px) rgba(168, 85, 247, calc(0.24 + var(--beat) * 0.62)));
    transform: translateY(140%) scale(.94); /* hidden state: fully below the screen */
    transform-origin: 50% 100%;
    display: flex; flex-wrap: wrap; align-items: center; row-gap: 4px; gap: 12px;
    padding: 10px 14px 8px;
  }
  .player.show { transform: scale(calc(1 + var(--beat) * 0.035)); }
  /* basis 0 (not auto): a long title must SHRINK, never wrap the buttons off the row */
  .np { flex: 1 1 0; min-width: 0; gap: 10px; overflow: hidden; }
  .np-meta { min-width: 0; overflow: hidden; }
  /* controls dissolve into the pill: buttons on row 1, the scrub gets its OWN full row —
     times sit beside the bar, never on top of it (was: absolute overlay, numbers collided) */
  .controls { display: contents; }
  .np-art { width: clamp(42px, 12vw, 54px); height: clamp(42px, 12vw, 54px); }
  .controls .scrub { order: 5; flex: 1 1 100%; max-width: none; display: flex; align-items: center; gap: 8px; min-height: 18px; }
  .controls .scrub .t { display: inline-block; font-size: 11px; min-width: 34px; color: var(--text-dim); }
  #livePill { position: static; order: 5; flex: 1 1 100%; justify-content: center; margin: 0; padding: 4px 10px; font-size: 10px; }
  .player::before { background: linear-gradient(180deg, #1d1d24, #131318); }
  /* heart: premium-size like target, thumb-friendly */
  .like { font-size: 26px; padding: 6px 8px; }
  .extras { display: none; }
  .player .ctrl.ghost { display: none; }   /* shuffle/repeat off the mini-bar */
  /* pause / prev / next: big, weighted, thumb-first */
  .ctrl-btns { gap: clamp(16px, 6.5vw, 26px); }
  .ctrl { font-size: 21px; }
  .ctrl.play { width: clamp(38px, 10vw, 43px); height: clamp(38px, 10vw, 43px); font-size: 19px; }

  /* content clears the floating player + nav on every device */
  .content {
    grid-area: unset;
    /* top: clear the status bar / notch; bottom: clear the floating player (no nav anymore) */
    padding: max(env(safe-area-inset-top), 30px) var(--pad-x) calc(var(--player-h) + env(safe-area-inset-bottom) + 28px);
  }
  /* PWA in a BROWSER TAB: the browser's own bar covers the status area — drop the big top pad */
  @media (display-mode: browser) {
    .content { padding-top: 12px; }
  }
  .topbar { margin: 0; padding: 6px 0 12px; }   /* kill the desktop -24px full-bleed (caused right overflow) */
  .search-wrap { max-width: none; min-width: 0; }
  html, body { overflow-x: hidden; max-width: 100%; }
  .content, .hero, .topbar, .tl-rows, .tl-head, .row, #libraryView, #browseView { max-width: 100%; min-width: 0; }
  .user-pill { display: none; }

  /* tiles + rows scale with the viewport, columns auto-fit any width */
  .genre-grid { grid-template-columns: repeat(auto-fill, minmax(clamp(132px, 42vw, 180px), 1fr)); gap: clamp(10px, 3vw, 16px); }
  .genre-tile { height: clamp(84px, 24vw, 116px); font-size: clamp(15px, 4.6vw, 18px); border-radius: clamp(16px, 5vw, 22px); }
  .row { padding: 12px 6px; grid-template-columns: 32px 1fr 54px; }
  .row.has-add { grid-template-columns: 32px 1fr 48px 34px; }
  .s-row.has-add { grid-template-columns: 44px 1fr 48px 34px; }
  .row .c-album, .tl-head .c-album { display: none; }
  .tl-head { grid-template-columns: 32px 1fr 54px; }
  .hero h1 { font-size: clamp(22px, 7vw, 32px); }
  .hero .sub { font-size: clamp(12px, 3.4vw, 14px); }
  .lib-btn, .src-btn, .chip { padding: 12px 16px; }
  .load-more { padding: 14px 30px; width: 100%; }
}

/* scrollbars: hidden everywhere — touch-first app, the rail is visual noise */
::-webkit-scrollbar { width: 0; height: 0; display: none; }
* { scrollbar-width: none; }

/* ============================================================
   v2: greeting home + bubbles + settings + expanded now-playing + visualizer
   ============================================================ */
/* SKY ENGINE stage: a compact rounded glass card holding a living sky */
.home-hero {
  padding: 20px 18px 16px;
  margin: 8px 0 12px;
  position: relative; overflow: hidden;
  border-radius: 24px;
  min-height: 116px;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.09), 0 10px 28px rgba(0,0,0,.35);
}
#skyCanvas { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 0; pointer-events: none; }
.greet-card { position: relative; z-index: 1; }
.greet-card h1 {
  /* gradient-clipped text: descenders (g, y, p) MUST stay inside the background box —
     line-height >= 1.18 + bottom padding, or they render transparent (= cut off) */
  font-size: clamp(28px, 8vw, 46px); font-weight: 800; letter-spacing: -1px; line-height: 1.18;
  padding-bottom: 0.08em;
  width: fit-content; max-width: 100%; /* box hugs the glyphs: sun avoidance + rain drips land on real letters */
  background: linear-gradient(90deg, var(--green), var(--neon), var(--neon2), var(--green));
  background-size: 300% 100%; -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; animation: greetShine 8s linear infinite, greetRise .6s ease both;
}
@keyframes greetShine { to { background-position: 300% 0; } }
@keyframes greetRise { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
.greet-card .sub { color: var(--text-dim); margin-top: 6px; }

.bubble-grid { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(12px, 3.5vw, 18px); padding: 16px 0 24px; }
.bubble {
  display: flex; flex-direction: column; align-items: flex-start; justify-content: space-between; gap: 12px;
  min-height: clamp(96px, 27vw, 134px); padding: 16px; border-radius: 22px; color: #fff;
  font-weight: 800; font-size: clamp(15px, 4.4vw, 18px); text-align: left; position: relative; overflow: hidden;
  cursor: pointer; transition: transform .12s cubic-bezier(.2,.8,.3,1.4), box-shadow .2s;
  animation: tileIn .42s cubic-bezier(.18,.9,.25,1.5) both;
}
.bubble:active { transform: scale(.94); filter: brightness(1.1); }
.bubble:hover { box-shadow: 0 12px 30px rgba(0,0,0,.5); }
.bub-ic { font-size: clamp(24px, 7vw, 32px); }
/* jewel-tone glass bubbles: deep gradients + hairline sheen */
.bub-browse   { background: linear-gradient(135deg, #7c5cf0, #3730a3); box-shadow: inset 0 1px 0 rgba(255,255,255,.22), 0 10px 26px rgba(0,0,0,.35); }
.bub-playlist { background: linear-gradient(135deg, #e0559a, #6d2854); box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 10px 26px rgba(0,0,0,.35); }
.bub-fresh    { background: linear-gradient(135deg, #e8a33d, #8a5a1f); box-shadow: inset 0 1px 0 rgba(255,255,255,.22), 0 10px 26px rgba(0,0,0,.35); }
.bubble:nth-child(1){animation-delay:.04s} .bubble:nth-child(2){animation-delay:.09s}
.bubble:nth-child(3){animation-delay:.14s} .bubble:nth-child(4){animation-delay:.19s}
.sec-title { font-size: 20px; font-weight: 800; margin: 6px 0 10px; }

.settings-form { display: flex; flex-direction: column; gap: 16px; max-width: 460px; }
.settings-form label { display: flex; flex-direction: column; gap: 6px; color: var(--text-dim); font-size: 13px; font-weight: 700; }
.settings-form input:not([type="range"]) { padding: 14px 16px; border-radius: 14px; background: var(--bg-hi); color: var(--text); border: 1px solid transparent; font-size: 15px; outline: none; }
.settings-form input:not([type="range"]):focus { border-color: var(--green); }
.save-btn { align-self: flex-start; background: var(--green); color: #fff; font-weight: 800; padding: 13px 30px; border-radius: 24px; }
.set-saved { color: var(--neon); font-weight: 700; }

/* expanded now-playing (full screen overlay) */
#nowPlayingView {
  position: fixed; inset: 0; z-index: 80;
  /* solid base layer: the radial alone was semi-transparent near the top — underlying
     view's buttons ghosted through (Ken saw "< Home" behind "< Back") */
  background: radial-gradient(120vmax 90vmax at 50% -10%, rgba(168,85,247,.22), transparent 60%), var(--bg);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: clamp(14px, 3vh, 26px);
  padding: max(env(safe-area-inset-top), 40px) 24px calc(env(safe-area-inset-bottom) + 30px);
  animation: npRise .28s cubic-bezier(.2,.8,.3,1) both;
}
@keyframes npRise { from { transform: translateY(100%); } to { transform: none; } }
/* real back button (was an ambiguous ⌄ chevron) — same glass pill language as view-back */
.np-back {
  position: absolute; top: max(env(safe-area-inset-top), 16px); left: 14px; z-index: 2;
  background: rgba(255,255,255,.1); color: var(--text); font-weight: 800; font-size: 15px;
  padding: 10px 18px; border-radius: 22px; backdrop-filter: blur(8px);
  transition: transform .1s, background .15s;
}
.np-back:active { transform: scale(.92); }
.np-big-art {
  width: clamp(180px, 62vw, 300px); height: clamp(180px, 62vw, 300px); border-radius: 22px;
  background-color: var(--bg-hi); background-position: center; background-size: cover;
  display: grid; place-items: center; font-size: 64px; color: var(--text-dim); z-index: 1;
  /* the artwork bumps, glows AND shudders with the real kick */
  transform: translate(var(--shakeX, 0px), var(--shakeY, 0px)) scale(calc(1 + var(--beat) * 0.10));
  box-shadow: 0 18px 50px rgba(168,85,247, calc(0.22 + var(--beat) * 0.6)),
              0 0 calc(var(--beat) * 110px) rgba(34,211,238, calc(var(--beat) * 0.8));
  will-change: transform, box-shadow;
}
/* the shaky waveform: real FFT fire bars, jittering on hard hits */
#waveBig {
  width: min(92%, 500px); height: 88px; z-index: 1;
  transform: translate(var(--shakeX, 0px), var(--shakeY, 0px));
  /* no per-frame filter here: bars carry their own glow colors (battery) */
  will-change: transform;
}
/* big, finger-friendly seek bar in the expanded player (drag anywhere on the song) */
#seekBig { display: block; width: 100%; height: 10px; border-radius: 7px; background: var(--bar); }
#seekBig::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none; width: 28px; height: 28px; border-radius: 50%;
  background: #fff; opacity: 1; border: 4px solid var(--green-hi);
  box-shadow: 0 2px 12px rgba(168,85,247,.8);
}
.np-times { font-size: 14px; font-weight: 700; }
.np-big-meta { text-align: center; max-width: 92%; z-index: 1; }
.np-big-title { font-size: clamp(20px, 6vw, 28px); font-weight: 800; }
.np-big-artist { color: var(--text-dim); margin-top: 4px; }
.np-big-source { color: var(--green); font-size: 12px; margin-top: 6px; text-transform: uppercase; letter-spacing: 1px; }
.np-scrub { width: 100%; max-width: 480px; z-index: 1; }
.np-times { display: flex; justify-content: space-between; color: var(--text-dim); font-size: 12px; margin-top: 8px; }
.np-big-controls { display: flex; align-items: center; gap: clamp(18px, 7vw, 30px); z-index: 1; }
.np-big-controls .ctrl { font-size: 24px; color: var(--text); }
.np-big-controls .ctrl.play { width: 66px; height: 66px; font-size: 22px; background: #fff; color: #000; border-radius: 50%; display: grid; place-items: center; }

/* overflow lock (no sideways slide) + ellipsis long titles */
/* NOTE: #browseView must NOT clip horizontally — shelves bleed past it to the screen edge */
#settingsView, #playlistView, .genre-grid, .tl-rows, .results-head, #hubChips, #searchChips, .bubble-grid { max-width: 100%; overflow-x: hidden; }
.c-title .tt, .np-title, .np-big-title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.player { cursor: pointer; }
.np { cursor: pointer; }

/* ============================================================
   v3: SUPER-GAMEY bubbles, back button, save heart, drag handle
   ============================================================ */
.bubble { animation: bubbleIn .55s cubic-bezier(.2,1.25,.3,1.4) both, bob 3.6s ease-in-out infinite; }
@keyframes bubbleIn { 0% { opacity: 0; transform: translateY(28px) scale(.65) rotate(-5deg); } 60% { opacity: 1; transform: translateY(-7px) scale(1.07); } 100% { opacity: 1; transform: none; } }
@keyframes bob { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-7px); } }
.bubble:nth-child(1) { animation-delay: 0s, .2s; }
.bubble:nth-child(2) { animation-delay: .07s, .55s; }
.bubble:nth-child(3) { animation-delay: .14s, .9s; }
.bubble:nth-child(4) { animation-delay: .21s, 1.25s; }
.bubble:active { animation: squash .32s ease; }
@keyframes squash { 0% { transform: scale(.85,.95); } 40% { transform: scale(1.1,.9); } 70% { transform: scale(.96,1.04); } 100% { transform: scale(1); } }
.bubble::after { content: ""; position: absolute; top: -60%; left: -40%; width: 45%; height: 220%; transform: translateX(-220%) rotate(20deg); background: linear-gradient(90deg, transparent, rgba(255,255,255,.28), transparent); animation: bubShine 5.5s ease-in-out infinite; pointer-events: none; }
@keyframes bubShine { 0%,72% { transform: translateX(-220%) rotate(20deg); } 88%,100% { transform: translateX(420%) rotate(20deg); } }
.bub-ic { transition: transform .2s cubic-bezier(.2,.8,.3,1.5); display: inline-block; }
.bubble:hover .bub-ic { transform: scale(1.3) rotate(-8deg); }
.bubble:active .bub-ic { transform: scale(1.45) rotate(8deg); }

/* back button (nav removed) */
.view-back {
  /* no negative margin: the view containers clip overflow-x, a -4px offset cut the pill's edge */
  position: relative; align-self: flex-start; margin: 6px 0 10px 0;
  background: rgba(255,255,255,.07); color: var(--text); font-weight: 800; font-size: 15px;
  padding: 10px 18px; border-radius: 22px; transition: transform .1s, background .15s;
}
.view-back:hover { background: rgba(255,255,255,.14); }
.view-back:active { transform: scale(.92); }

/* prominent back button in genre results (was a tiny transparent chevron) */
.results-back {
  flex: 0 0 auto; background: linear-gradient(135deg, var(--green), #6d28d9); color: #fff;
  font-weight: 800; font-size: 15px; padding: 11px 20px; border-radius: 22px;
  box-shadow: 0 4px 14px rgba(168,85,247,.45); transition: transform .1s, box-shadow .15s;
}
.results-back:hover { box-shadow: 0 6px 20px rgba(168,85,247,.6); }
.results-back:active { transform: scale(.92); }

/* expanded player: save heart + drag handle */
.np-save { position: absolute; top: max(env(safe-area-inset-top), 18px); right: 16px; font-size: 30px; color: var(--text-dim); background: none; line-height: 1; z-index: 2; }
.np-save.on, .like.on { color: var(--neon2); text-shadow: 0 0 16px rgba(255,43,214,.8); }
.np-drag-hint { position: absolute; top: 9px; left: 50%; transform: translateX(-50%); width: 46px; height: 5px; border-radius: 3px; background: rgba(255,255,255,.3); z-index: 2; }
.like { transition: color .15s, transform .1s; }

/* predictive-back: NO custom arrow (the OS draws its own) — the content itself reacts.
   Incoming view settles with a videogame overshoot on every back navigation. */
@keyframes slideBackIn {
  0% { transform: translateX(-6%) scale(.965); opacity: .45; }
  62% { transform: translateX(1.2%) scale(1.004); opacity: 1; }
  100% { transform: none; opacity: 1; }
}
.content.slide-back { animation: slideBackIn .32s cubic-bezier(.22,1.2,.36,1); }

/* ---- named playlists: list rows, new-playlist form, save picker ---- */
#plNew { margin: 4px 0 10px; }
.pl-newform { display: flex; gap: 8px; margin: 0 0 12px; }
.pl-newform input { flex: 1; min-width: 0; padding: 13px 14px; border-radius: 12px; background: rgba(255,255,255,.08); color: var(--text); font-size: 15px; border: none; outline: none; }
.pl-newform .save-btn { white-space: nowrap; }
.pl-list-row .pico { font-size: 20px; color: var(--green-hi); }
.pl-del { background: none; color: var(--text-dim); font-size: 16px; padding: 8px; flex: 0 0 auto; }
.pl-del:active { color: var(--neon2); transform: scale(.9); }

.pl-picker { position: fixed; inset: 0; z-index: 80; display: flex; align-items: flex-end; justify-content: center; background: rgba(0,0,0,.6); backdrop-filter: blur(4px); }
.pl-picker-card { width: 100%; max-width: 520px; background: linear-gradient(180deg, #1b1a24, #131218); border-radius: 22px 22px 0 0; padding: 20px 18px calc(env(safe-area-inset-bottom) + 20px); box-shadow: 0 -10px 40px rgba(0,0,0,.6); animation: npRise .25s ease; }
.pl-picker-head { font-size: 18px; font-weight: 800; margin-bottom: 14px; }
.pl-picker-list { display: flex; flex-direction: column; gap: 8px; max-height: 42vh; overflow-y: auto; }
.pl-pick-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; width: 100%; text-align: left; padding: 14px 16px; border-radius: 14px; background: rgba(255,255,255,.06); color: var(--text); font-size: 15px; font-weight: 600; }
.pl-pick-row.on { background: rgba(168,85,247,.22); }
.pl-pick-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pl-pick-chk { font-size: 20px; color: var(--green-hi); flex: 0 0 auto; }
.pl-pick-row.on .pl-pick-chk { color: var(--neon2); }
.pl-pick-empty { color: var(--text-dim); padding: 8px 4px 4px; font-size: 14px; }
.pl-picker-close { width: 100%; margin-top: 14px; padding: 14px; border-radius: 14px; background: rgba(255,255,255,.1); color: var(--text); font-weight: 800; font-size: 15px; }

/* ============================================================
   v4: GENRE HUBS + SHELVES + INSTANT SEARCH + LIVE RADIO
   ============================================================ */

/* ---- home instant search bar ---- */
.home-search-wrap {
  display: flex; align-items: center; gap: 10px;
  margin: 4px 0 14px; padding: 0 16px;
  background: var(--bg-hi); border-radius: 26px; border: 1px solid transparent;
  transition: border-color .15s, box-shadow .2s;
}
.home-search-wrap:focus-within { border-color: var(--green); box-shadow: 0 0 18px rgba(168,85,247,.35); }
.hs-ic { font-size: 20px; color: var(--text-dim); }
.hs-back { color: var(--text); font-size: 26px; font-weight: 900; padding: 6px 10px 6px 2px; line-height: 1; flex: 0 0 auto; }
.hs-back:active { transform: scale(.86); }
#homeSearch {
  flex: 1; min-width: 0; padding: 15px 0; background: none; border: none; outline: none;
  color: var(--text); font-size: 16px; font-family: inherit;
}
#homeSearch::placeholder { color: var(--text-dim); }
.hs-clear { color: var(--text-dim); font-size: 16px; padding: 8px; flex: 0 0 auto; }
.hs-clear:active { transform: scale(.88); color: var(--text); }

/* ---- search panel: sections, rows, top result ---- */
#searchPanel { animation: viewIn .25s ease both; padding-bottom: calc(var(--player-h) + 30px); }
.s-hint { color: var(--text-dim); font-size: 14px; padding: 14px 4px; line-height: 1.5; }
.s-sec { margin: 4px 0 14px; }
.s-row { grid-template-columns: 44px 1fr 54px; padding: 9px 8px; }
.s-row .c-title .tt { font-size: 15px; }
.s-more { margin: 10px 0 0 8px; display: inline-block; }
/* type filter chips collapse the blend to one type (Spotify pattern) */
.sf-songs .s-sec:not(.s-songs), .sf-artists .s-sec:not(.s-artists), .sf-live .s-sec:not(.s-live) { display: none; }
.top-card {
  display: flex; align-items: center; gap: 14px; padding: 14px;
  background: linear-gradient(135deg, rgba(168,85,247,.16), rgba(34,211,238,.08));
  border-radius: 18px; cursor: pointer; box-shadow: inset 0 0 0 1px rgba(255,255,255,.07);
  transition: transform .1s, box-shadow .2s;
}
.top-card:active { transform: scale(.97); }
.top-art {
  width: 74px; height: 74px; border-radius: 14px; flex: 0 0 auto;
  background-color: var(--bg-hi); background-size: cover; background-position: center;
  display: grid; place-items: center; font-size: 30px; color: var(--text-dim);
}
.top-artist .top-art { border-radius: 50%; }
.top-meta { min-width: 0; flex: 1; }
.top-t { font-size: 18px; font-weight: 800; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.top-s { color: var(--text-dim); font-size: 13px; margin-top: 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.top-play {
  width: 46px; height: 46px; border-radius: 50%; flex: 0 0 auto;
  background: var(--green); color: #fff; display: grid; place-items: center; font-size: 17px;
  box-shadow: 0 4px 16px rgba(168,85,247,.5);
}

/* ---- row artwork thumbs (search + results lists) ---- */
.c-idx .thumb {
  width: 36px; height: 36px; border-radius: 7px; display: inline-block;
  background-color: var(--bg-hi); background-size: cover; background-position: center;
}
.c-idx .thumb-empty { display: inline-grid; place-items: center; font-size: 16px; color: var(--text-dim); }
.row:hover .c-idx .thumb { display: none; }
.row.playing .c-idx .thumb { display: none; }

/* add-to-playlist ＋ on song rows (search + results) */
.row.has-add { grid-template-columns: 40px 1fr 1fr 60px 36px; }
.s-row.has-add { grid-template-columns: 44px 1fr 54px 36px; }
/* add-to-playlist: glass circle, not a bare glyph */
.row-add {
  width: 32px; height: 32px; border-radius: 50%; padding: 0;
  display: grid; place-items: center; justify-self: end; align-self: center;
  background: rgba(255,255,255,.07);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.16);
  color: var(--text-dim); font-size: 18px; font-weight: 800; line-height: 1;
  transition: transform .1s cubic-bezier(.2,.8,.3,1.4), background .15s, color .15s;
  flex: 0 0 auto;
}
.row-add:active { background: var(--green); color: #fff; transform: scale(.82); box-shadow: 0 0 14px rgba(168,85,247,.6); }

/* ---- shelves (horizontal scroll rails) ---- */
.shelf-sec { margin: 6px 0 16px; }
.shelf-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 8px; }
.shelf-head .sec-title { margin: 0; font-size: 18px; }
.shelf-all { color: var(--text-dim); font-size: 13px; font-weight: 700; padding: 6px 2px; white-space: nowrap; }
.shelf-all:hover, .shelf-all:active { color: var(--text); }
.shelf {
  /* FULL-BLEED: shelves run under the physical screen edges — cards slide in from
     outside the phone (negative gutter margins + matching inner padding) */
  display: flex; gap: 12px; overflow-x: auto; overflow-y: hidden;
  margin-left: calc(var(--pad-x) * -1); margin-right: calc(var(--pad-x) * -1);
  padding: 4px var(--pad-x) 10px;
  scroll-snap-type: x proximity;
  scroll-padding-left: var(--pad-x);
  scrollbar-width: none;
}
.shelf::-webkit-scrollbar { display: none; }
.card {
  position: relative; overflow: hidden; flex: 0 0 auto; width: clamp(118px, 32vw, 150px);
  cursor: pointer; scroll-snap-align: start; border-radius: 12px; padding: 6px;
  transition: transform .12s cubic-bezier(.2,.8,.3,1.4), background .15s;
}
.card:hover { background: var(--bg-elev); }
.card:active { transform: scale(.94); }
.card-art {
  position: relative; width: 100%; aspect-ratio: 1; border-radius: 10px; overflow: hidden;
  background: linear-gradient(135deg, var(--bg-hi), #2a2440);
  display: grid; place-items: center; font-size: 34px; color: var(--text-dim);
  box-shadow: 0 6px 16px rgba(0,0,0,.35);
}
.card-art img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: 1; }
.card-fallback { position: absolute; font-size: 34px; color: var(--text-dim); }
.card-t { font-size: 13px; font-weight: 700; margin-top: 8px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.card-s { font-size: 11.5px; color: var(--text-dim); margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.card-circle .card-art { border-radius: 50%; }
.card-circle .card-t { text-align: center; }
.card-circle .card-s { text-align: center; }
/* live station cards: pulsing red LIVE dot pinned on the art */
.card-dot { position: absolute; top: 12px; right: 12px; z-index: 2; }
.live-dot {
  display: inline-block; width: 9px; height: 9px; border-radius: 50%;
  background: #ff3b3b; box-shadow: 0 0 10px rgba(255,59,59,.9);
  animation: liveBlink 1.6s ease-in-out infinite;
}
@keyframes liveBlink { 0%,100% { opacity: 1; } 50% { opacity: .35; } }
.shelf-note { color: var(--text-dim); font-size: 13.5px; padding: 10px 4px; display: flex; align-items: center; gap: 12px; }

/* skeleton shimmer while shelves/search load */
.skel .card-art, .skel-box { background: var(--bg-hi); }
.skel-line { display: inline-block; height: 12px; border-radius: 6px; background: var(--bg-hi); width: 76%; }
.skel .card-art, .skel .skel-line, .skel-box, .s-row.skel .skel-line {
  position: relative; overflow: hidden;
}
.skel .card-art::after, .skel-line::after, .skel-box::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(100deg, transparent 30%, rgba(255,255,255,.09) 50%, transparent 70%);
  animation: shimmer 1.4s linear infinite;
}
@keyframes shimmer { from { transform: translateX(-100%); } to { transform: translateX(100%); } }
.skel-box { width: 36px; height: 36px; border-radius: 7px; display: inline-block; }

/* ---- genre hub ---- */
.hub-hero {
  margin: 6px calc(var(--pad-x) * -1) 12px; padding: 34px var(--pad-x) 22px;
  border-radius: 0 0 26px 26px;
}
.hub-hero h1 { font-size: clamp(30px, 8vw, 44px); font-weight: 800; letter-spacing: -1px; }
.hub-hero .sub { color: rgba(255,255,255,.85); margin-top: 6px; font-size: 14px; }
#hubChips { padding-bottom: 16px; }
@media (max-width: 760px) {
  .hub-hero { padding-top: 26px; padding-bottom: 18px; }
}

/* ---- LIVE state on the player ---- */
.live-pill {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 6px 14px; border-radius: 16px; font-size: 12px; font-weight: 800; letter-spacing: 1.5px;
  background: rgba(255,59,59,.16); color: #ff6b6b; box-shadow: inset 0 0 0 1px rgba(255,59,59,.35);
}
.player.is-live .scrub { display: none; }
.player.is-live .controls { justify-content: center; }
/* LIVE badge lives on its OWN row of the pill (never absolute — an absolute rule here
   once parked it on top of the artwork). The mobile row rule lives in the player block. */
#livePill { margin: 2px auto 0; }

/* ---- bubbles ---- */
.bub-live { background: linear-gradient(135deg, #dc3545, #6e1423); box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 10px 26px rgba(0,0,0,.35); }
/* settings = standard top-right gear on Home (was a whole bubble) */
.home-hero { position: relative; }
.home-top { display: flex; justify-content: flex-end; padding-top: 6px; }
.gear-btn {
  width: 44px; height: 44px; border-radius: 50%;
  display: grid; place-items: center;
  background: rgba(255,255,255,.08); color: var(--text-dim);
  transition: transform .12s cubic-bezier(.2,.8,.3,1.4), background .15s, color .15s;
}
.gear-btn:hover { color: var(--text); background: rgba(255,255,255,.14); }
.gear-btn:active { transform: scale(.86) rotate(30deg); color: var(--neon); }

/* settings hint */
.set-hint { font-weight: 400; font-size: 11.5px; color: var(--text-dim); }
.set-sec {
  margin-top: 10px; padding-top: 16px; border-top: 1px solid rgba(255,255,255,.08);
  font-size: 17px; font-weight: 800; color: var(--text);
}
.cf-bar {
  /* thin rail — it's just a track for the lever. flex:0 kills the column-flex stretch
     (the shared .bar class has flex:1, which ballooned this input's height in the label) */
  flex: 0 0 auto;
  width: 100%; max-width: 460px; height: 4px; margin-top: 14px;
  background: linear-gradient(to right, var(--green) var(--p, 33%), var(--bar) var(--p, 33%)) !important;
}
.cf-bar::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none; width: 22px; height: 22px; border-radius: 50%;
  background: #fff; opacity: 1; border: 3px solid var(--green-hi);
  box-shadow: 0 2px 10px rgba(168,85,247,.7);
}
