@import url('https://fonts.googleapis.com/css2?family=Bebas+Neue&family=Big+Shoulders+Display:wght@600;800&family=Fraunces:opsz,wght@9..144,400;9..144,600&family=IBM+Plex+Mono:wght@400;500&family=Playfair+Display:wght@700;900&family=Monoton&family=Kaushan+Script&family=VT323&display=swap');

:root {
  --bg: #060608;
  --surface: #101014;
  --surface-raised: #17171d;
  --gold: #d4af37;
  --gold-bright: #f2cf6e;
  --pink: #ff2d95;
  --pink-bright: #ff5cb3;
  --cyan: #22d3ee;
  --cyan-bright: #6ee7f5;
  --purple: #a855f7;
  --cream: #f2ece0;
  --cream-dim: #b8b0a2;
  --shadow: rgba(0, 0, 0, 0.7);

  --font-marquee: 'Playfair Display', serif;
  --font-title: 'Fraunces', serif;
  --font-mono: 'IBM Plex Mono', monospace;
  --font-script: 'Big Shoulders Display', sans-serif;
}

@keyframes neonPulse {
  0%, 100% { box-shadow: inset 0 0 24px rgba(255, 45, 149, 0.25), inset 0 0 3px rgba(34, 211, 238, 0.4); }
  50% { box-shadow: inset 0 0 40px rgba(255, 45, 149, 0.4), inset 0 0 6px rgba(34, 211, 238, 0.65); }
}

@keyframes titleFlicker {
  0%, 100% { text-shadow: 0 0 14px rgba(212, 175, 55, 0.6), 0 0 32px rgba(212, 175, 55, 0.35); }
  92% { text-shadow: 0 0 14px rgba(212, 175, 55, 0.6), 0 0 32px rgba(212, 175, 55, 0.35); }
  93% { text-shadow: 0 0 4px rgba(212, 175, 55, 0.2); }
  94% { text-shadow: 0 0 14px rgba(212, 175, 55, 0.6), 0 0 32px rgba(212, 175, 55, 0.35); }
}

@keyframes eqBounce {
  0%, 100% { height: 20%; }
  50% { height: 90%; }
}

@keyframes ctaPulse {
  0%, 100% { box-shadow: 0 0 14px rgba(255, 45, 149, 0.45); }
  50% { box-shadow: 0 0 26px rgba(255, 45, 149, 0.75); }
}

.neon-frame {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 50;
  border: 2px solid rgba(255, 45, 149, 0.4);
  animation: neonPulse 3.4s ease-in-out infinite;
}

/* ================= Custom scrollbars ================= */
/* Default browser scrollbars render light/white and clash badly against
   this dark theme — style them to match instead of leaving them native. */

* {
  scrollbar-width: thin;
  scrollbar-color: var(--gold) transparent;
}

*::-webkit-scrollbar {
  width: 8px;
  height: 6px;
}

*::-webkit-scrollbar-track {
  background: transparent;
}

*::-webkit-scrollbar-thumb {
  background: var(--gold);
  border-radius: 4px;
}

*::-webkit-scrollbar-thumb:hover {
  background: var(--gold-bright);
}

/* Tag tabs specifically scroll horizontally but the bar doesn't need to
   be visible at all — the row is short enough that drag/swipe is enough */
.tag-tabs::-webkit-scrollbar {
  height: 0px;
}
.tag-tabs {
  scrollbar-width: none;
}

* { box-sizing: border-box; }

html, body {
  height: 100%;
  overflow: hidden;
}

body {
  margin: 0;
  background:
    radial-gradient(ellipse at 20% 0%, rgba(255,45,149,0.10) 0%, transparent 45%),
    radial-gradient(ellipse at 80% 0%, rgba(34,211,238,0.10) 0%, transparent 45%),
    radial-gradient(circle at 1px 1px, rgba(255,255,255,0.025) 1px, transparent 0) 0 0/22px 22px,
    var(--bg);
  color: var(--cream);
  font-family: var(--font-title);
  -webkit-tap-highlight-color: transparent;
  user-select: none;
  display: flex;
  flex-direction: column;
}

/* ================= Top logo bar ================= */

/* Grid, not flex — the logo needs to sit on the page's true center line,
   but its flanking siblings are very unequal in width (the small eq-decor
   bars vs. the zone picker/presented-by/QR cluster). A flex:1 middle
   column centers within whatever space is left between two unequal
   siblings, which is NOT the true center (confirmed: the logo drifted
   left of center, worse once the QR badge widened the right side
   further). minmax(0,1fr) on both outer columns forces them to equal
   width regardless of their own content, so the auto-sized middle column
   lands exactly on center; the wider (right) side has plenty of room to
   fit within that shared width without overflowing. */
.top-bar {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: center;
  padding: 14px 28px;
  background: linear-gradient(180deg, var(--surface-raised), var(--surface));
  border-bottom: 2px solid var(--gold);
  box-shadow: 0 4px 24px rgba(0,0,0,0.6);
  position: relative;
  z-index: 5;
  gap: 20px;
}

.eq-decor {
  display: flex;
  align-items: flex-end;
  gap: 3px;
  height: 40px;
  flex-shrink: 0;
  justify-self: start; /* grid column, not flex — pins it to the left edge */
}

.eq-decor span {
  width: 5px;
  border-radius: 2px;
  animation: eqBounce 1.4s ease-in-out infinite;
}
.eq-decor span:nth-child(1) { background: var(--pink); height: 40%; animation-delay: 0s; }
.eq-decor span:nth-child(2) { background: var(--purple); height: 70%; animation-delay: 0.15s; }
.eq-decor span:nth-child(3) { background: var(--cyan); height: 90%; animation-delay: 0.3s; }
.eq-decor span:nth-child(4) { background: var(--gold); height: 55%; animation-delay: 0.45s; }
.eq-decor span:nth-child(5) { background: var(--pink); height: 80%; animation-delay: 0.6s; }
.eq-decor span:nth-child(6) { background: var(--cyan); height: 35%; animation-delay: 0.75s; }
.eq-decor span:nth-child(7) { background: var(--gold); height: 65%; animation-delay: 0.9s; }

.logo-badge {
  display: flex;
  justify-content: center;
  justify-self: center; /* grid column, not flex — the column is already
                            auto-sized to content, this just makes the
                            centering intent explicit */
}

.neon-marquee {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
}

.neon-top-row {
  display: flex;
  align-items: center;
  gap: 14px;
}

/* The signature-style "P$" neon script, red tube glow */
.neon-p-dollar {
  font-family: 'Kaushan Script', cursive;
  font-size: 46px;
  line-height: 1;
  color: #fff;
  -webkit-text-stroke: 1px rgba(255,255,255,0.4);
  text-shadow:
    0 0 4px #fff,
    0 0 10px #ff2d55,
    0 0 20px #ff2d55,
    0 0 34px #ff2d55,
    0 0 48px #d4004a;
  animation: neonPFlicker 7s linear infinite;
}

/* Tapering "speed line" wing flourishes either side of the P$, like a
   vintage neon roadside sign */
.neon-wing {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.neon-wing span {
  height: 2px;
  background: var(--cyan-bright);
  box-shadow: 0 0 6px var(--cyan-bright), 0 0 12px var(--cyan);
  border-radius: 2px;
}

.neon-wing-left span:nth-child(1) { width: 46px; }
.neon-wing-left span:nth-child(2) { width: 32px; margin-left: 14px; }
.neon-wing-left span:nth-child(3) { width: 18px; margin-left: 28px; }

.neon-wing-right span:nth-child(1) { width: 46px; }
.neon-wing-right span:nth-child(2) { width: 32px; margin-right: 14px; align-self: flex-end; }
.neon-wing-right span:nth-child(3) { width: 18px; margin-right: 28px; align-self: flex-end; }

.neon-sub-row {
  display: flex;
  align-items: center;
  gap: 10px;
}

/* Blocky tube-letter "JUKEBOX" in cyan neon */
.neon-jukebox {
  font-family: 'Monoton', cursive;
  font-size: 22px;
  letter-spacing: 4px;
  color: #fff;
  text-shadow:
    0 0 3px #fff,
    0 0 8px var(--cyan-bright),
    0 0 16px var(--cyan),
    0 0 28px var(--cyan);
}

.neon-dash {
  width: 26px;
  height: 2px;
  background: #ff2d55;
  box-shadow: 0 0 6px #ff2d55, 0 0 12px #ff2d55;
  border-radius: 2px;
}

@keyframes neonSignFlicker {
  0%, 100% { opacity: 1; }
  91% { opacity: 1; }
  92% { opacity: 0.85; }
  93% { opacity: 1; }
  94% { opacity: 0.7; }
  95% { opacity: 1; }
}

/* A more convincing "old neon sign" flicker for the P$ mark specifically —
   a quick stutter cluster, a dead-dim dropout, then a late single flicker,
   with a real dim (not just faded opacity) so it reads as a power
   fluctuation rather than a fade. */
@keyframes neonPFlicker {
  0%, 100% {
    opacity: 1;
    text-shadow: 0 0 4px #fff, 0 0 10px #ff2d55, 0 0 20px #ff2d55, 0 0 34px #ff2d55, 0 0 48px #d4004a;
  }
  2% {
    opacity: 0.3;
    text-shadow: 0 0 2px #fff, 0 0 4px #ff2d55, 0 0 8px #ff2d55, 0 0 12px #ff2d55, 0 0 16px #d4004a;
  }
  3% {
    opacity: 1;
    text-shadow: 0 0 4px #fff, 0 0 10px #ff2d55, 0 0 20px #ff2d55, 0 0 34px #ff2d55, 0 0 48px #d4004a;
  }
  4% {
    opacity: 0.2;
    text-shadow: 0 0 2px #fff, 0 0 4px #ff2d55, 0 0 8px #ff2d55, 0 0 12px #ff2d55, 0 0 16px #d4004a;
  }
  5%, 45% {
    opacity: 1;
    text-shadow: 0 0 4px #fff, 0 0 10px #ff2d55, 0 0 20px #ff2d55, 0 0 34px #ff2d55, 0 0 48px #d4004a;
  }
  46% {
    opacity: 0.4;
    text-shadow: 0 0 2px #fff, 0 0 4px #ff2d55, 0 0 8px #ff2d55, 0 0 12px #ff2d55, 0 0 16px #d4004a;
  }
  47%, 78% {
    opacity: 1;
    text-shadow: 0 0 4px #fff, 0 0 10px #ff2d55, 0 0 20px #ff2d55, 0 0 34px #ff2d55, 0 0 48px #d4004a;
  }
  79% {
    opacity: 0.25;
    text-shadow: 0 0 2px #fff, 0 0 4px #ff2d55, 0 0 8px #ff2d55, 0 0 12px #ff2d55, 0 0 16px #d4004a;
  }
  80% {
    opacity: 1;
    text-shadow: 0 0 4px #fff, 0 0 10px #ff2d55, 0 0 20px #ff2d55, 0 0 34px #ff2d55, 0 0 48px #d4004a;
  }
  81% {
    opacity: 0.5;
    text-shadow: 0 0 2px #fff, 0 0 4px #ff2d55, 0 0 8px #ff2d55, 0 0 12px #ff2d55, 0 0 16px #d4004a;
  }
  82%, 99% {
    opacity: 1;
    text-shadow: 0 0 4px #fff, 0 0 10px #ff2d55, 0 0 20px #ff2d55, 0 0 34px #ff2d55, 0 0 48px #d4004a;
  }
}

.top-bar-right {
  display: flex;
  align-items: center;
  gap: 22px;
  flex-shrink: 0;
  justify-self: end; /* grid column, not flex — pins it to the right edge */
}

.zone-stack {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}

/* Custom-built dropdown instead of a native <select> — the options popup
   on a native select can't be reliably themed cross-browser (Android
   WebViews in particular just render it as a plain native list, ignoring
   most CSS), so this is fully our own markup/styling instead. */
.zone-picker {
  position: relative;
}

.zone-picker-btn {
  display: flex;
  align-items: center;
  gap: 5px;
  font-family: var(--font-mono);
  background: var(--bg);
  color: var(--pink-bright);
  border: 1px solid var(--pink-bright);
  border-radius: 20px;
  padding: 4px 12px;
  font-size: 13px;
  box-shadow: 0 0 10px rgba(255,45,149,0.3);
  cursor: pointer;
  white-space: nowrap;
}

.zone-picker-icon { font-size: 12px; }

.zone-picker-arrow {
  font-size: 9px;
  margin-left: 2px;
  transition: transform 0.15s ease;
}

.zone-picker.open .zone-picker-arrow { transform: rotate(180deg); }

.zone-picker-menu {
  display: none;
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  min-width: 150px;
  background: var(--surface-raised);
  border: 1px solid var(--pink-bright);
  border-radius: 12px;
  box-shadow: 0 10px 30px rgba(0,0,0,0.65), 0 0 16px rgba(255,45,149,0.35);
  overflow: hidden;
  z-index: 500;
}

.zone-picker.open .zone-picker-menu { display: block; }

.zone-picker-option {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 11px 14px;
  background: transparent;
  border: none;
  border-bottom: 1px solid rgba(255,255,255,0.06);
  color: var(--cream);
  font-family: var(--font-mono);
  font-size: 13px;
  text-align: left;
  cursor: pointer;
}

.zone-picker-option:last-child { border-bottom: none; }

.zone-picker-option:active,
.zone-picker-option.active {
  background: rgba(255,45,149,0.18);
  color: var(--pink-bright);
}

.presented-by {
  display: flex;
  flex-direction: column;
  align-items: center;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 2px;
  color: var(--cream-dim);
  gap: 4px;
}

/* Always-visible header companion — same link as the tap-to-open QR
   overlay (openQrOverlay/qrToggleBtn), just glanceable without a tap.
   Sits in the header's natural gap between the centered logo and the
   presented-by badge. */
.header-qr-badge {
  display: flex;
  flex-direction: column;
  align-items: center;
  font-family: var(--font-mono);
  font-size: 8px;
  letter-spacing: 1px;
  line-height: 1.4;
  color: var(--cream-dim);
  text-align: center;
  gap: 4px;
}

.header-qr-code-wrap {
  background: var(--cream);
  padding: 4px;
  border-radius: 6px;
  border: 2px solid var(--gold);
  box-shadow: 0 0 10px rgba(212,175,55,0.35);
  line-height: 0;
}

.arcade-badge {
  display: flex;
  flex-direction: column;
  align-items: center;
  border: 2px solid var(--cyan);
  border-radius: 8px;
  padding: 3px 10px;
  box-shadow: 0 0 12px rgba(34,211,238,0.45);
}

.arcade-badge-p {
  font-family: var(--font-marquee);
  font-weight: 900;
  font-size: 20px;
  color: var(--gold-bright);
}

.arcade-badge-sub {
  font-family: var(--font-mono);
  font-size: 9px;
  color: var(--pink-bright);
  letter-spacing: 1px;
}

.invader {
  font-size: 26px;
  filter: drop-shadow(0 0 8px rgba(255,45,149,0.6));
}

/* The header invader (#dakboardPingBtn) is a real button now, not just
   decorative text — reset it back to look identical to the plain span
   it used to be, since .invader's own rule only covers font/glow. */
button.invader {
  background: none;
  border: none;
  padding: 0;
  line-height: 1;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
button.invader:active { transform: scale(0.9); }

/* ================= App body: 3 columns ================= */

.app-body {
  display: grid;
  grid-template-columns: 220px 1fr 320px;
  flex: 1;
  min-height: 0;
  overflow: hidden;
}

/* ---------------- Left sidebar nav ---------------- */

.side-nav {
  background: linear-gradient(180deg, var(--surface-raised), var(--bg));
  border-right: 1px solid #221c14;
  padding: 20px 0;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  overflow-y: auto;
  min-height: 0;
}

.nav-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.nav-item {
  width: 100%;
  text-align: left;
  background: transparent;
  border: none;
  border-left: 3px solid transparent;
  color: var(--cream-dim);
  font-family: var(--font-mono);
  font-size: 14px;
  letter-spacing: 1px;
  padding: 13px 20px;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 10px;
}

.nav-icon { font-size: 16px; }
.nav-arrow { margin-left: auto; color: var(--pink-bright); }

.nav-item.active {
  color: var(--gold-bright);
  border-left-color: var(--pink-bright);
  background: linear-gradient(90deg, rgba(255,45,149,0.12), transparent);
  text-shadow: 0 0 8px rgba(212,175,55,0.5);
}

.nav-item:active { background: rgba(34,211,238,0.08); }

.side-nav-tagline {
  font-family: var(--font-script);
  font-style: italic;
  font-size: 19px;
  color: var(--gold-bright);
  text-shadow: 0 0 10px rgba(212,175,55,0.4);
  padding: 20px 24px;
  line-height: 1.5;
  border-top: 1px solid #221c14;
}

/* ---------------- Center content ---------------- */

.main-content {
  padding: 22px 28px 24px;
  overflow-y: auto;
  min-height: 0;
  position: relative;
}

.scroll-to-top-btn {
  position: fixed;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: rgba(8, 14, 18, 0.9);
  border: 2px solid var(--cyan);
  color: var(--cyan-bright);
  font-size: 17px;
  font-weight: 700;
  cursor: pointer;
  box-shadow: 0 6px 18px rgba(0,0,0,0.55), 0 0 16px rgba(34,211,238,0.4);
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: opacity 0.2s ease, transform 0.15s ease, box-shadow 0.2s ease;
}

.scroll-to-top-btn:hover {
  box-shadow: 0 6px 18px rgba(0,0,0,0.55), 0 0 22px rgba(34,211,238,0.65);
}
.scroll-to-top-btn:active { transform: scale(0.92); }

.search-bar-wrap {
  position: relative;
  margin-bottom: 22px;
}

.search-icon {
  position: absolute;
  left: 16px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--pink-bright);
  font-size: 17px;
}

.search-clear-btn {
  position: absolute;
  right: 12px;
  top: 50%;
  transform: translateY(-50%);
  background: transparent;
  border: none;
  color: var(--cream-dim);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  padding: 4px 6px;
}

.search-clear-btn:hover { color: var(--pink-bright); }

.search-input-main {
  width: 100%;
  font-family: var(--font-title);
  font-size: 18px;
  padding: 13px 40px 13px 44px;
  background: var(--surface);
  border: 1px solid #2a231a;
  border-radius: 8px;
  color: var(--cream);
}

.search-input-main:focus {
  outline: none;
  border-color: var(--pink-bright);
  box-shadow: 0 0 12px rgba(255,45,149,0.3);
}

.search-mode-toggle {
  display: flex;
  gap: 8px;
  margin-bottom: 18px;
}

.search-mode-btn {
  background: transparent;
  border: 1px solid #3a3226;
  color: var(--cream-dim);
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 1px;
  padding: 6px 16px;
  border-radius: 20px;
  cursor: pointer;
}

.search-mode-btn.active {
  border-color: var(--pink-bright);
  color: var(--pink-bright);
  box-shadow: 0 0 10px rgba(255,45,149,0.25);
}

.search-status {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--cream-dim);
  margin-bottom: 12px;
}

.search-results {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 14px;
  margin-bottom: 10px;
}

.search-result {
  position: relative;
  cursor: pointer;
  text-align: left;
  background: var(--surface);
  border-radius: 10px;
  padding: 8px;
  border: 1px solid #241d16;
  display: flex;
  flex-direction: column;
  height: 100%;
}

.search-result img {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: 6px;
}

.search-result .meta {
  flex: 1;
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--cream-dim);
  margin-top: 6px;
  line-height: 1.4;
}

.search-queue-btn {
  width: 100%;
  margin-top: auto;
  padding: 5px 10px;
  font-size: 12px;
  font-family: var(--font-mono);
  background: transparent;
  border: 1px solid var(--gold);
  color: var(--gold-bright);
  border-radius: 4px;
  cursor: pointer;
}

.section-heading {
  font-family: var(--font-marquee);
  font-weight: 900;
  font-size: 24px;
  letter-spacing: 1px;
  color: var(--gold-bright);
  text-align: center;
  margin: 26px 0 16px;
  position: relative;
}

.section-heading::before,
.section-heading::after {
  content: "";
  position: absolute;
  top: 50%;
  width: 22%;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--gold), transparent);
}
.section-heading::before { left: 0; }
.section-heading::after { right: 0; }

/* ---------------- Genre grid ---------------- */

.genre-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
}

/* Featured's icons carry much longer labels than a genre tag ("American
   Top 40 Classics" vs "80s") — 3 columns instead of 4 gives each card
   more width, and a smaller label size keeps the longest ones from
   wrapping past the card's fixed height. */
.featured-grid {
  grid-template-columns: repeat(3, 1fr);
}

.featured-grid .genre-card {
  height: 190px;
}

.featured-grid .genre-label {
  font-size: 14px;
  line-height: 1.3;
  padding: 12px 14px;
}

.genre-card {
  position: relative;
  height: 150px;
  border-radius: 14px;
  overflow: hidden;
  cursor: pointer;
  background-size: cover;
  background-position: center;
  background-color: var(--surface-raised);
  display: flex;
  align-items: flex-end;
  border: 2px solid var(--gold);
  transition: transform 0.18s ease, box-shadow 0.18s ease;
}

.genre-card:active { transform: scale(0.97) translateY(1px); }

.genre-card::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(0,0,0,0.05) 0%, rgba(0,0,0,0.35) 50%, rgba(0,0,0,0.92) 100%);
}

.genre-card::after {
  /* faint color wash tying the photo back to the card's neon border color */
  content: "";
  position: absolute;
  inset: 0;
  mix-blend-mode: overlay;
  opacity: 0.5;
}

.genre-card.c-pink::after { background: radial-gradient(circle at 30% 20%, var(--pink), transparent 60%); }
.genre-card.c-cyan::after { background: radial-gradient(circle at 30% 20%, var(--cyan), transparent 60%); }
.genre-card.c-gold::after { background: radial-gradient(circle at 30% 20%, var(--gold), transparent 60%); }
.genre-card.c-purple::after { background: radial-gradient(circle at 30% 20%, var(--purple), transparent 60%); }

.genre-card .genre-label {
  position: relative;
  z-index: 1;
  font-family: var(--font-marquee);
  font-weight: 900;
  font-size: 21px;
  color: #fff;
  padding: 14px 16px;
  text-transform: uppercase;
  line-height: 1.15;
  text-shadow: 0 2px 10px rgba(0,0,0,0.9);
}

.decade-s {
  font-size: 0.6em;
  text-transform: lowercase;
}

.genre-card.c-pink { border-color: var(--pink); box-shadow: 0 10px 26px rgba(0,0,0,0.5), 0 0 22px rgba(255,45,149,0.4); }
.genre-card.c-cyan { border-color: var(--cyan); box-shadow: 0 10px 26px rgba(0,0,0,0.5), 0 0 22px rgba(34,211,238,0.4); }
.genre-card.c-gold { border-color: var(--gold); box-shadow: 0 10px 26px rgba(0,0,0,0.5), 0 0 22px rgba(212,175,55,0.4); }
.genre-card.c-purple { border-color: var(--purple); box-shadow: 0 10px 26px rgba(0,0,0,0.5), 0 0 22px rgba(168,85,247,0.4); }

/* One-off: Americana's photo composition reads better with its label
   centered than the grid's usual bottom-left placement. */
.genre-card-center-label { justify-content: center; text-align: center; }

/* One-off: for a tile whose source image already carries its own name
   and its own graphic border/frame (e.g. the Classic Country 104.9 tile
   — see renderGenreGrid) — the normal label text and neon card border
   would just duplicate both, so this strips the card down to the bare
   image. */
.genre-card-image-only {
  border: none;
  box-shadow: 0 10px 26px rgba(0,0,0,0.5);
}
.genre-card-image-only::before,
.genre-card-image-only::after {
  content: none;
}

/* ---------------- Featured row ---------------- */

.featured-row {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 16px;
}

.featured-card {
  cursor: pointer;
  text-align: left;
  transition: transform 0.15s ease;
}

.featured-card:active { transform: scale(0.96); }

.featured-card img {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: 10px;
  border: 1px solid rgba(212,175,55,0.25);
  box-shadow: 0 10px 22px rgba(0,0,0,0.55);
}

.featured-card .f-title {
  font-size: 15px;
  font-weight: 600;
  margin-top: 8px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.featured-card .f-artist {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--gold-bright);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.back-to-genres {
  background: transparent;
  border: 1px solid var(--gold);
  color: var(--gold-bright);
  font-family: var(--font-mono);
  font-size: 14px;
  padding: 7px 14px;
  border-radius: 16px;
  cursor: pointer;
  margin-bottom: 14px;
}

.now-playing-big {
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
}

.big-np-art {
  width: min(320px, 40vh);
  height: min(320px, 40vh);
  border-radius: 16px;
  object-fit: cover;
  border: 3px solid var(--gold);
  box-shadow: 0 20px 50px rgba(0,0,0,0.6), 0 0 40px rgba(212,175,55,0.35);
  margin-bottom: 24px;
  background: var(--surface);
}

.big-np-title {
  font-size: 32px;
  font-weight: 700;
  color: var(--cream);
}

.big-np-artist {
  font-family: var(--font-mono);
  font-size: 18px;
  color: var(--pink-bright);
  margin-top: 6px;
}

.big-np-album {
  font-family: var(--font-title);
  font-style: italic;
  font-size: 16px;
  color: var(--cream-dim);
  margin-top: 4px;
}

.big-np-progress-wrap {
  display: flex;
  align-items: center;
  gap: 12px;
  width: min(480px, 80%);
  margin-top: 28px;
}

.big-np-controls {
  display: flex;
  gap: 20px;
  margin-top: 20px;
}

.big-np-btn {
  width: 54px;
  height: 54px;
  font-size: 22px;
}

/* ---------------- Tag tabs ---------------- */

.tag-tabs {
  display: flex;
  gap: 10px;
  overflow-x: auto;
  margin-bottom: 16px;
}

.tag-tab {
  font-family: var(--font-mono);
  font-size: 14px;
  letter-spacing: 0.5px;
  white-space: nowrap;
  background: transparent;
  border: 1px solid #3a3226;
  color: var(--cream-dim);
  padding: 7px 14px;
  border-radius: 20px;
  cursor: pointer;
  flex-shrink: 0;
}

.tag-tab.active {
  border-color: var(--pink-bright);
  color: var(--pink-bright);
  background: rgba(255, 45, 149, 0.12);
  box-shadow: 0 0 10px rgba(255, 45, 149, 0.35);
}

/* ---------------- Cover wall (albums / stations) ---------------- */

.cover-wall {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: 18px;
}

.album-tile, .station-tile {
  cursor: pointer;
  border-radius: 12px;
  overflow: hidden;
  background: var(--surface);
  box-shadow: 0 12px 26px rgba(0,0,0,0.55), 0 0 0 1px rgba(212,175,55,0.15);
  transition: transform 0.15s ease, box-shadow 0.2s ease;
  position: relative;
}

.album-tile:active, .station-tile:active {
  transform: scale(0.96);
  box-shadow: 0 4px 22px rgba(255,45,149,0.4), 0 0 0 1px var(--pink-bright);
}

.album-tile img, .station-tile img {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  display: block;
  border-bottom: 2px solid var(--gold);
}

.album-tile .info, .station-tile .info { padding: 10px 12px; }

.album-tile .title, .station-tile .title {
  font-size: 16px;
  font-weight: 600;
  color: var(--cream);
  margin: 0 0 2px;
}

.album-tile .artist, .station-tile .format {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--gold-bright);
  margin: 0;
}

/* Radio station tiles specifically match the genre grid's size/shape
   (4-column layout, ~150px cards with an overlaid label) rather than the
   taller image+info-block style Hot Hits/My Songs use — scoped to
   .station-wall so those other views are unaffected. */
.station-wall {
  grid-template-columns: repeat(4, 1fr) !important;
}

.ps-radio-wall {
  grid-template-columns: repeat(4, 1fr) !important;
}

.ps-radio-tile {
  position: relative;
}

.ps-radio-badge {
  position: absolute;
  top: 10px;
  right: 10px;
  background: rgba(0,0,0,0.7);
  border: 1px solid var(--pink-bright);
  color: var(--pink-bright);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 1px;
  padding: 4px 8px;
  border-radius: 12px;
}

/* Station tiles are styled as preset buttons on a 90s car-stereo head
   unit — brushed-metal bezel, a tuner-strip accent, and an inset LCD
   readout for the name/format instead of a plain photo-with-caption tile,
   matching the look of the dedicated Car Stereo mode. */
.station-wall .station-tile {
  height: auto;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 9px;
  border-radius: 10px;
  border: 2px solid #050505;
  background: linear-gradient(180deg, #3a3a3e 0%, #1c1c1f 10%, #0a0a0c 100%);
  box-shadow: 0 12px 26px rgba(0,0,0,0.6), inset 0 2px 3px rgba(255,255,255,0.12), inset 0 0 0 1px rgba(255,255,255,0.05);
}

.station-wall .station-tile::before {
  /* tuner frequency-scale accent along the top edge */
  content: "";
  position: absolute;
  top: 0;
  left: 10px;
  right: 10px;
  height: 3px;
  background: linear-gradient(90deg, var(--pink), var(--gold), var(--cyan));
  border-radius: 0 0 2px 2px;
  z-index: 2;
}

.station-wall .station-tile img {
  /* A fixed square keeps every logo fully visible regardless of its own
     source dimensions — the previous wide/short crop area was slicing
     most station logos down to a thin horizontal sliver under
     object-fit: cover. Logos are typically supplied on a white square
     canvas, so a white backing avoids gaps for non-square source files. */
  position: static;
  width: 100%;
  aspect-ratio: 1;
  object-fit: contain;
  background: #fff;
  border-radius: 4px;
  border: 1px solid #000;
}

.station-wall .station-tile .info {
  position: relative;
  z-index: 1;
  width: 100%;
  height: 42px;
  margin: 0;
  padding: 4px 10px;
  background:
    repeating-linear-gradient(180deg, rgba(0,0,0,0.18) 0px 1px, transparent 1px 3px),
    linear-gradient(180deg, #0d1f0d, #061206);
  border: 1px solid #000;
  border-radius: 3px;
  box-shadow: inset 0 2px 6px rgba(0,0,0,0.8);
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.station-wall .station-tile .title {
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.3px;
  color: #3ef77a;
  text-shadow: 0 0 6px rgba(62,247,122,0.7);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.station-wall .station-tile .format {
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 0.3px;
  color: #2a8f52;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.favorite-heart {
  position: absolute;
  top: 4px;
  right: 4px;
  background: rgba(6, 6, 8, 0.75);
  border: none;
  border-radius: 50%;
  width: 32px;
  height: 32px;
  font-size: 17px;
  cursor: pointer;
  color: var(--cream-dim);
}

.favorite-heart.active { color: var(--pink-bright); }

/* ================= Right sidebar: Now Playing / Queue ================= */

.side-now-playing {
  background: linear-gradient(180deg, var(--surface-raised), var(--bg));
  border-left: 1px solid #221c14;
  padding: 18px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  overflow-y: auto;
  min-height: 0;
}

.np-panel, .up-next-panel {
  border: 1px solid var(--gold);
  border-radius: 14px;
  padding: 18px;
  background: linear-gradient(160deg, rgba(212,175,55,0.06), rgba(212,175,55,0.01));
  box-shadow: 0 14px 30px rgba(0,0,0,0.5), 0 0 22px rgba(212,175,55,0.1);
}

.np-heading {
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--gold-bright);
  text-align: center;
  margin: 0 0 12px;
}

.np-empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: 22px 8px 18px;
}

.np-empty-icon {
  font-size: 30px;
  color: var(--gold);
  opacity: 0.55;
  text-shadow: 0 0 16px rgba(212,175,55,0.35);
  margin-bottom: 10px;
  animation: npEmptyPulse 3s ease-in-out infinite;
}

@keyframes npEmptyPulse {
  0%, 100% { opacity: 0.35; transform: scale(1); }
  50% { opacity: 0.7; transform: scale(1.08); }
}

.np-empty-title {
  font-family: var(--font-title);
  font-size: 17px;
  font-weight: 600;
  color: var(--cream-dim);
}

.np-empty-sub {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--gold);
  opacity: 0.7;
  margin-top: 4px;
}

.np-hero {
  display: flex;
  gap: 12px;
  align-items: center;
}

.np-hero-art {
  width: 76px;
  height: 76px;
  border-radius: 10px;
  object-fit: cover;
  border: 2px solid var(--gold);
  box-shadow: 0 8px 20px rgba(0,0,0,0.5), 0 0 16px rgba(212,175,55,0.4);
  background: var(--surface);
}

.np-hero-meta { min-width: 0; }

.np-hero-title {
  font-size: 18px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.np-hero-artist {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--pink-bright);
  margin-top: 2px;
}

.np-hero-album {
  font-family: var(--font-title);
  font-style: italic;
  font-size: 13px;
  color: var(--cream-dim);
  margin-top: 2px;
}

.np-shuffle-badge {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.5px;
  color: var(--gold-bright);
  margin-top: 6px;
}

.np-progress-wrap {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 14px;
}

.np-time {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--cream-dim);
  flex-shrink: 0;
}

.np-progress-track {
  flex: 1;
  height: 4px;
  background: #2a231a;
  border-radius: 2px;
  overflow: visible;
  position: relative;
}

.np-progress-fill {
  height: 100%;
  width: 0%;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--pink-bright), var(--gold-bright));
  box-shadow: 0 0 8px rgba(255,45,149,0.6);
  transition: width 0.5s linear;
  position: relative;
}

.np-progress-fill::after {
  content: "";
  position: absolute;
  right: -4px;
  top: 50%;
  transform: translateY(-50%);
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--gold-bright);
  box-shadow: 0 0 10px rgba(232,189,111,0.8);
}

.np-controls-row {
  display: flex;
  justify-content: center;
  gap: 12px;
  margin-top: 14px;
}

.np-btn {
  background: transparent;
  border: 1px solid var(--gold);
  color: var(--gold-bright);
  border-radius: 50%;
  width: 38px;
  height: 38px;
  font-size: 16px;
  cursor: pointer;
}

.np-btn:active { background: var(--gold); color: var(--bg); }

.up-next-list { display: flex; flex-direction: column; gap: 10px; margin-bottom: 12px; }

.up-next-item {
  display: flex;
  align-items: center;
  gap: 10px;
}

.up-next-item img {
  width: 36px;
  height: 36px;
  border-radius: 5px;
  object-fit: cover;
  border: 1px solid #2a231a;
  flex-shrink: 0;
}

.up-next-meta { flex: 1; min-width: 0; }

.up-next-title {
  font-size: 14px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.up-next-artist {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--cream-dim);
}

.up-next-req {
  font-family: var(--font-mono);
  font-size: 11px;
  text-align: right;
  color: var(--cream-dim);
  flex-shrink: 0;
}

.up-next-req span {
  display: block;
  color: var(--gold-bright);
}

.up-next-empty {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--cream-dim);
  text-align: center;
  padding: 8px 0;
}

.up-next-more {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 1px;
  color: var(--gold);
  opacity: 0.75;
  text-align: center;
  padding: 6px 0 2px;
}

.view-queue-btn {
  width: 100%;
  background: transparent;
  border: 1px solid #3a3226;
  color: var(--cream-dim);
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.5px;
  padding: 9px 12px;
  border-radius: 6px;
  cursor: pointer;
  display: flex;
  justify-content: space-between;
}

.add-song-cta {
  border: 2px solid var(--pink-bright);
  border-radius: 14px;
  background: linear-gradient(160deg, rgba(255,45,149,0.10), rgba(255,45,149,0.02));
  padding: 16px 18px;
  display: flex;
  align-items: center;
  gap: 12px;
  cursor: pointer;
  animation: ctaPulse 2.4s ease-in-out infinite;
  box-shadow: 0 14px 30px rgba(0,0,0,0.5);
}

.coin-icon {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, var(--gold-bright), var(--gold) 70%);
  color: var(--bg);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 800;
  font-size: 18px;
  flex-shrink: 0;
  box-shadow: 0 0 10px rgba(212,175,55,0.6);
}

.add-song-text {
  font-family: var(--font-mono);
  font-size: 15px;
  color: var(--gold-bright);
  letter-spacing: 0.5px;
  text-align: left;
  line-height: 1.5;
}

.add-song-sub {
  font-size: 11px;
  color: var(--cyan-bright);
}

.start-here-badge {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--pink-bright);
  border: 1px solid var(--pink-bright);
  border-radius: 14px;
  padding: 5px 10px;
  flex-shrink: 0;
}

.genre-songs-section {
  margin-top: 28px;
}

/* ---------------- Featured (Top 20 this month, N years ago) ---------------- */

.featured-decade-block {
  margin-bottom: 32px;
}

.featured-decade-heading {
  font-family: var(--font-mono);
  font-size: 14px;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--gold-bright);
  margin: 0 0 10px;
  padding-bottom: 8px;
  border-bottom: 1px solid #241d16;
}

.featured-decade-month {
  color: var(--cream-dim);
  letter-spacing: 1px;
  text-transform: none;
  font-weight: normal;
}

.featured-decade-banner {
  display: block;
  width: 100%;
  max-width: 320px;
  margin: 0 auto;
  border-radius: 12px;
  box-shadow: 0 12px 28px rgba(0,0,0,0.55), 0 0 0 1px rgba(212,175,55,0.15);
}

.featured-decade-month-label {
  text-align: center;
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 1px;
  color: var(--cream-dim);
  margin: 10px 0 18px;
}

.featured-decade-list {
  display: flex;
  flex-direction: column;
}

.genre-songs-header-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 12px;
  padding-bottom: 8px;
  border-bottom: 1px solid #241d16;
}

.genre-songs-heading {
  font-family: var(--font-mono);
  font-size: 14px;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--gold-bright);
  margin: 0;
  flex-shrink: 0;
}

.genre-songs-filter {
  font-family: var(--font-title);
  font-size: 18px;
  padding: 6px 12px;
  background: var(--bg);
  border: 1px solid #3a3226;
  border-radius: 20px;
  color: var(--cream);
  width: 200px;
  max-width: 45vw;
}

.genre-songs-filter:focus {
  outline: none;
  border-color: var(--pink-bright);
}

.genre-songs-header-actions {
  display: flex;
  align-items: center;
  gap: 10px;
}

.shuffle-list-btn {
  background: var(--pink-bright);
  color: #1a0510;
  border: none;
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 0.5px;
  padding: 7px 16px;
  border-radius: 20px;
  cursor: pointer;
  white-space: nowrap;
  box-shadow: 0 4px 14px rgba(255,45,149,0.35);
}

.shuffle-list-btn:active { transform: scale(0.96); }

.shuffle-list-btn-standalone {
  display: inline-block;
  margin: 4px 0 14px;
}

.multi-select-toggle-btn {
  background: transparent;
  border: 1px solid var(--cyan);
  color: var(--cyan-bright);
  font-family: var(--font-mono);
  font-size: 13px;
  padding: 6px 14px;
  border-radius: 20px;
  cursor: pointer;
  white-space: nowrap;
}

.multi-select-toggle-btn.active {
  background: var(--cyan);
  color: var(--bg);
}

.multi-select-bulk-btn {
  width: 100%;
  background: var(--pink-bright);
  color: #1a0510;
  border: none;
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: 15px;
  padding: 12px;
  border-radius: 8px;
  cursor: pointer;
  margin-bottom: 14px;
}

.genre-song-checkbox {
  width: 20px;
  height: 20px;
  accent-color: var(--pink-bright);
  cursor: pointer;
  flex-shrink: 0;
}

.genre-songs-list {
  display: flex;
  flex-direction: column;
}

.genre-song-row {
  position: relative;
  padding: 8px 6px;
}

.genre-song-row .favorite-heart {
  position: static;
  flex-shrink: 0;
  margin-left: 4px;
  background: transparent;
}

/* ================= River Top 25 chart ================= */
/* Namespaced .rc-* throughout — .queue-btn/.genre-song-art/etc. above
   are reused as-is (not redefined), see CLAUDE.md's note on the
   .queue-btn/.search-queue-btn collision bug for why a new row style
   gets its own prefix instead of extending an existing button class. */

.rc-header-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}

.rc-month-picker {
  background: var(--surface-raised, #1a1610);
  color: var(--cream, #f2ece0);
  border: 1px solid var(--gold);
  border-radius: 20px;
  font-family: var(--font-mono);
  font-size: 13px;
  padding: 6px 14px;
}

.rc-actions-row {
  display: flex;
  gap: 10px;
  margin: 10px 0 14px;
}

.rc-play-all-btn {
  background: var(--cyan);
  color: var(--bg);
  border: none;
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 0.5px;
  padding: 7px 16px;
  border-radius: 20px;
  cursor: pointer;
  white-space: nowrap;
}

.rc-play-all-btn:active { transform: scale(0.96); }
.rc-play-all-btn:disabled,
.rc-actions-row .shuffle-list-btn:disabled {
  opacity: 0.4;
  cursor: default;
}

.rc-status {
  color: var(--cream-dim);
  font-family: var(--font-mono);
  font-size: 14px;
  padding: 12px 4px;
}

.rc-row {
  position: relative;
}

.rc-row .favorite-heart {
  position: static;
  flex-shrink: 0;
  margin-left: 4px;
  background: transparent;
}

.rc-rank {
  width: 26px;
  flex-shrink: 0;
  text-align: center;
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: 15px;
  color: var(--gold-bright);
}

.rc-move {
  flex-shrink: 0;
  min-width: 40px;
  text-align: center;
}

.rc-badge {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 700;
  padding: 2px 6px;
  border-radius: 10px;
  white-space: nowrap;
}

.rc-badge-up { color: #4ade80; }
.rc-badge-down { color: #f87171; }
.rc-badge-new {
  background: var(--pink-bright);
  color: #1a0510;
}

.genre-song-art {
  width: 42px;
  height: 42px;
  border-radius: 6px;
  object-fit: cover;
  border: 1px solid #2a231a;
  flex-shrink: 0;
  cursor: pointer;
}

.genre-song-meta {
  flex: 1;
  min-width: 0;
  cursor: pointer;
}

.genre-song-title {
  font-size: 16px;
  font-weight: 600;
  color: var(--cream);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.genre-song-artist {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--gold-bright);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ================= Volume slider ================= */

.volume-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 14px;
}

.volume-icon {
  font-size: 16px;
  color: var(--gold-bright);
  flex-shrink: 0;
}

.volume-value {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--gold-bright);
  min-width: 32px;
  text-align: right;
  flex-shrink: 0;
}

.volume-slider {
  flex: 1;
  -webkit-appearance: none;
  height: 4px;
  border-radius: 2px;
  background: #2a231a;
  outline: none;
}

.volume-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--gold-bright);
  box-shadow: 0 0 8px rgba(212,175,55,0.7);
  cursor: pointer;
}

.volume-slider::-moz-range-thumb {
  width: 14px;
  height: 14px;
  border: none;
  border-radius: 50%;
  background: var(--gold-bright);
  box-shadow: 0 0 8px rgba(212,175,55,0.7);
  cursor: pointer;
}

.big-volume-row {
  width: min(320px, 70%);
  margin-top: 18px;
}

/* ================= Screen-stay-awake fallback video ================= */
/* Deliberately NOT display:none — several browsers/WebViews pause (and
   some fully unload) video playback for display:none elements, which
   would defeat the entire point. Kept in-layout but visually and
   interactively invisible instead: 1x1, zero opacity, no pointer events,
   tucked in a corner so it can't affect layout even at that size. */
.keep-awake-video, #keepAwakeVideo {
  position: fixed;
  bottom: 0;
  right: 0;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
  z-index: -1;
}

/* ================= Toast ================= */

.toast {
  position: fixed;
  bottom: 28px;
  left: 50%;
  transform: translateX(-50%) translateY(20px);
  background: var(--surface-raised);
  border: 1px solid var(--pink-bright);
  color: var(--cream);
  font-family: var(--font-mono);
  font-size: 15px;
  padding: 12px 22px;
  border-radius: 10px;
  box-shadow: 0 10px 30px rgba(0,0,0,0.6), 0 0 20px rgba(255,45,149,0.3);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s ease, transform 0.25s ease;
  z-index: 400;
  max-width: 70vw;
  text-align: center;
}

.toast.visible {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

/* ================= Queue row actions (remove/reorder) ================= */

.queue-row-actions {
  display: flex;
  gap: 4px;
  flex-shrink: 0;
}

.queue-row-btn {
  background: transparent;
  border: 1px solid #3a3226;
  color: var(--cream-dim);
  border-radius: 4px;
  width: 26px;
  height: 26px;
  font-size: 14px;
  cursor: pointer;
}

.queue-row-btn:hover { border-color: var(--gold); color: var(--gold-bright); }
.queue-row-btn.remove-btn:hover { border-color: var(--pink-bright); color: var(--pink-bright); }
.queue-row-btn.play-now-btn { border-color: var(--cyan); color: var(--cyan-bright); }
.queue-row-btn.play-now-btn:hover { background: var(--cyan); color: var(--bg); }
.queue-row-btn.play-next-btn {
  border-color: var(--gold);
  color: var(--gold-bright);
  width: auto;
  padding: 0 8px;
  font-size: 11px;
  font-family: var(--font-mono);
  font-weight: 700;
}
.queue-row-btn.play-next-btn:hover { background: var(--gold); color: var(--bg); }

.queue-duration-estimate {
  font-family: var(--font-mono);
  font-size: 14px;
  color: var(--gold-bright);
  margin: -6px 0 14px;
}

/* ================= Recap / Admin PIN / Admin Panel ================= */

.recap-panel, .admin-pin-panel, .admin-panel {
  flex-direction: column;
  width: min(480px, 90vw);
  align-items: stretch;
}

.recap-title {
  font-size: 24px;
  color: var(--gold-bright);
  margin: 0 0 18px;
  text-align: center;
}

.recap-stat-row {
  display: flex;
  justify-content: space-between;
  padding: 10px 4px;
  border-bottom: 1px solid #241d16;
  font-family: var(--font-mono);
  font-size: 15px;
}

.recap-stat-label { color: var(--cream-dim); }
.recap-stat-value { color: var(--gold-bright); font-weight: 600; }

.recap-top-list { margin-top: 16px; }

.recap-top-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 4px;
  cursor: pointer;
  border-radius: 6px;
}

.recap-top-item:hover { background: rgba(255, 45, 149, 0.08); }

.recap-top-item img {
  width: 38px;
  height: 38px;
  border-radius: 5px;
  object-fit: cover;
  border: 1px solid var(--gold);
}

.recap-rank {
  font-family: var(--font-mono);
  color: var(--pink-bright);
  font-weight: 700;
  width: 20px;
}

.admin-pin-input {
  font-family: var(--font-mono);
  font-size: 22px;
  letter-spacing: 4px;
  text-align: center;
  padding: 14px;
  background: var(--bg);
  border: 1px solid var(--gold);
  border-radius: 8px;
  color: var(--cream);
  margin-bottom: 14px;
}

.admin-pin-submit {
  background: var(--gold);
  color: var(--bg);
  border: none;
  font-family: var(--font-mono);
  font-weight: 700;
  padding: 12px;
  border-radius: 8px;
  cursor: pointer;
}

.admin-pin-error {
  color: var(--pink-bright);
  font-family: var(--font-mono);
  font-size: 14px;
  text-align: center;
  margin-top: 10px;
}

.admin-action-btn {
  background: transparent;
  border: 1px solid var(--gold);
  color: var(--gold-bright);
  font-family: var(--font-mono);
  font-size: 15px;
  padding: 14px;
  border-radius: 8px;
  cursor: pointer;
  margin-bottom: 12px;
}

.admin-action-btn.admin-danger {
  border-color: var(--pink-bright);
  color: var(--pink-bright);
}

.admin-debug-row {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--cream-dim);
  border-top: 1px solid rgba(212,175,55,0.2);
  padding-top: 10px;
  margin-top: 6px;
}

.admin-debug-value { color: var(--gold-bright); text-align: right; }

/* ================= Guest name picker ================= */

.guest-name-input-row {
  display: flex;
  gap: 8px;
  margin-bottom: 16px;
}

.guest-name-input {
  flex: 1;
  font-family: var(--font-title);
  font-size: 18px;
  padding: 12px 14px;
  background: var(--bg);
  border: 1px solid var(--gold);
  border-radius: 8px;
  color: var(--cream);
}

.guest-name-go-btn {
  background: var(--pink-bright);
  color: #1a0510;
  border: none;
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: 15px;
  padding: 0 20px;
  border-radius: 8px;
  cursor: pointer;
}

.guest-name-prev-label {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--cream-dim);
  margin-bottom: 10px;
}

.guest-name-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 16px;
  max-height: 220px;
  overflow-y: auto;
}

.guest-name-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  border: 1px solid #3a3226;
  border-radius: 8px;
  padding: 10px 12px;
  cursor: pointer;
}

.guest-name-row:hover { border-color: var(--gold); }

.guest-name-row-label {
  font-family: var(--font-title);
  font-size: 16px;
  color: var(--cream);
}

.guest-name-row-delete {
  background: rgba(255, 45, 149, 0.08);
  border: 1px solid var(--pink-bright);
  color: var(--pink-bright);
  border-radius: 6px;
  width: 30px;
  height: 30px;
  font-size: 20px;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
  flex-shrink: 0;
}

.guest-name-row-delete:hover,
.guest-name-row-delete:active {
  background: var(--pink-bright);
  color: #1a0510;
}

/* ================= Album track picker ================= */

.album-picker-header {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 16px;
}

.album-picker-header img {
  width: 64px;
  height: 64px;
  border-radius: 8px;
  object-fit: cover;
  border: 1px solid var(--gold);
  flex-shrink: 0;
}

.album-picker-title {
  font-family: var(--font-title);
  font-size: 18px;
  font-weight: 600;
  color: var(--cream);
}

.album-picker-artist {
  font-family: var(--font-mono);
  font-size: 14px;
  color: var(--pink-bright);
  margin-top: 2px;
}

.album-picker-track-list {
  max-height: 320px;
  overflow-y: auto;
  margin-top: 6px;
}

.album-picker-track-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 4px;
  border-bottom: 1px solid #241d16;
  cursor: pointer;
}

.album-picker-track-row:hover { background: rgba(255, 45, 149, 0.06); }

.album-picker-track-num {
  font-family: var(--font-mono);
  color: var(--gold);
  width: 22px;
  flex-shrink: 0;
}

.album-picker-track-title {
  flex: 1;
  min-width: 0;
  font-size: 15px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.album-picker-track-fav {
  position: static;
  flex-shrink: 0;
  margin-right: 8px;
  background: transparent;
}

/* ================= Idle screensaver ================= */

.screensaver {
  display: none;
  position: fixed;
  inset: 0;
  background: #000;
  z-index: 300;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 20px 0;
  overflow-y: auto;
}

.screensaver.active { display: flex; }

.screensaver-marquee {
  display: flex;
  align-items: baseline;
  gap: 16px;
  margin-bottom: 22px;
}

.screensaver-p {
  font-family: 'Kaushan Script', cursive;
  font-size: 92px;
  color: #fff;
  text-shadow: 0 0 4px #fff, 0 0 10px #ff2d55, 0 0 24px #ff2d55, 0 0 44px #d4004a;
  animation: neonPFlicker 7s linear infinite;
}

.screensaver-p span { color: #fff; }

.screensaver-sub {
  font-family: 'Monoton', cursive;
  font-size: 38px;
  letter-spacing: 8px;
  color: #fff;
  text-shadow: 0 0 3px #fff, 0 0 10px var(--cyan-bright), 0 0 22px var(--cyan);
}

.screensaver-art {
  width: min(380px, 42vh);
  height: min(380px, 42vh);
  border-radius: 20px;
  object-fit: cover;
  border: 4px solid var(--gold);
  box-shadow: 0 0 70px rgba(212,175,55,0.4);
  transition: opacity 0.6s ease;
}

.screensaver-now-playing {
  margin-top: 18px;
  text-align: center;
}

.screensaver-np-label {
  font-family: var(--font-mono);
  font-size: 17px;
  letter-spacing: 4px;
  color: var(--gold-bright);
  text-shadow: 0 0 8px rgba(212,175,55,0.5);
  margin-bottom: 6px;
}

.screensaver-np-title {
  font-family: var(--font-title);
  font-size: 40px;
  font-weight: 600;
  color: #fff;
}

.screensaver-np-artist {
  font-family: var(--font-mono);
  font-size: 21px;
  color: var(--pink-bright);
  margin-top: 4px;
}

.screensaver-progress-wrap {
  display: flex;
  align-items: center;
  gap: 16px;
  width: min(560px, 65vw);
  margin: 14px auto 0;
}

.screensaver-progress-track {
  height: 5px;
}

.screensaver-np-time {
  font-size: 14px;
  min-width: 32px;
}

.screensaver-hint {
  margin-top: 16px;
  font-family: var(--font-mono);
  font-size: 14px;
  letter-spacing: 2px;
  color: var(--cream-dim);
}

/* ================= Overlays ================= */

.detail-overlay {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.8);
  z-index: 60;
  align-items: center;
  justify-content: center;
}

.detail-overlay.open { display: flex; }

.detail-panel {
  background: var(--surface-raised);
  border: 1px solid var(--gold);
  border-radius: 10px;
  width: min(720px, 92vw);
  max-height: 85vh;
  overflow-y: auto;
  display: flex;
  padding: 24px;
  gap: 24px;
  box-shadow: 0 0 40px rgba(255,45,149,0.15);
}

.queue-detail-panel { flex-direction: column; }

.detail-panel img {
  width: 220px;
  height: 220px;
  object-fit: cover;
  border-radius: 8px;
  border: 2px solid var(--gold);
  flex-shrink: 0;
}

.detail-meta h2 {
  font-size: 24px;
  margin: 0 0 4px;
  color: var(--gold-bright);
}

.detail-meta .artist-line {
  font-family: var(--font-mono);
  font-size: 15px;
  color: var(--cream-dim);
  margin-bottom: 18px;
}

.track-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 8px;
  border-radius: 6px;
  cursor: pointer;
  justify-content: space-between;
}

.track-row:hover { background: rgba(255, 45, 149, 0.08); }

.track-code {
  font-family: var(--font-mono);
  font-size: 15px;
  color: var(--bg);
  background: var(--gold-bright);
  padding: 3px 8px;
  border-radius: 3px;
  font-weight: 500;
  box-shadow: 0 0 8px rgba(212, 175, 55, 0.4);
}

.track-title { font-size: 17px; }

.queue-btn {
  font-family: var(--font-mono);
  background: transparent;
  border: 1px solid var(--gold);
  color: var(--gold-bright);
  border-radius: 4px;
  font-size: 20px;
  width: 40px;
  height: 40px;
  cursor: pointer;
  flex-shrink: 0;
}

.queue-btn:active { background: var(--gold); color: var(--bg); }

.close-detail {
  position: absolute;
  top: 16px;
  right: 16px;
  background: transparent;
  border: none;
  color: var(--cream-dim);
  font-size: 24px;
  cursor: pointer;
}

.full-queue-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 4px;
  border-bottom: 1px solid #241d16;
}

.full-queue-row img {
  width: 44px;
  height: 44px;
  border-radius: 6px;
  object-fit: cover;
  border: 1px solid var(--gold);
}

.full-queue-empty {
  font-family: var(--font-mono);
  color: var(--cream-dim);
  text-align: center;
  padding: 20px 0;
}

/* ================= Footer ticker ================= */

.ticker {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 10px 20px;
  background: linear-gradient(180deg, var(--bg), var(--surface));
  border-top: 1px solid var(--gold);
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 1px;
  color: var(--cream-dim);
}

.ticker .invader { font-size: 18px; }

/* ================= 90s Car Stereo mode ================= */

.mode-toggle-row {
  display: flex;
  flex-direction: row;
  gap: 10px;
}

.car-stereo-toggle-btn {
  background: transparent;
  border: 1px solid var(--gold);
  color: var(--gold-bright);
  border-radius: 50%;
  width: 40px;
  height: 40px;
  font-size: 20px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  line-height: 1;
}
.car-stereo-toggle-btn:hover { background: var(--gold); color: var(--bg); }

.mode-toggle-icon {
  width: 21px;
  height: 21px;
}


.car-stereo-overlay {
  display: none;
  position: fixed;
  inset: 0;
  background: #050505;
  z-index: 350;
  align-items: center;
  justify-content: center;
  padding: 20px;
}

/* Always-visible, guaranteed-tappable exit — pinned to the overlay's own
   corner (not the photo unit), so it works regardless of how little
   backdrop margin is left around the unit on any given screen. Backdrop
   tap is a nice-to-have; this is the reliable way out. */
.overlay-close-btn {
  position: absolute;
  top: 18px;
  right: 18px;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: rgba(5,5,5,0.75);
  border: 1px solid var(--pink-bright);
  color: var(--pink-bright);
  font-size: 18px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  z-index: 10;
  box-shadow: 0 0 14px rgba(255,45,149,0.5);
}
.overlay-close-btn:active { transform: scale(0.94); }
.car-stereo-overlay.active { display: flex; }

.car-stereo-unit {
  /* Same fill-the-screen approach as Boom Box — whichever of width/height
     is tighter wins, using the photo's real aspect ratio (1774:887 = 2:1,
     unchanged by the 2026-09 photo swap below — the new composite happens
     to be the same file dimensions as the old tight crop). On the
     portrait-mounted kiosk, vh dwarfs vw, so width stays the binding
     constraint and this fills nearly the full screen width. */
  width: min(97vw, calc(94vh * 2.0));
  position: relative;
  border-radius: 10px;
  overflow: hidden;
  box-shadow: 0 30px 80px rgba(0,0,0,0.7);
  line-height: 0; /* kill the inline-img baseline gap so the unit hugs the photo exactly */
}

.cs-photo {
  display: block;
  width: 100%;
  height: auto;
  pointer-events: none;
  -webkit-user-drag: none;
}

/* Invisible hit-zones layered on top of the photo's real buttons — sized
   and positioned in % of the unit so they track the photo at any scale.
   Coordinates were re-measured against the current photo,
   images/car-stereo/psr-9400-collection.webp (2026-09), by scanning a
   percentage grid overlaid on the actual image rather than eyeballing a
   screenshot — see the equivalent Boom Box reel-alignment fix for why
   that distinction matters. If this file is ever replaced with a
   different crop/framing, these will need re-tuning against the new one. */
.cs-hotspot {
  position: absolute;
  background: transparent;
  border: none;
  padding: 0;
  margin: 0;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.cs-hotspot-eject { left: 61.3%; top: 35.0%; width: 4.0%; height: 5.2%; }
.cs-hotspot-rew   { left: 32.2%; top: 62.5%; width: 5.8%; height: 6.5%; }
.cs-hotspot-ff    { left: 39.0%; top: 62.5%; width: 5.0%; height: 6.5%; }
.cs-hotspot-play  { left: 44.6%; top: 62.5%; width: 10.7%; height: 6.5%; }
.cs-hotspot-tuneseek { left: 61.3%; top: 54.9%; width: 4.0%; height: 5.1%; }

.cs-hotspot-knob {
  left: 20.7%;
  top: 43.0%;
  width: 10.6%;
  /* Explicit height instead of aspect-ratio: 1 — this is a plain div, not
     an <img>, so unlike the tile images elsewhere it has no intrinsic
     size to fall back on if aspect-ratio isn't supported (older Android
     WebViews in particular) — it would silently collapse to zero height.
     The knob also just doesn't measure as a perfect circle in this photo
     (width% and height% aren't a 1:2 ratio matching the image's own 2:1
     aspect) — shot at a slight angle, same real effect seen on the Boom
     Box's cassette hubs, not a measurement bug worth "fixing" to be
     circular. */
  height: 15.6%;
  border-radius: 50%;
  cursor: grab;
  touch-action: none;
}
.cs-hotspot-knob:active { cursor: grabbing; }

/* A thin synthetic indicator overlaid on the (static, photographed) knob
   so volume level still reads visually, like a painted position mark on
   a real knob. */
.cs-knob-indicator {
  position: absolute;
  top: 8%;
  left: 50%;
  width: 6%;
  height: 28%;
  background: linear-gradient(180deg, #f0f0f0, #a0a0a0);
  box-shadow: 0 0 5px rgba(255,255,255,0.75);
  border-radius: 3px;
  transform-origin: 50% 140%;
  transform: translateX(-50%) rotate(-135deg);
  pointer-events: none;
}

.cs-vol-slider-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

.cs-lcd-overlay {
  position: absolute;
  left: 37.4%;
  top: 44.3%;
  width: 21.5%;
  height: 12.9%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 2%;
  padding: 0 3%;
  pointer-events: none;
  overflow: hidden;
  line-height: normal; /* .car-stereo-unit sets line-height:0 to remove the
    photo's inline baseline gap — reset it here so it doesn't inherit down
    and collapse every text row in this overlay to near-zero height. */
}

.cs-eq-bars {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: 5px;
  height: 20px;
}
.cs-eq-bars span {
  width: 5px;
  height: 20%;
  background: #9fd88a;
  box-shadow: 0 0 5px rgba(159,216,138,0.7);
  border-radius: 1px;
  animation: csEqBounce 1s ease-in-out infinite;
  animation-play-state: paused;
}
.cs-eq-bars.playing span { animation-play-state: running; }
.cs-eq-bars span:nth-child(1) { animation-delay: 0s; }
.cs-eq-bars span:nth-child(2) { animation-delay: 0.1s; }
.cs-eq-bars span:nth-child(3) { animation-delay: 0.2s; }
.cs-eq-bars span:nth-child(4) { animation-delay: 0.3s; }
.cs-eq-bars span:nth-child(5) { animation-delay: 0.15s; }
.cs-eq-bars span:nth-child(6) { animation-delay: 0.25s; }
.cs-eq-bars span:nth-child(7) { animation-delay: 0.05s; }
.cs-eq-bars span:nth-child(8) { animation-delay: 0.35s; }
@keyframes csEqBounce { 0%, 100% { height: 15%; } 50% { height: 100%; } }

.cs-marquee-wrap {
  overflow: hidden;
  white-space: nowrap;
}

.cs-marquee-text {
  display: inline-block;
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: clamp(10px, 1.6vw, 20px);
  letter-spacing: 1px;
  color: #9dff7a;
  text-shadow: 0 0 6px rgba(157,255,122,0.85), 0 0 14px rgba(157,255,122,0.4);
}

.cs-artist {
  font-family: var(--font-mono);
  font-size: clamp(8px, 1.1vw, 13px);
  letter-spacing: 0.5px;
  color: #7fe85f;
  text-shadow: 0 0 4px rgba(127,232,95,0.6);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.cs-time-row {
  display: flex;
  align-items: center;
  gap: 3%;
  font-family: var(--font-mono);
  font-size: clamp(7px, 1vw, 11px);
  color: #7fe85f;
  text-shadow: 0 0 4px rgba(127,232,95,0.6);
}

.cs-progress-track {
  flex: 1;
  height: 3px;
  background: rgba(157,255,122,0.2);
  border-radius: 2px;
  overflow: hidden;
}

.cs-progress-fill {
  height: 100%;
  background: #9dff7a;
  box-shadow: 0 0 5px rgba(157,255,122,0.8);
  width: 0%;
}

/* Pixel-measured directly against images/car-stereo/psr-9400-collection.webp
   (2026-09) — a percentage grid overlaid on the actual photo and read off
   directly, not eyeballed from a screenshot of the rendered page. */
.cs-preset-row {
  position: absolute;
  left: 66.43%;
  top: 43.2%;
  width: 15.46%;
  height: 17.02%;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: repeat(2, 1fr);
  gap: 11.75% 3.9%;
}

.cs-preset-btn {
  position: relative;
  background: transparent;
  border: none;
  padding: 0;
  margin: 0;
  cursor: pointer;
  border-radius: 4px;
  -webkit-tap-highlight-color: transparent;
}

/* The small printed indicator dash under each preset number — lit up
   for whichever preset is active instead of ringing the whole button.
   Derived from the 8 printed dashes themselves, found by scanning the
   photo for their green pixels (centers x 68.1/72.15/76.18/80.13, y
   48.7/58.25 — a 4.03%/9.5% pitch) — an earlier pass measured one
   button by eye and got the button pitch wrong (4.5%), leaving the
   lit dashes a smidge off. The grid above uses that same pitch. */
.cs-preset-light {
  position: absolute;
  left: 34%;
  top: 70%;
  width: 30%;
  height: 8%;
  border-radius: 2px;
  background: transparent;
  pointer-events: none;
}

.cs-preset-btn.active .cs-preset-light {
  background: #3ef77a;
  box-shadow: 0 0 6px rgba(62,247,122,0.95), 0 0 14px rgba(62,247,122,0.7);
}

/* ---------------- Boom Box mode (regular-song ambient display) ---------------- */
/* Same real-photo-overlay approach as Car Stereo — reuses its shared LCD/
   knob classes (.cs-eq-bars, .cs-marquee-text, .cs-artist, .cs-time-row,
   .cs-progress-track/.cs-progress-fill, .cs-knob-indicator, .cs-hotspot,
   .cs-vol-slider-hidden) so the two skins stay visually/behaviorally
   consistent without duplicating CSS. Coordinates below were measured
   against images/boom-box/panasonic-stereo-rack.webp (1619×972) by
   overlaying a percentage grid with PIL and reading pixel bounds off it
   directly — same method as the reel/preset-light calibration notes
   elsewhere in this file, just script-generated instead of canvas-drawn.
   This full four-component rack (tuner/amp/dual-cassette/CD, flanked by
   real cassette and CD collections) replaced an earlier, simpler stereo
   photo. Both decks' reel hubs read as fully dark/closed at normal
   brightness — the spinning reel animation (see .bb-reel below) was
   nearly dropped for that reason, until a brightened/contrast-boosted
   crop revealed both decks do show real hub detail after all. */

.boom-box-overlay {
  display: none;
  position: fixed;
  inset: 0;
  background: #050505;
  z-index: 350;
  align-items: center;
  justify-content: center;
  padding: 10px;
}
.boom-box-overlay.active { display: flex; }

.boom-box-unit {
  /* Fill as much of the screen as the photo's fixed aspect ratio
     (1619:972 ≈ 1.666:1) allows — whichever of width/height is the
     tighter constraint wins. On a portrait-oriented screen (the actual
     kiosk mounting) vh dwarfs vw, so width is always the binding
     constraint — pushed close to the edge since the corner close button
     (not backdrop tap) is the guaranteed way out, so a large backdrop
     margin isn't load-bearing for being able to exit. */
  width: min(97vw, calc(94vh * 1.666));
  position: relative;
  border-radius: 6px;
  overflow: hidden;
  box-shadow: 0 30px 80px rgba(0,0,0,0.7);
  line-height: 0;
}

.bb-photo {
  display: block;
  width: 100%;
  height: auto;
  pointer-events: none;
  -webkit-user-drag: none;
}

/* Cassette reels — the deck doors read as fully dark/closed at normal
   brightness, but brightening+contrast-boosting a crop (same tool as the
   coordinate grids elsewhere in this file) reveals both decks actually
   do show their reel hubs; a first pass at this photo missed them and
   dropped the animation entirely. Same semi-transparent spinning cross
   pattern as before — a plain rotating circle reads as motionless
   regardless of speed since it's symmetric. */
.bb-reel {
  position: absolute;
  width: 3%;
  /* Explicit height instead of aspect-ratio: 1 — see .bb-hotspot-knob. The
     hub reads visibly non-circular in the photo (taller % than wide) only
     because this rack was shot at a slight angle, not because % width/
     height need any manual aspect correction — both are already plain
     percentages of the same element, so they map 1:1 onto the measured
     image-relative percentages below. */
  height: 3.2%;
  border-radius: 50%;
  background:
    linear-gradient(0deg, transparent 44%, rgba(0,0,0,0.5) 44% 56%, transparent 56%),
    linear-gradient(90deg, transparent 44%, rgba(0,0,0,0.5) 44% 56%, transparent 56%);
  pointer-events: none;
}
.bb-reel.spinning {
  animation: bbReelSpin 1.6s linear infinite;
}
@keyframes bbReelSpin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

/* Hub centers — the first pass at these (committed, then immediately
   reported as visibly misaligned) was read by eye off a brightened/
   gridded crop and trusted after only checking that the CSS rendered
   the numbers I'd written, never independently checking those numbers
   against the actual photo. Redone properly this time: a script scans
   each hub's brightened crop for the dark hole's pixel bounds directly
   (no eyeballing), then the resulting box was overlaid back onto the
   photo as a visible ellipse and visually confirmed to trace the real
   hub rim before committing. */
.bb-reel-a1 { left: 32.5%; top: 63.3%; }
.bb-reel-a2 { left: 41.5%; top: 63.4%; }
.bb-reel-b1 { left: 58.1%; top: 63.3%; }
.bb-reel-b2 { left: 65.6%; top: 63.4%; }

/* The tuner's own blank LCD glass, top-center of the rack. */
.bb-lcd-overlay {
  position: absolute;
  left: 33%;
  top: 8.2%;
  width: 32.5%;
  height: 12.2%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 1.5%;
  padding: 0 2.5%;
  pointer-events: none;
  overflow: hidden;
  line-height: normal;
}

.bb-lcd-overlay .cs-eq-bars {
  height: 14px;
}

/* The amplifier's VOLUME knob (second component down). Not a perfect
   circle in this photo's own pixels (slight camera angle/lens
   perspective on the whole rack shot) — explicit width/height instead
   of aspect-ratio: 1, same reasoning as Car Stereo's knob, matches the
   ellipse actually visible rather than forcing a geometric circle that
   would drift off the real knob. */
.bb-hotspot-knob {
  left: 68.9%;
  top: 32.2%;
  width: 9.5%;
  height: 12%;
  border-radius: 50%;
  cursor: grab;
  touch-action: none;
}
.bb-hotspot-knob:active { cursor: grabbing; }

/* Eject/exit = the CD player's own OPEN/CLOSE button (bottom component)
   — same "stop and go home" semantic as the old photo's eject button,
   just relocated to fit this rack's actual layout. Play/pause = the CD
   player's play triangle just below it; prev/next = the cassette deck's
   own transport arrows (third component) either side of its stop
   button, which is left unwired — same as this project's other skins,
   not every visible button needs a function. */
.bb-hotspot-eject { left: 66.3%; top: 86.1%; width: 8%; height: 2.6%; }
.bb-hotspot-play  { left: 73.3%; top: 90.2%; width: 6.2%; height: 6.6%; }
.bb-hotspot-prev  { left: 42.6%; top: 77%; width: 4.9%; height: 4.2%; }
.bb-hotspot-next  { left: 53.6%; top: 77%; width: 4.9%; height: 4.2%; }

/* This rack's tuner LCD is a plain dark glass with no inherent lit
   color (it's photographed off) — picked a warm amber/VFD look,
   authentic to real stereo tuner displays of this style and distinct
   from Car Stereo's green and iPod's white/blue. */
.bb-lcd-overlay .cs-marquee-text {
  color: #ffb84d;
  text-shadow: 0 0 6px rgba(255,184,77,0.85), 0 0 14px rgba(255,184,77,0.4);
}
.bb-lcd-overlay .cs-artist {
  color: #e0954a;
  text-shadow: 0 0 4px rgba(224,149,74,0.6);
}
.bb-lcd-overlay .cs-time-row {
  color: #e0954a;
  text-shadow: 0 0 4px rgba(224,149,74,0.6);
}
.bb-lcd-overlay .cs-progress-track {
  background: rgba(255,184,77,0.2);
}
.bb-lcd-overlay .cs-progress-fill {
  background: #ffb84d;
  box-shadow: 0 0 5px rgba(255,184,77,0.8);
}
.bb-lcd-overlay .cs-eq-bars span {
  background: #ffc97a;
  box-shadow: 0 0 5px rgba(255,201,122,0.7);
}

/* ================= iPod mode (mobile-only alternate skin) =================
   Same photo-plus-invisible-hotspots approach as Car Stereo/Boom Box, but
   built for mobile only — see the mobile-view overrides near the bottom
   of this file for how the toggle button/overlay are shown here instead
   of hidden. The reference photo (images/ipod/ipod-classic.png) already
   has demo Now Playing content baked into its screen; .ipod-screen-overlay
   is a fully opaque rectangle painted over that exact area so nothing of
   the original demo content shows through, then real Now Playing data is
   rendered on top in a light/dark theme matching an actual iPod's Now
   Playing screen (not the neon-LCD green look Car Stereo/Boom Box use —
   those are stylized period-correct car/boom-box displays, this is meant
   to look like a real iPod screen). */
.ipod-overlay {
  display: none;
  position: fixed;
  inset: 0;
  background: #050505;
  z-index: 350;
  align-items: center;
  justify-content: center;
  padding: 0;
  /* .ipod-unit is deliberately sized wider than the viewport below, so
     it can fill full height instead of letterboxing top/bottom — this
     clips the resulting horizontal overflow instead of letting it push
     out a scrollbar or shift the page. */
  overflow: hidden;
}
.ipod-overlay.active { display: flex; }

.ipod-unit {
  /* Second source photo (2026-09) — replaces the first, which had a
     real white background baked into its pixels that no CSS sizing
     could remove (see git history). This one is a clean 1024x1536
     (exactly 2:3, ~0.667:1) render with no border, full-bleed device.
     That ratio is still noticeably less elongated than a modern phone
     viewport (e.g. iPhone 16 Pro Max's ~0.46:1), so fitting the whole
     image within the viewport always left real black space above/below
     — filling height instead and letting the resulting width exceed
     100vw (clipped by .ipod-overlay's overflow:hidden, the same "cover"
     crop an <img object-fit:cover> would give) maximizes it properly.
     Deliberately not object-fit:cover on the <img> itself — that would
     shift the coordinate mapping every hotspot/screen-overlay percentage
     below is calibrated against; scaling the whole unit (image and
     hotspots together, still percentages of this same box) and clipping
     the overflow at the parent keeps all of that calibration valid. */
  width: calc(100vh * 0.667);
  flex-shrink: 0; /* otherwise flexbox shrinks this back down to fit the
    overlay's own width before overflow/clipping ever comes into play,
    silently undoing the whole point of sizing by height */
  position: relative;
  overflow: hidden;
  line-height: 0;
}

.ipod-photo {
  display: block;
  width: 100%;
  height: auto;
  pointer-events: none;
  -webkit-user-drag: none;
}

/* Coordinates hand-calibrated against images/ipod/ipod-classic.png —
   if that file is ever replaced with a different crop/framing, these
   will need re-tuning against the new one. */
.ipod-screen-overlay {
  /* Bounding box found via a brightness-threshold pixel scan against the
     second source photo (screen is a light gray/white rectangle against
     the near-black device body) — precise, not eyeballed. */
  position: absolute;
  left: 18.85%;
  top: 6.45%;
  width: 62.11%;
  height: 33.72%;
  background: #eef1f4;
  display: flex;
  flex-direction: column;
  padding: 3% 5%;
  line-height: normal;
  overflow: hidden;
}

.ipod-screen-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-family: -apple-system, BlinkMacSystemFont, sans-serif;
  font-weight: 700;
  color: #1a1a1a;
  font-size: clamp(9px, 2.6vw, 15px);
  margin-bottom: 4%;
}
.ipod-play-icon { color: #2f6fe0; font-size: 0.8em; }
.ipod-battery { color: #2f8f3f; }

.ipod-np-row {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4%;
  flex: 1;
  min-height: 0;
}

/* height-driven (not width-driven) so it fills as much of the screen's
   vertical space as the header/progress bar leave available, the way a
   real iPod Classic's Now Playing screen uses one large centered cover
   instead of a small thumbnail beside the text — that thumbnail was
   leaving most of the screen looking like flat, unauthentic blank space. */
.ipod-cover {
  width: auto;
  height: 100%;
  max-width: 78%;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: 2px;
  box-shadow: 0 1px 4px rgba(0,0,0,0.4);
  flex-shrink: 1;
  min-height: 0;
}

.ipod-np-text {
  min-width: 0;
  width: 100%;
  flex-shrink: 0;
  text-align: center;
}

.ipod-np-title {
  font-family: -apple-system, BlinkMacSystemFont, sans-serif;
  font-weight: 700;
  color: #111;
  font-size: clamp(9px, 2.4vw, 14px);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ipod-np-artist, .ipod-np-album {
  font-family: -apple-system, BlinkMacSystemFont, sans-serif;
  color: #444;
  font-size: clamp(8px, 2vw, 12px);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ipod-progress-track {
  height: 4px;
  background: rgba(0,0,0,0.15);
  border-radius: 2px;
  overflow: hidden;
  margin-top: 4%;
}
.ipod-progress-fill {
  height: 100%;
  background: #2f6fe0;
  width: 0%;
}

.ipod-time-row {
  display: flex;
  justify-content: space-between;
  font-family: -apple-system, BlinkMacSystemFont, sans-serif;
  color: #333;
  font-size: clamp(7px, 1.8vw, 11px);
  margin-top: 2%;
}

/* Transient volume readout, shown only while scrolling the click wheel
   (see wireIpodWheelVolume in app.js) — mirrors the brief on-screen
   volume HUD a real iPod shows while scrolling on the Now Playing
   screen, rather than a volume control that sits visible at all times. */
.ipod-volume-hud {
  display: none;
  align-items: center;
  gap: 3%;
  margin-top: 3%;
}
.ipod-volume-hud.visible { display: flex; }
.ipod-volume-hud-icon {
  font-size: clamp(9px, 2.2vw, 13px);
  flex-shrink: 0;
}
.ipod-volume-hud-track {
  flex: 1;
  height: 4px;
  background: rgba(0,0,0,0.15);
  border-radius: 2px;
  overflow: hidden;
}
.ipod-volume-hud-fill {
  height: 100%;
  background: #2f6fe0;
  width: 0%;
}

.ipod-hotspot {
  position: absolute;
  background: transparent;
  border: none;
  padding: 0;
  margin: 0;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  /* Without this, a real finger drag on a phone is claimed by the browser
     as a page scroll/pan and the pointer stream gets cancelled almost
     immediately, so the wheel's rotate-to-change-volume gesture never
     gets enough move events to register (mouse-driven testing hid this). */
  touch-action: none;
}

.ipod-hotspot-menu    { left: 35.25%; top: 51.30%; width: 29.30%; height: 10.55%; }
.ipod-hotspot-prev     { left: 24.71%; top: 61.85%; width: 19.24%; height: 8.79%; }
.ipod-hotspot-next     { left: 55.86%; top: 61.85%; width: 19.24%; height: 8.79%; }
.ipod-hotspot-select   { left: 44.53%; top: 62.63%; width: 10.74%; height: 7.16%; border-radius: 50%; }
.ipod-hotspot-playpause { left: 35.25%; top: 70.64%; width: 29.30%; height: 10.61%; }

/* ================= Persistent QR badges ================= */
/* Always-visible companions for the 90s Car Stereo/Boom Box overlays and
   the idle screensaver — same link as the header badge and the
   tap-to-open overlay, just pinned to whichever full-bleed screen is
   showing. Positioned relative to the overlay/screensaver itself (all
   three are position:fixed, which already establishes the containing
   block), in the opposite corner from the exit button so it never
   overlaps it. */
.qr-badge-corner {
  position: absolute;
  bottom: 18px;
  right: 18px;
  z-index: 10;
}

.qr-badge {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}

.qr-badge-code {
  background: var(--cream);
  padding: 6px;
  border-radius: 8px;
  border: 2px solid var(--gold);
  box-shadow: 0 0 16px rgba(212,175,55,0.4);
  line-height: 0;
}

.qr-badge-label {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 1.5px;
  line-height: 1.4;
  color: var(--gold-bright);
  text-align: center;
  text-shadow: 0 0 6px rgba(212,175,55,0.4);
}

/* ================= QR phone-companion overlay ================= */

.qr-panel {
  align-items: center;
  text-align: center;
}

.qr-code-wrap {
  background: var(--cream);
  padding: 16px;
  border-radius: 10px;
  border: 2px solid var(--gold);
  box-shadow: 0 0 22px rgba(212,175,55,0.25);
  display: inline-flex;
  align-self: center;
  margin: 4px 0 16px;
}

.qr-instructions {
  font-family: var(--font-mono);
  font-size: 14px;
  color: var(--cream-dim);
  line-height: 1.5;
}

.qr-instructions span {
  color: var(--gold-bright);
}

/* ================= Mobile companion view (?mobile=1 from a QR scan) =================
   Reuses all the same markup/IDs/JS as the kiosk — nav, search, guest
   name picker, genre/featured/radio/etc. browsing, Now Playing, Up Next
   — restyled into a single scrolling column with a horizontal nav strip
   instead of the desktop sidebar. Only the genuinely kiosk-only concepts
   stay hidden: Car Stereo/Boom Box (physical ambient displays nobody's
   phone needs), the screensaver, and their mode-toggle buttons. */

html.mobile-view, body.mobile-view {
  overflow-y: auto;
  height: auto;
  min-height: 100%;
}

body.mobile-view .neon-frame,
body.mobile-view .ticker,
body.mobile-view .scroll-to-top-btn,
body.mobile-view .screensaver,
body.mobile-view .car-stereo-overlay,
body.mobile-view .boom-box-overlay,
body.mobile-view #carStereoToggleBtn,
body.mobile-view #boomBoxToggleBtn {
  display: none !important;
}

/* iPod mode is the mobile equivalent of Car Stereo/Boom Box — its
   toggle button only makes sense on mobile (the kiosk already has its
   own two skins), so this is the mirror image of the rule above: hidden
   by default, shown only once body.mobile-view is present. */
#ipodToggleBtn {
  display: none;
}
body.mobile-view #ipodToggleBtn {
  display: flex;
}

body.mobile-view .top-bar {
  padding: 10px 14px;
  gap: 8px;
}

body.mobile-view .eq-decor {
  display: none;
}

body.mobile-view .neon-marquee {
  transform: scale(0.6);
  transform-origin: left center;
  margin-right: -60px; /* claw back the space the scale leaves behind */
}

body.mobile-view .presented-by,
body.mobile-view .header-qr-badge {
  display: none;
}

body.mobile-view .app-body {
  display: flex;
  flex-direction: column;
  overflow-y: auto;
}

/* The desktop sidebar becomes a horizontal scrollable pill strip —
   there's no room for a stacked vertical nav list on a phone screen,
   and this matches the same horizontal-scroll pattern .tag-tabs already
   uses elsewhere in the app. */
body.mobile-view .side-nav {
  flex-direction: row;
  align-items: center;
  overflow-x: auto;
  overflow-y: hidden;
  gap: 8px;
  padding: 10px 14px;
  border-right: none;
  border-bottom: 1px solid #221c14;
  flex-shrink: 0;
  justify-content: flex-start;
}

body.mobile-view .nav-list {
  display: flex;
  flex-direction: row;
  gap: 8px;
  list-style: none;
  margin: 0;
  padding: 0;
}

body.mobile-view .nav-item {
  width: auto;
  white-space: nowrap;
  border: 1px solid #3a3226;
  border-left: 1px solid #3a3226;
  border-radius: 20px;
  padding: 8px 14px;
  flex-shrink: 0;
}

body.mobile-view .nav-item.active {
  border-color: var(--pink-bright);
}

body.mobile-view .nav-arrow {
  display: none;
}

body.mobile-view .side-nav-tagline {
  display: none;
}

body.mobile-view .main-content {
  padding: 16px 16px 4px;
  overflow: visible;
}

body.mobile-view .side-now-playing {
  border-left: none;
  border-top: 1px solid #221c14;
  padding: 16px;
  overflow: visible;
}

/* Genre/Featured/P$ Favs icon grids and the Radio/P$ Radio station
   walls are all fixed at 3-4 columns for the kiosk's much wider
   main-content — cramped well past legible at phone width (station
   names were truncating to "WX…", "KE…"), so drop to 2. */
body.mobile-view .genre-grid,
body.mobile-view .featured-grid,
body.mobile-view .station-wall,
body.mobile-view .ps-radio-wall {
  grid-template-columns: repeat(2, 1fr) !important;
}
