/* ============================================================
   SONGS AGAINST HUMANITY — Design System v3 "Mixtape"
   ============================================================ */

/* ------------------------------------------------------------
   1. CUSTOM PROPERTIES
   ------------------------------------------------------------ */
:root {
  /* Palette */
  --ink:    #0E0E12;
  --paper:  #FFF6E9;
  --hot:    #FF2E63;
  --acid:   #D7FF3A;
  --cobalt: #2E3CFF;
  --bone:   #EFE6D7;
  --smoke:  #6B6B78;

  /* Swatch rotation (player chips, stickers) */
  --swatch-1: var(--hot);
  --swatch-2: var(--acid);
  --swatch-3: var(--cobalt);
  --swatch-4: #FF7A1A;   /* tangerine */
  --swatch-5: #3CE0B4;   /* mint */
  --swatch-6: #C8A8FF;   /* lilac */

  /* Typography */
  --font-display: 'Bricolage Grotesque', system-ui, sans-serif;
  --font-body:    'DM Sans', system-ui, sans-serif;
  --font-mono:    'DM Mono', ui-monospace, monospace;
  --font-hand:    'Caveat', cursive;

  /* Spacing / structure */
  --border-width: 1.5px;
  --shadow-chunky: 4px 4px 0 var(--ink);
  --radius-pill: 999px;
  --radius-card: 6px;
}

/* ------------------------------------------------------------
   2. RESET & BASE
   ------------------------------------------------------------ */
*, *::before, *::after { box-sizing: border-box; }
[x-cloak] { display: none !important; }

html {
  width: 100%;
}

html, body {
  margin: 0;
  padding: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.5;
}

body {
  min-width: 0;
}

img, svg, video, canvas {
  max-width: 100%;
}

a {
  color: var(--cobalt);
  text-decoration: none;
}
a:hover { text-decoration: underline; }

/* ------------------------------------------------------------
   3. TYPOGRAPHY HELPERS
   ------------------------------------------------------------ */

/* Tabular numerics — timers, scores, counts */
.num {
  font-variant-numeric: tabular-nums;
  font-family: var(--font-mono);
}

/* Large display moments — topic, wordmark, winner */
.display {
  font-family: var(--font-display);
  font-weight: 700;
  line-height: 0.95;
  letter-spacing: 0;
  overflow-wrap: anywhere;
}

/* Handwriting — stickers only, use very sparingly */
.hand {
  font-family: var(--font-hand);
}

/* ------------------------------------------------------------
   4. TILT UTILITIES — neutralized (kept for class hooks, no rotation)
   ------------------------------------------------------------ */
.tilt-1, .tilt-2, .tilt-3, .tilt-n1, .tilt-n2 { transform: none; }

/* ------------------------------------------------------------
   5. SLAB — full-bleed colored band
   ------------------------------------------------------------ */
.slab {
  border: var(--border-width) solid var(--ink);
  padding: 3rem 2rem;
  position: relative;
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 4vw, 2.5rem);
  font-weight: 700;
  line-height: 1;
}

/* Color variants */
.slab--hot    { background: var(--hot);    color: var(--paper); }
.slab--cobalt { background: var(--cobalt); color: var(--paper); }
.slab--acid   { background: var(--acid);   color: var(--ink);   }
.slab--paper  { background: var(--paper);  color: var(--ink);   }

/* ------------------------------------------------------------
   6. STICKER — pill / circle badge with tilt
   ------------------------------------------------------------ */
.sticker {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.25em;
  padding: 0.25em 0.65em;
  border: var(--border-width) solid var(--ink);
  border-radius: var(--radius-pill);
  font-family: var(--font-display);
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  line-height: 1;
  transform: none;
  white-space: nowrap;
  max-width: 100%;
  user-select: none;
}

/* Color variants — background from swatch palette */
.sticker--1 { background: var(--swatch-1); color: var(--paper); }
.sticker--2 { background: var(--swatch-2); color: var(--ink); }
.sticker--3 { background: var(--swatch-3); color: var(--paper); }
.sticker--4 { background: var(--swatch-4); color: var(--ink); }
.sticker--5 { background: var(--swatch-5); color: var(--ink); }
.sticker--6 { background: var(--swatch-6); color: var(--ink); }

/* Circle sub-variant — equal w/h, tighter shape */
.sticker--circle {
  padding: 0.4em;
  aspect-ratio: 1;
  border-radius: 50%;
  font-size: 0.65rem;
}

/* ------------------------------------------------------------
   7. CASSETTE — paper card with chunky offset shadow
   ------------------------------------------------------------ */
.cassette {
  position: relative;
  min-width: 0;
  background: var(--paper);
  border: var(--border-width) solid var(--ink);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-chunky);
  padding: 0.85rem 1rem;
  transform: none;
  /* Offset shadow means the element needs breathing room */
  margin-bottom: 4px;
  margin-right: 4px;
}

/* Album art within a cassette */
.cassette img {
  width: 64px;
  height: 64px;
  object-fit: cover;
  border-radius: 4px;
  border: 1px solid var(--bone);
  flex-shrink: 0;
}

/* Voted state — locked-in, clearly distinguishable from a neutral card.
   Hot-pink fill + paper text + acid inset border. */
.cassette--voted {
  background: var(--hot);
  border-color: var(--ink);
  box-shadow: 4px 4px 0 var(--ink), 0 0 0 2px var(--acid) inset;
  color: var(--paper);
}
.cassette--voted .meta strong,
.cassette--voted .meta .artist,
.cassette--voted strong,
.cassette--voted .cassette-result__title,
.cassette--voted .cassette-result__artist {
  color: var(--paper);
}

/* ------------------------------------------------------------
   8. CHUNKY BUTTON
   ------------------------------------------------------------ */
.btn-chunky {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4em;
  padding: 0.6em 1.4em;
  background: var(--paper);
  color: var(--ink);
  border: var(--border-width) solid var(--ink);
  border-radius: var(--radius-pill);
  box-shadow: var(--shadow-chunky);
  font-family: var(--font-display);
  font-size: 0.9rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  max-width: 100%;
  min-width: 0;
  text-align: center;
  white-space: normal;
  cursor: pointer;
  text-decoration: none;
  transition: box-shadow 60ms ease, translate 60ms ease;
  user-select: none;
}

.btn-chunky:hover {
  text-decoration: none;
}

.btn-chunky:active {
  translate: 2px 2px;
  box-shadow: 0 0 0 var(--ink);
}

/* Hot variant — hot-pink background */
.btn-chunky--hot {
  background: var(--hot);
  color: var(--paper);
}

/* Acid variant */
.btn-chunky--acid {
  background: var(--acid);
  color: var(--ink);
}

/* Cobalt variant */
.btn-chunky--cobalt {
  background: var(--cobalt);
  color: var(--paper);
}

/* ------------------------------------------------------------
   9. MARQUEE — ticker-tape running text
   ------------------------------------------------------------ */
@keyframes marquee {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

.marquee {
  overflow: hidden;
  white-space: nowrap;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink);
  /* Full-bleed edge-to-edge */
  width: 100%;
}

.marquee__inner {
  display: inline-flex;
  animation: marquee 30s linear infinite;
  /* Width must be >= 200% of visible area for seamless loop */
  width: max-content;
}

/* Two spans of identical content — first exits left as second enters */
.marquee__inner span {
  display: inline-block;
  padding-right: 3em; /* gap between repetitions */
}

/* Pause on hover/focus-within for accessibility */
.marquee:hover .marquee__inner,
.marquee:focus-within .marquee__inner {
  animation-play-state: paused;
}

/* ------------------------------------------------------------
   10. LAYOUT — topbar, main, lobby grid
   ------------------------------------------------------------ */

/* Topbar */
.topbar {
  display: flex;
  align-items: baseline;
  gap: 1rem;
  padding: 0.6rem 1.25rem;
  background: var(--paper);
  border-bottom: var(--border-width) solid var(--ink);
  position: sticky;
  top: 0;
  z-index: 100;
  min-width: 0;
}

/* Brand / wordmark */
.brand {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1rem;
  color: var(--ink);
  letter-spacing: -0.01em;
  text-decoration: none;
  flex: 0 1 auto;
  min-width: 0;
  overflow-wrap: anywhere;
}
.brand:hover { text-decoration: none; }

/* Lobby code in topbar */
.lobby-code {
  margin-left: auto;
  color: var(--smoke);
  font-size: 0.85rem;
  min-width: 0;
}
.lobby-code strong {
  color: var(--ink);
  letter-spacing: 0.2em;
  font-family: var(--font-mono);
  font-weight: 500;
}

/* Timer */
.timer {
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  font-family: var(--font-mono);
  min-width: 0;
}
.timer .label {
  color: var(--smoke);
  margin-right: 0.5em;
  font-family: var(--font-body);
  font-size: 0.8rem;
}

.saved-songs-trigger {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  align-self: center;
  padding: 0.35rem 0.55rem;
  background: var(--paper);
  color: var(--hot);
  border: var(--border-width) solid var(--ink);
  border-radius: var(--radius-pill);
  box-shadow: 2px 2px 0 var(--ink);
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
}

.saved-songs-trigger__heart,
.saved-songs-trigger [data-saved-songs-count] {
  display: block;
  line-height: 1;
}

.saved-songs-trigger__heart {
  transform: translateY(-0.02em);
}

.saved-songs-trigger:active {
  translate: 1px 1px;
  box-shadow: 1px 1px 0 var(--ink);
}

/* Main — no max-width so full-bleed slabs work at root level */
main {
  /* Deliberately no max-width here; inner wrappers constrain content */
}

/* Inner constrained wrapper */
.inner {
  max-width: 1200px;
  margin: 0 auto;
  padding: 1.5rem;
}

/* Landing */
.landing {
  max-width: 560px;
  margin: 2.5rem auto;
  padding: 0 1.5rem;
  display: grid;
  gap: 1.5rem;
}
.landing h1 {
  font-family: var(--font-display);
  font-size: 2rem;
  font-weight: 700;
  margin: 0;
  line-height: 1;
}
.lede { color: var(--smoke); }

/* Cards (legacy / used in landing, etc.) */
.card {
  background: var(--paper);
  padding: 1.25rem;
  border: var(--border-width) solid var(--ink);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-chunky);
  margin-bottom: 4px;
  margin-right: 4px;
}
.card h2 {
  margin-top: 0;
  font-family: var(--font-display);
  font-size: 1rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.row { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.row > * { flex: 1 1 auto; }

/* Error */
.error {
  background: rgba(255, 46, 99, 0.08);
  border: var(--border-width) solid var(--hot);
  color: var(--hot);
  padding: 0.75rem 1rem;
  border-radius: var(--radius-card);
  font-weight: 500;
}

/* Lobby grid — 3-col desktop, stacks at 900px */
.lobby-grid {
  display: grid;
  grid-template-columns: 220px minmax(0, 1fr) 260px;
  grid-template-areas: "players stage room-chat";
  gap: 1.5rem;
  max-width: 1440px;
  margin: 0 auto;
  padding: 1.5rem;
  align-items: start;
}
.lobby-grid > * {
  min-width: 0;
}

/* Rail — left/right sidebars in lobby */
.rail {
  grid-area: players;
  min-width: 0;
  background: var(--bone);
  padding: 1rem;
  border: var(--border-width) solid var(--ink);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-chunky);
  align-self: start;
  margin-bottom: 4px;
  margin-right: 4px;
}
.rail h2 {
  font-family: var(--font-display);
  font-size: 0.7rem;
  font-weight: 700;
  color: var(--smoke);
  margin: 0 0 0.75rem 0;
  text-transform: uppercase;
  letter-spacing: 0.12em;
}

/* Room chat */
.chat-shell {
  grid-area: room-chat;
  min-width: 0;
  align-self: start;
}

.chat-panel {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  min-height: 420px;
  max-height: calc(100vh - 6rem);
  background: var(--bone);
  border: var(--border-width) solid var(--ink);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-chunky);
  overflow: hidden;
  margin-bottom: 4px;
  margin-right: 4px;
}

.chat-panel__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.75rem 0.85rem;
  border-bottom: var(--border-width) solid var(--ink);
  background: var(--paper);
}

.chat-panel__header h2 {
  margin: 0;
  font-family: var(--font-display);
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--smoke);
  text-transform: uppercase;
  letter-spacing: 0.12em;
}

.chat-panel__collapse,
.chat-mobile-toggle {
  display: none;
}

.chat-panel__messages {
  min-height: 0;
  max-height: 100%;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  padding: 0.85rem;
  display: flex;
  flex-direction: column;
  gap: 0.65rem;
}

.chat-message {
  max-width: 92%;
  padding: 0.55rem 0.65rem;
  background: var(--paper);
  border: var(--border-width) solid var(--ink);
  border-radius: var(--radius-card);
}

.chat-message--me {
  align-self: flex-end;
  background: rgba(215, 255, 58, 0.35);
}

.chat-message--system {
  max-width: 100%;
  align-self: stretch;
  background: var(--cobalt);
  color: var(--paper);
}

.chat-message--system .chat-message__meta,
.chat-message--system .chat-message__meta strong {
  color: var(--acid);
}

.chat-message__meta {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  margin-bottom: 0.2rem;
  font-size: 0.72rem;
  color: var(--smoke);
}

.chat-message__meta strong {
  color: var(--ink);
  overflow-wrap: anywhere;
}

.chat-message__meta span {
  padding: 0.05rem 0.25rem;
  border: 1px solid var(--ink);
  border-radius: var(--radius-pill);
  background: var(--acid);
  color: var(--ink);
  font-size: 0.6rem;
}

.chat-message p,
.chat-empty {
  margin: 0;
  overflow-wrap: anywhere;
}

.chat-form {
  display: grid;
  gap: 0.5rem;
  padding: 0.75rem;
  background: var(--paper);
  border-top: var(--border-width) solid var(--ink);
}

.chat-emoji-row {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  gap: 0.25rem;
}

.chat-emoji-row button,
.chat-send-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
}

.chat-emoji-row button {
  aspect-ratio: 1;
  min-height: 2rem;
  background: var(--bone);
  line-height: 1;
}

.chat-input-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 2.5rem;
  gap: 0.4rem;
}

.chat-input-row input {
  width: 100%;
}

.chat-send-btn {
  min-height: 2.5rem;
  background: var(--hot);
  color: var(--paper);
  border-radius: 50%;
  font-weight: 800;
}

.emoji-rain-layer {
  position: fixed;
  inset: 0;
  z-index: 400;
  pointer-events: none;
  overflow: hidden;
}

.emoji-rain-burst {
  position: absolute;
  inset: 0;
}

.emoji-rain-name {
  position: absolute;
  left: var(--name-x);
  top: 1rem;
  translate: -50% 0;
  max-width: min(12rem, 70vw);
  padding: 0.28rem 0.55rem;
  background: var(--acid);
  color: var(--ink);
  border: var(--border-width) solid var(--ink);
  border-radius: var(--radius-pill);
  box-shadow: 2px 2px 0 var(--ink);
  font-family: var(--font-display);
  font-size: 0.75rem;
  font-weight: 700;
  line-height: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  animation: emoji-name-pop 4.2s ease-out forwards;
}

.emoji-rain-drop {
  position: absolute;
  top: -4rem;
  left: var(--x);
  translate: -50% 0;
  font-size: clamp(1.6rem, 7vw, 3rem);
  line-height: 1;
  animation:
    emoji-drop-fall var(--duration) linear var(--delay) forwards,
    emoji-drop-wiggle 850ms ease-in-out var(--delay) infinite alternate;
  filter: drop-shadow(2px 2px 0 rgba(14, 14, 18, 0.35));
}

.emoji-rain-drop:nth-child(3n) {
  opacity: 0.82;
}

.emoji-rain-drop:nth-child(4n) {
  font-size: clamp(1.2rem, 5vw, 2.2rem);
}

@media (max-width: 900px) {
  .lobby-grid {
    grid-template-columns: 1fr;
    grid-template-areas:
      "players"
      "stage";
  }

  .chat-shell {
    grid-area: auto;
    position: fixed;
    right: 1rem;
    bottom: 1rem;
    z-index: 180;
    display: grid;
    justify-items: end;
    align-items: end;
    width: 3.25rem;
    height: 3.25rem;
    pointer-events: auto;
  }

  .chat-panel {
    display: none;
    width: 100%;
    height: 100%;
    max-height: none;
    min-height: 0;
    margin: 0;
    border-radius: 0;
  }

  .chat-shell.is-open {
    inset: 0;
    width: 100vw;
    height: 100dvh;
    padding: 0;
  }

  .chat-shell.is-open .chat-panel {
    display: grid;
    position: absolute;
    inset: 0;
    pointer-events: auto;
  }

  .chat-mobile-toggle {
    display: inline-flex;
    position: relative;
    align-items: center;
    justify-content: center;
    width: 3.25rem;
    height: 3.25rem;
    padding: 0;
    background: var(--acid);
    border: var(--border-width) solid var(--ink);
    border-radius: 50%;
    box-shadow: var(--shadow-chunky);
    font-size: 1.45rem;
    pointer-events: auto;
  }

  .chat-panel__collapse {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    padding: 0;
    border-radius: 50%;
    box-shadow: 2px 2px 0 var(--ink);
    font-size: 1.2rem;
    line-height: 1;
  }

  .chat-shell.is-open .chat-mobile-toggle {
    display: none;
  }

  .chat-unread {
    position: absolute;
    top: -0.35rem;
    right: -0.35rem;
    min-width: 1.35rem;
    height: 1.35rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0 0.3rem;
    background: var(--hot);
    color: var(--paper);
    border: var(--border-width) solid var(--ink);
    border-radius: var(--radius-pill);
    font-size: 0.7rem;
    font-weight: 700;
  }

  .chat-unread[hidden] {
    display: none;
  }
}

@keyframes emoji-name-pop {
  from {
    transform: translateY(-1rem) scale(0.92);
    opacity: 1;
  }
  20% {
    transform: translateY(0) scale(1);
    opacity: 1;
  }
  88% {
    opacity: 1;
  }
  to {
    transform: translateY(0.75rem) scale(0.96);
    opacity: 0;
  }
}

@keyframes emoji-drop-fall {
  from {
    top: -4rem;
    opacity: 1;
  }
  88% {
    opacity: 1;
  }
  to {
    top: calc(100vh + 5rem);
    opacity: 0;
  }
}

@keyframes emoji-drop-wiggle {
  from {
    transform: rotate(calc(var(--spin) * -1));
  }
  to {
    transform: rotate(var(--spin)) translateX(var(--sway));
  }
}

/* Players list */
.players {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 0.45rem;
}
.player {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0.3rem;
  padding: 0.45rem 0.65rem;
  background: var(--paper);
  border: var(--border-width) solid var(--ink);
  border-radius: var(--radius-card);
}
.player .name { grid-column: 1 / 2; font-weight: 500; font-size: 0.9rem; }
/* "me" indicator is the YOU badge + a thicker ink outline; do NOT override swatch background */
.players .sticker.player.me { box-shadow: 0 0 0 2px var(--ink) inset; }
.player.offline { opacity: 0.5; }
.player.host .name::after { content: none; }
.player .badge {
  font-size: 0.65rem;
  font-family: var(--font-display);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  padding: 0.15em 0.5em;
  border-radius: var(--radius-pill);
  border: 1px solid var(--ink);
  background: var(--bone);
  color: var(--ink);
}
.player .badge.ok  { background: var(--acid); color: var(--ink); }
.player .badge.muted { background: var(--bone); color: var(--smoke); }
.player .score {
  font-weight: 700;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  color: var(--cobalt);
}

/* Scoreboard */
.scoreboard {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 0.35rem;
  counter-reset: rank;
}
.scoreboard li {
  display: grid;
  grid-template-columns: 1.5em 1fr auto;
  gap: 0.5rem;
  align-items: center;
  padding: 0.4rem 0.65rem;
  background: var(--paper);
  border: var(--border-width) solid var(--bone);
  border-radius: var(--radius-card);
  counter-increment: rank;
  font-size: 0.9rem;
}
.scoreboard li::before {
  content: counter(rank);
  color: var(--smoke);
  font-family: var(--font-mono);
  font-size: 0.8rem;
}
/* When the template emits a competitive rank (ties share rank), prefer that
   over the sequential CSS counter. */
.scoreboard li[data-rank]::before {
  content: attr(data-rank);
}
.scoreboard li.me {
  border-color: var(--hot);
  background: rgba(255, 46, 99, 0.06);
}
.scoreboard.final li { padding: 0.65rem 0.8rem; font-size: 1rem; }

/* Round meta */
.round-meta { color: var(--smoke); margin-top: 0.5rem; font-size: 0.85rem; }

/* Stage */
.stage {
  grid-area: stage;
  min-width: 0;
  min-height: 320px;
  display: grid;
  align-content: start;
  gap: 1rem;
  container-type: inline-size;
}
.stage-card {
  background: var(--paper);
  padding: 1.5rem;
  border: var(--border-width) solid var(--ink);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-chunky);
  margin-bottom: 4px;
  margin-right: 4px;
  overflow: hidden;
}

/* Round tag + topic */
.round-tag {
  font-family: var(--font-display);
  font-size: 0.7rem;
  font-weight: 700;
  color: var(--smoke);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  margin: 0;
}
.topic {
  font-family: var(--font-display);
  font-size: clamp(1.4rem, 3vw, 2rem);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -0.02em;
  margin: 0.25rem 0 1rem;
}

/* Banners */
.banner {
  padding: 0.65rem 1rem;
  border: var(--border-width) solid var(--ink);
  border-radius: var(--radius-card);
  background: rgba(255, 122, 26, 0.12);
  color: var(--ink);
  font-weight: 500;
}
.banner.ok {
  background: rgba(215, 255, 58, 0.25);
  color: var(--ink);
}

/* Muted helper */
.muted { color: var(--smoke); }

/* Config fieldset */
.config {
  border: var(--border-width) solid var(--bone);
  border-radius: var(--radius-card);
  padding: 0.75rem 1rem;
  margin-bottom: 1rem;
  background: var(--bone);
}
.config legend {
  font-family: var(--font-display);
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--smoke);
  padding: 0 0.4rem;
}
.config label {
  display: grid;
  gap: 0.25rem;
  font-size: 0.85rem;
  color: var(--smoke);
}

/* ------------------------------------------------------------
   11. FORMS — inputs, buttons (preserve existing class hooks)
   ------------------------------------------------------------ */
input, button, select {
  min-width: 0;
  max-width: 100%;
  background: var(--paper);
  color: var(--ink);
  border: var(--border-width) solid var(--ink);
  border-radius: var(--radius-card);
  padding: 0.6rem 0.75rem;
  font: inherit;
}

input:focus, button:focus {
  outline: 2.5px solid var(--cobalt);
  outline-offset: 2px;
}

button { cursor: pointer; }

/* Legacy primary submit styling — only kicks in when the button does NOT use the
   .btn-chunky utility (which now owns CTA visuals). Avoids overriding our
   color variants like .btn-chunky--cobalt / --acid. */
button.primary:not(.btn-chunky),
button[type="submit"]:not(.btn-chunky) {
  background: var(--hot);
  border-color: var(--ink);
  color: var(--paper);
  font-family: var(--font-display);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  border-radius: var(--radius-pill);
  box-shadow: var(--shadow-chunky);
  transition: box-shadow 60ms ease, translate 60ms ease;
}
button.primary:not(.btn-chunky):active,
button[type="submit"]:not(.btn-chunky):active {
  translate: 2px 2px;
  box-shadow: 0 0 0 var(--ink);
}

button:disabled {
  opacity: 0.45;
  cursor: not-allowed;
  box-shadow: none;
}

/* ------------------------------------------------------------
   12. SEARCH
   ------------------------------------------------------------ */
.search input { width: 100%; }

.search-results { display: grid; gap: 0.4rem; margin-top: 0.75rem; }

.search-results .result,
.search-list .result {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: grid;
  grid-template-columns: 48px 1fr;
  grid-auto-rows: auto;
  gap: 0 0.75rem;
  align-items: center;
  text-align: left;
  padding: 0.6rem 0.85rem;
  background: var(--paper);
  border: var(--border-width) solid var(--ink);
  border-radius: var(--radius-card);
  cursor: pointer;
  color: inherit;
  font: inherit;
  transition: box-shadow 60ms ease;
}
.search-results .result:hover,
.search-list .result:hover {
  box-shadow: var(--shadow-chunky);
}

.search-results .result img,
.search-list .result img {
  width: 48px;
  height: 48px;
  border-radius: 4px;
  object-fit: cover;
  grid-row: 1 / span 2;
  align-self: center;
}
.search-results .result .title,
.search-list .result .title {
  font-weight: 600;
  grid-column: 2;
  align-self: end;
}
.search-results .result .artist,
.search-list .result .artist {
  color: var(--smoke);
  grid-column: 2;
  align-self: start;
  font-size: 0.9em;
}
.search-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 0.4rem;
}

/* ------------------------------------------------------------
   13. AUDIO + PROGRESS FILL
   ------------------------------------------------------------ */
/* Audio is preview-only — hide the native controls; hover the card to play */
.result audio, .vote-card audio, .result-card audio,
.cassette audio { display: none; }

/* Cassette playing state — dramatic hot-pink fill that grows with progress.
   The unplayed portion stays softly tinted so paper-cream text on top
   remains readable across the whole card at any progress value.
   Driven by --progress (0..1) set on the card from audio timeupdate events. */
.cassette[data-playing],
.result[data-playing],
.vote-card[data-playing],
.result-card[data-playing] {
  background:
    linear-gradient(
      90deg,
      var(--hot) 0%,
      var(--hot) calc(var(--progress, 0) * 100%),
      rgba(255, 46, 99, 0.55) calc(var(--progress, 0) * 100%),
      rgba(255, 46, 99, 0.55) 100%
    );
  border-color: var(--ink);
  box-shadow: 4px 4px 0 var(--ink), 0 0 0 2px var(--acid) inset;
  transition: box-shadow 120ms ease;
}

/* Acid progress hairline at the bottom — gives the card a visible scrub line.
   No CSS transition: --progress is updated 60fps from rAF, so any added
   transition would lag behind incoming frames and re-introduce stepping. */
.cassette[data-playing]::after,
.result[data-playing]::after,
.vote-card[data-playing]::after,
.result-card[data-playing]::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 3px;
  width: calc(var(--progress, 0) * 100%);
  background: var(--acid);
  pointer-events: none;
  z-index: 2;
  /* Match the card's bottom corners so the hairline doesn't poke past them
     now that we no longer rely on overflow:hidden to clip it. */
  border-bottom-left-radius: inherit;
}

/* When the card has the dramatic fill, force readable text on the filled half.
   The simplest readable solution: paper-cream text while playing — works on
   the hot-pink filled portion and stays acceptable on the remaining paper edge
   since the album art + acid border keep the card scannable. */
.cassette[data-playing] .cassette-result__title,
.cassette[data-playing] .cassette-result__artist,
.cassette[data-playing] strong,
.cassette[data-playing] .meta strong,
.cassette[data-playing] .meta .artist,
.vote-card[data-playing] .meta strong,
.vote-card[data-playing] .meta .artist,
.result-card[data-playing] .meta strong,
.result-card[data-playing] .meta .artist {
  color: var(--paper);
  text-shadow: 0 1px 0 rgba(14, 14, 18, 0.25);
}

/* ------------------------------------------------------------
   14. VOTE / RESULT CARDS
   ------------------------------------------------------------ */
.vote-list, .results-list {
  list-style: none;
  padding: 0;
  margin: 1rem 0 0;
  display: grid;
  gap: 0.75rem;
}

.vote-card, .result-card {
  position: relative;
  isolation: isolate;
  /* Background gradient already clips to border-radius; no overflow:hidden so
     status tags (Confirm, Voted) can sit on the edge without being clipped. */
  display: grid;
  grid-template-columns: 64px 1fr auto;
  gap: 0.75rem;
  align-items: center;
  padding: 0.85rem 1rem;
  background: var(--paper);
  border: var(--border-width) solid var(--ink);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-chunky);
  transition: box-shadow 60ms ease, translate 60ms ease;
  margin-bottom: 4px;
  margin-right: 4px;
}
.vote-card:hover { box-shadow: 6px 6px 0 var(--ink); }
/* Voted card keeps its locked styling on hover — don't let the generic hover
   shadow above repaint over the inset acid ring. */
.vote-card.cassette--voted,
.vote-card.cassette--voted:hover {
  box-shadow: 4px 4px 0 var(--ink), 0 0 0 2px var(--acid) inset;
  cursor: default;
}

/* Self-submitted card */
.vote-card.self {
  opacity: 0.55;
  box-shadow: none;
  border-style: dashed;
  padding-bottom: 2.2rem; /* room for the bottom-pinned YOUR PICK sticker */
}

/* Already-voted card */
.vote-card.voted {
  border-color: var(--hot);
  box-shadow: 4px 4px 0 var(--hot);
}

.vote-card img, .result-card img {
  width: 64px;
  height: 64px;
  border-radius: 4px;
  object-fit: cover;
}
.vote-card .meta strong, .result-card .meta strong {
  display: block;
  font-weight: 600;
  overflow-wrap: anywhere;
}
.vote-card .meta .artist, .result-card .meta .artist {
  color: var(--smoke);
  display: block;
  font-size: 0.9em;
  overflow-wrap: anywhere;
}

.card-actions {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  justify-content: center;
  gap: 0.45rem;
}

.favorite-song-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  padding: 0;
  background: var(--paper);
  color: var(--hot);
  border: var(--border-width) solid var(--ink);
  border-radius: 50%;
  box-shadow: 2px 2px 0 var(--ink);
  font-size: 1.25rem;
  line-height: 1;
  cursor: pointer;
  user-select: none;
  transition: box-shadow 60ms ease, translate 60ms ease, background 120ms ease;
  z-index: 6;
}

.favorite-song-btn:hover,
.favorite-song-btn.is-saved {
  background: var(--hot);
  color: var(--paper);
}

.favorite-song-btn:active {
  translate: 1px 1px;
  box-shadow: 1px 1px 0 var(--ink);
}

.result-card > .favorite-song-btn {
  justify-self: end;
}

.vote-card.inactive .favorite-song-btn,
.vote-card.self .favorite-song-btn {
  cursor: pointer;
}
.result-card .picker {
  display: block;
}
.vote-count {
  font-variant-numeric: tabular-nums;
  font-family: var(--font-mono);
  font-weight: 700;
  color: var(--hot);
  font-size: 1.1rem;
}

/* ------------------------------------------------------------
   15a. VOTE INTERACTION — click to select, click again to confirm
   ------------------------------------------------------------ */
.vote-hint {
  margin: 0.25rem 0 0.75rem;
  font-style: italic;
  color: var(--smoke);
}

.vote-card { cursor: pointer; }
.vote-card.self { cursor: not-allowed; }
.vote-card.voted,
.vote-card.inactive { cursor: default; }

/* Selected (first click) — chunky pink outline + lift */
.vote-card.selected {
  border-color: var(--hot);
  box-shadow: 6px 6px 0 var(--hot);
  translate: -2px -2px;
}

/* Once a vote is locked, dim the cards we didn't pick. */
.vote-card.inactive {
  opacity: 0.5;
  filter: saturate(0.7);
  box-shadow: var(--shadow-chunky);
}
.vote-card.inactive:hover { box-shadow: var(--shadow-chunky); }

/* Tag positioned in the third grid column (where the old Vote button sat). */
.card-tag {
  font-family: var(--font-display);
  font-size: 0.65rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  padding: 0.25em 0.55em;
  border: var(--border-width) solid var(--ink);
  border-radius: var(--radius-pill);
  white-space: nowrap;
  user-select: none;
}
.card-tag.self-tag {
  background: var(--bone);
  color: var(--smoke);
  border-style: dashed;
}
@keyframes tag-pop {
  0%   { transform: scale(0);   opacity: 0; }
  70%  { transform: scale(1.1); opacity: 1; }
  100% { transform: scale(1);   opacity: 1; }
}
.card-tag.confirm-tag {
  background: var(--hot);
  color: var(--paper);
  animation: tag-pop 180ms cubic-bezier(0.175, 0.885, 0.32, 1.275) both;
}
.card-tag.voted-tag {
  background: var(--acid);
  color: var(--ink);
}

/* ------------------------------------------------------------
   15. FLASH / TOAST
   ------------------------------------------------------------ */
.flash {
  position: fixed;
  bottom: 1.5rem;
  left: 50%;
  transform: translateX(-50%);
  z-index: 200;
  pointer-events: none;
}
.toast {
  background: var(--paper);
  border: var(--border-width) solid var(--hot);
  color: var(--ink);
  padding: 0.65rem 1.1rem;
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-chunky);
  font-weight: 500;
}

/* ------------------------------------------------------------
   15b. SAVED SONGS
   ------------------------------------------------------------ */
.saved-songs-open {
  overflow: hidden;
}

.saved-songs-modal[hidden] {
  display: none;
}

.saved-songs-modal {
  position: fixed;
  inset: 0;
  z-index: 250;
  display: grid;
  place-items: center;
  padding: 1rem;
}

.saved-songs-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(14, 14, 18, 0.55);
}

.saved-songs-panel {
  position: relative;
  z-index: 1;
  width: min(720px, 100%);
  max-height: min(720px, calc(100vh - 2rem));
  overflow: auto;
  background: var(--paper);
  border: var(--border-width) solid var(--ink);
  border-radius: var(--radius-card);
  box-shadow: 8px 8px 0 var(--ink);
  padding: 1rem;
}

.saved-songs-panel__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1rem;
}

.saved-songs-panel__header h2 {
  margin: 0;
  font-size: clamp(1.6rem, 5vw, 2.5rem);
  text-transform: uppercase;
}

.saved-songs-close,
.saved-song-remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  padding: 0;
  background: var(--paper);
  color: var(--ink);
  border: var(--border-width) solid var(--ink);
  border-radius: 50%;
  box-shadow: 2px 2px 0 var(--ink);
  font-size: 1.25rem;
  line-height: 1;
  cursor: pointer;
}

.saved-songs-list {
  display: grid;
  gap: 0.75rem;
}

.saved-songs-empty {
  margin: 1rem 0;
}

.saved-song-row {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr) auto;
  gap: 0.85rem;
  align-items: center;
}

.saved-song-row .meta {
  min-width: 0;
}

.saved-song-row .meta strong,
.saved-song-row .meta span {
  display: block;
}

.saved-song-row .meta strong {
  font-size: 0.95rem;
  line-height: 1.1;
}

.saved-song-row .artist {
  color: var(--smoke);
  font-size: 0.82rem;
}

.saved-song-topic {
  color: var(--cobalt);
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  line-height: 1.25;
  margin-top: 0.25rem;
  text-transform: uppercase;
}

.saved-song-actions {
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

.saved-song-actions audio {
  width: 180px;
  max-width: 34vw;
  height: 32px;
}

/* ------------------------------------------------------------
   16. FINAL / GAME OVER
   ------------------------------------------------------------ */
.final .winner {
  font-family: var(--font-display);
  font-size: 1.4rem;
  font-weight: 800;
  letter-spacing: -0.02em;
  margin: 0.5rem 0 1rem;
}

/* ------------------------------------------------------------
   17. PHASE 2A — LANDING PAGE
   ------------------------------------------------------------ */

/* Hero slab — full-bleed, no max-width cap */
.hero-slab {
  position: relative;
  padding: 3rem 2.5rem 4rem;
}

/* Three-line stacked wordmark */
.hero-wordmark {
  font-size: clamp(3rem, 10vw, 7rem);
  line-height: 0.9;
  color: var(--paper);
  max-width: 760px;
  min-width: 0;
}

/* Mono kicker — pinned bottom-right inside slab */
.hero-kicker {
  position: absolute;
  bottom: 1.5rem;
  right: 2rem;
  color: rgba(255,246,233,0.65);
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  margin: 0;
}

/* Mascot — pinned bottom-left peeking from slab */
.hero-mascot {
  position: absolute;
  bottom: 0.5rem;
  left: 2rem;
  color: rgba(255,246,233,0.55);
  line-height: 0;
}

/* Hero mascot character image (DJ disco ball) — sized up for landing prominence */
.hero-mascot-img {
  position: absolute;
  bottom: 1.5rem;
  right: 2rem;
  width: clamp(220px, 26vw, 360px);
  height: auto;
  filter: drop-shadow(3px 3px 0 var(--ink));
  pointer-events: none;
  z-index: 1;
}
@media (max-width: 700px) {
  .hero-mascot-img {
    bottom: 0.75rem;
    right: 0.75rem;
    width: 140px;
    opacity: 0.85;
  }
}

/* Landing body wrapper — constrained, centred */
.landing-body {
  max-width: 860px;
  margin: 0 auto;
  padding: 2rem 1.5rem 1.5rem;
  display: grid;
  gap: 1.25rem;
}

/* Example topic line */
.landing-topic {
  font-family: var(--font-display);
  font-style: italic;
  font-size: 1.1rem;
  color: var(--smoke);
  margin: 0;
}

/* Side-by-side cassette forms */
.landing-forms {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.25rem;
}
@media (max-width: 600px) {
  .landing-forms { grid-template-columns: 1fr; }
}

/* Individual cassette form card — flex column so the button can be pushed
   to the bottom and both cards visually balance even when the JOIN form has
   one more input row than the CREATE form. */
.landing-form {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}
.landing-form form {
  display: flex;
  flex-direction: column;
  flex: 1;
  gap: 0.75rem;
}
/* The button row sits at the bottom of the card, equal padding above it. */
.landing-form .form-row:last-child {
  margin-top: auto;
}
.landing-form h2 {
  display: inline-flex;
  margin: 0 0 0.35rem 0;
  font-size: 0.8rem;
  transform: none;
}
.landing-form .form-row {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
  align-items: center;
}
.landing-form input {
  flex: 1 1 auto;
  min-width: min(12rem, 100%);
}

.visibility-toggle {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.65rem;
  align-items: start;
  padding: 0.65rem 0.75rem;
  background: var(--bone);
  border: var(--border-width) solid var(--ink);
  border-radius: var(--radius-card);
  cursor: pointer;
}
.visibility-toggle input {
  width: 1.1rem;
  height: 1.1rem;
  margin: 0.15rem 0 0;
  accent-color: var(--hot);
}
.visibility-toggle strong {
  display: block;
  font-family: var(--font-display);
  font-size: 0.86rem;
  line-height: 1.1;
  text-transform: uppercase;
}
.visibility-toggle small {
  display: block;
  color: var(--smoke);
  font-size: 0.78rem;
  line-height: 1.25;
}

.public-matches {
  display: grid;
  gap: 0.85rem;
}
.public-matches__header {
  display: flex;
  justify-content: space-between;
  gap: 0.75rem;
  align-items: center;
}
.public-matches__header h2 {
  margin: 0;
}
.public-matches__count {
  color: var(--smoke);
  font-size: 0.8rem;
  font-weight: 700;
}
.public-match-grid {
  display: grid;
  gap: 0.85rem;
}
.public-match {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(260px, 0.85fr);
  gap: 1rem;
  align-items: center;
  background:
    linear-gradient(90deg, rgba(215, 255, 58, 0.28), transparent 48%),
    var(--paper);
}
.public-match h3,
.public-match p {
  margin: 0;
}
.public-match h3 {
  font-family: var(--font-display);
  font-size: 1.15rem;
  line-height: 1.1;
}
.public-match__code {
  display: inline-flex;
  margin: 0 0 0.35rem;
  padding: 0.12rem 0.45rem;
  background: var(--cobalt);
  color: var(--paper);
  border: var(--border-width) solid var(--ink);
  border-radius: var(--radius-card);
  font-weight: 700;
  letter-spacing: 0.08em;
}
.public-match__join {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 0.55rem;
}
.public-empty p {
  margin: 0;
}
.public-empty p + p {
  margin-top: 0.25rem;
}
@media (max-width: 700px) {
  .public-match,
  .public-match__join {
    grid-template-columns: 1fr;
  }
}

/* Ghost (outlined only) variant for copy-link button */
.btn-chunky--ghost {
  background: transparent;
  color: var(--ink);
  box-shadow: none;
  border-style: dashed;
}
.btn-chunky--ghost:active {
  translate: 2px 2px;
}

/* Bottom marquee border strip */
.marquee--landing {
  border-top: var(--border-width) solid var(--ink);
  padding: 0.5rem 0;
  background: var(--acid);
}

/* ------------------------------------------------------------
   18. PHASE 2A — LOBBY WAITING ROOM
   ------------------------------------------------------------ */

/* Poster code slab inside stage-card */
.lobby-code-slab {
  text-align: center;
  padding: 2rem 1.5rem;
  border-radius: var(--radius-card);
  margin-bottom: 1rem;
  overflow: hidden;
}

/* Giant lobby code */
.lobby-code-giant {
  font-size: clamp(3.25rem, 8vw, 6rem);
  letter-spacing: 0.16em;
  text-indent: 0.16em;
  line-height: 1;
  margin-bottom: 0.75rem;
  overflow-wrap: normal;
}

/* Share hint below code */
.lobby-share-hint {
  color: var(--smoke);
  font-size: 0.85rem;
  margin: 0 0 0.75rem 0;
}

/* Player count line — centred, bold mono */
.lobby-player-count {
  font-size: 0.9rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-align: center;
  margin: 0.25rem 0 1rem;
}

/* Settings disclosure */
.config-details {
  margin-bottom: 1rem;
}
.config-summary {
  cursor: pointer;
  font-size: 1rem;
  font-weight: 700;
  color: var(--smoke);
  list-style: none;
  padding: 0.4rem 0;
}
.config-summary::-webkit-details-marker { display: none; }

/* Start button — full width on narrow stage */
.lobby-start-btn {
  display: block;
  width: 100%;
  text-align: center;
  font-size: 1.1rem;
  padding: 0.75em 1.5em;
}

/* Non-host waiting state */
.lobby-waiting-guest {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  color: var(--smoke);
  margin-top: 0.5rem;
}
.lobby-waiting-guest p { margin: 0; }

/* Waiting-screen character — used in guest lobby + spectator banner.
   Source is 200×133 (3:2). Default = larger lobby size; --sm = banner size. */
.waiting-mascot {
  width: 144px;
  height: auto;
  flex-shrink: 0;
  display: block;
  filter: drop-shadow(2px 2px 0 var(--ink));
}
.waiting-mascot--sm {
  width: 88px;
  filter: drop-shadow(1.5px 1.5px 0 var(--ink));
}
@media (max-width: 700px) {
  .waiting-mascot { width: 112px; }
  .waiting-mascot--sm { width: 72px; }
}

/* ------------------------------------------------------------
   19. PHASE 2A — PLAYERS RAIL (sticker name-tags)
   ------------------------------------------------------------ */

/* Player sticker name-tags — merged players + scoreboard panel */
.players .sticker.player {
  display: grid;
  min-width: 0;
  /* row 1: rank · name · score (one line) ; row 2: badges (full width) */
  grid-template-columns: auto 1fr auto;
  grid-template-rows: auto auto;
  gap: 0.15rem 0.5rem;
  align-items: baseline;
  padding: 0.5rem 0.75rem;
  border-radius: 6px;
  margin-bottom: 6px;
  margin-right: 6px;
}
.players .sticker.player .rank {
  grid-column: 1;
  grid-row: 1;
  font-size: 0.7rem;
  opacity: 0.65;
  letter-spacing: 0.04em;
}
.players .sticker.player .name {
  grid-column: 2;
  grid-row: 1;
  font-size: 0.95rem;
  white-space: normal;
  word-break: break-word;
  overflow-wrap: anywhere;
  line-height: 1.2;
}
.players .sticker.player .score {
  grid-column: 3;
  grid-row: 1;
  font-size: 1rem;
  font-weight: 700;
  color: inherit;
  justify-self: end;
}
.players .sticker.player .player-badges {
  grid-column: 1 / -1;
  grid-row: 2;
  display: flex;
  flex-wrap: wrap;
  gap: 0.25em;
  align-items: center;
  margin-top: 0.15rem;
}
/* Hide the empty badge row when no badges render (avoid extra gap) */
.players .sticker.player .player-badges:empty {
  display: none;
}
.players .sticker.player .sticker--circle {
  font-size: 0.55rem;
  padding: 0.3em;
  background: rgba(255,255,255,0.3);
  border-color: rgba(14,14,18,0.25);
  color: inherit;
}
.players .sticker.player .you-badge { background: var(--acid); color: var(--ink); }
.players .sticker.player .ok-badge  { background: var(--acid); color: var(--ink); }
.players .sticker.player .offline-badge { opacity: 0.55; }

/* Boost specificity so the swatch class wins over legacy .player base bg */
.players .sticker.player.sticker--1 { background: var(--swatch-1); color: var(--paper); }
.players .sticker.player.sticker--2 { background: var(--swatch-2); color: var(--ink); }
.players .sticker.player.sticker--3 { background: var(--swatch-3); color: var(--paper); }
.players .sticker.player.sticker--4 { background: var(--swatch-4); color: var(--ink); }
.players .sticker.player.sticker--5 { background: var(--swatch-5); color: var(--ink); }
.players .sticker.player.sticker--6 { background: var(--swatch-6); color: var(--ink); }

/* ------------------------------------------------------------
   20. PHASE 2A — SCOREBOARD RAIL
   ------------------------------------------------------------ */

/* Leader (first rank) row — hot pink tint */
.scoreboard li.leader {
  background: rgba(255,46,99,0.08);
  border-color: var(--hot);
}

/* Leader badge star */
.leader-badge {
  font-size: 0.75rem;
  color: var(--hot);
  margin-right: 0.25em;
}

/* ------------------------------------------------------------
   21. PHASE 2A — TIMER DISPLAY
   ------------------------------------------------------------ */

/* Countdown digits — loud numeric display */
.countdown.num.display {
  font-size: 2rem;
  font-weight: 700;
  line-height: 1;
  color: var(--ink);
  font-family: var(--font-mono);
}

/* Low-time pulse — add class .timer--low via JS if desired */
@keyframes acid-pulse {
  0%, 100% { color: var(--ink); }
  50%       { color: var(--hot); }
}
.timer--low .countdown {
  animation: acid-pulse 0.8s ease-in-out infinite;
}

/* Topbar timer layout */
.timer .timer-inner {
  display: inline-flex;
  align-items: baseline;
  gap: 0.35em;
}
.timer .label {
  color: var(--smoke);
  font-size: 0.75rem;
  font-family: var(--font-body);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

/* ============================================================
   PHASE 2B ADDITIONS — in-round game phase templates
   (_round_submit, _round_vote, _round_results, _game_over)
   ============================================================ */

/* ------------------------------------------------------------
   2B-1. ROUND META KICKER
   Small mono uppercase label: "ROUND N / N"
   ------------------------------------------------------------ */
.round-kicker {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--smoke);
  margin: 0 0 0.5rem;
}

/* ------------------------------------------------------------
   2B-2. TOPIC HERO
   Override base .topic for the poster moment
   ------------------------------------------------------------ */
.topic.display {
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(1.9rem, 6.5cqw, 3rem);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: 0;
  margin: 0 0 1.25rem;
  color: var(--ink);
}

/* Slightly smaller recap variant used on results screen */
.topic--recap {
  font-size: clamp(1.35rem, 4.5cqw, 2rem) !important;
  margin-bottom: 1rem !important;
}

/* ------------------------------------------------------------
   2B-3. SUBMIT SCREEN
   ------------------------------------------------------------ */

/* Spectator banner */
.submit-spectator-banner {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.75rem 1rem;
  border: var(--border-width) solid var(--ink);
  border-radius: var(--radius-card);
  background: var(--bone);
  margin-top: 0.5rem;
}
.submit-spectator-text {
  font-style: italic;
  color: var(--smoke);
  margin: 0;
}

/* Submitted confirmation area */
.submit-confirmed {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin: 0.5rem 0 1rem;
}
.submit-waiting {
  margin: 0;
  font-style: italic;
}

/* Voted confirmation — prominent banner shown after the user has cast a vote.
   Sits between the topic and the cassette grid so the wait state is unmissable. */
.voted-banner {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  padding: 0.85rem 1.25rem;
  margin: 0.75rem auto 1.25rem;
  max-width: 480px;
  border: var(--border-width) solid var(--ink);
  border-radius: var(--radius-card);
  background: var(--bone);
  box-shadow: 4px 4px 0 var(--ink);
}
.voted-banner__text {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.35rem;
}
.voted-banner__caption {
  margin: 0;
  font-style: italic;
  color: var(--smoke);
}

/* Search input — big paper input, ink border, square corners */
.submit-search-input {
  width: 100%;
  font-size: 1.05rem;
  padding: 0.75rem 1rem;
  border: var(--border-width) solid var(--ink);
  border-radius: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  box-shadow: none;
  margin-bottom: 0.75rem;
}
.submit-search-input:focus {
  outline: 2.5px solid var(--cobalt);
  outline-offset: 0;
}

/* Cassette result cards in search results */
.cassette-result {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr);
  gap: 0 0.85rem;
  align-items: center;
  text-align: left;
  width: 100%;
  background: var(--paper);
  border: var(--border-width) solid var(--ink);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-chunky);
  padding: 0.75rem 1rem;
  cursor: pointer;
  color: var(--ink);
  font: inherit;
  /* Override default .cassette tilt — search results stay flat */
  transform: none;
  transition: translate 60ms ease, box-shadow 60ms ease;
  margin-bottom: 4px;
  margin-right: 4px;
}
.cassette-result:hover {
  translate: -2px -2px;
  box-shadow: 6px 6px 0 var(--ink);
}
.cassette-result:active {
  translate: 2px 2px;
  box-shadow: 0 0 0 var(--ink);
  background: var(--acid);
}
.cassette-result img {
  width: 64px;
  height: 64px;
  object-fit: cover;
  border-radius: 4px;
  border: 1px solid var(--bone);
  grid-row: 1 / span 2;
  align-self: center;
  flex-shrink: 0;
}
.cassette-result__meta {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  min-width: 0;
}
.cassette-result__title {
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.01em;
  overflow-wrap: anywhere;
}
.cassette-result__artist {
  font-size: 0.8rem;
  color: var(--smoke);
  overflow-wrap: anywhere;
}

/* Submitted-state pick card — same layout as a result, without click affordance */
.submit-pick {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr);
  gap: 0 0.85rem;
  align-items: center;
  width: 100%;
  padding: 0.75rem 1rem;
  margin-top: 0.75rem;
  cursor: default;
  transform: none;
}
.submit-pick img {
  width: 64px;
  height: 64px;
  object-fit: cover;
  border-radius: 4px;
  border: 1px solid var(--bone);
  grid-row: 1 / span 2;
  align-self: center;
}

/* ------------------------------------------------------------
   2B-4. VOTE SCREEN
   ------------------------------------------------------------ */

/* Direction line */
.vote-direction {
  font-style: italic;
  color: var(--smoke);
  margin: 0 0 1rem;
  font-size: 0.9rem;
}

/* CSS grid for cassette vote cards */
.vote-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(240px, 100%), 1fr));
  gap: 1.5rem;
  list-style: none;
  padding: 0;
  margin: 0;
}

/* Self-pick sticker overlay on vote cards — pinned bottom-right, clear of title */
.vote-self-sticker {
  position: absolute;
  bottom: 0.4rem;
  right: 0.5rem;
  top: auto;
  font-size: 0.65rem;
  z-index: 5;
}

/* Ensure vote cards are positioned for absolute children */
.vote-grid .vote-card {
  position: relative;
}

/* ------------------------------------------------------------
   2B-5. RESULTS SCREEN
   ------------------------------------------------------------ */

/* Empty round */
.results-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  padding: 2rem 0;
  color: var(--smoke);
}
.results-empty__caption {
  font-size: 1.4rem;
  color: var(--smoke);
  margin: 0;
}
/* Standard icon image size — 200×200 max, intrinsic aspect preserved.
   Apply this size convention to any new icon assets dropped into /static/img/. */
.results-empty__char,
.icon-img {
  width: auto;
  height: auto;
  max-width: 200px;
  max-height: 200px;
  display: block;
}

/* ------------------------------------------------------------
   BANGER OF THE ROUND BANNER
   One-per-round celebration block. Sits between topic recap and
   the cassette list. Acid slab + tilted mascot + display headline +
   song(s). On ties, headline pluralizes and all winning
   titles are listed in the songs line.
   ------------------------------------------------------------ */
.round-banger-banner {
  display: grid;
  grid-template-columns: minmax(140px, 34%) minmax(0, 1fr);
  align-items: center;
  gap: clamp(1rem, 3cqw, 1.75rem);
  padding: 0.9rem 1.25rem;
  margin: 1.25rem 0 1.5rem;
  background: var(--acid);
  color: var(--ink);
  border: var(--border-width) solid var(--ink);
  box-shadow: var(--shadow-chunky);
  /* Override .slab base typographic defaults — copy is handled by inner elements. */
  font-size: 1rem;
  line-height: 1.2;
  font-weight: 400;
  font-family: var(--font-body);
  /* Allow the offset shadow to breathe without clipping. */
  margin-right: 4px;
}

/* Banger mascot's own stamp-in keyframes — the global stamp-in hard-codes
   rotate(-12deg), so we use a -6deg variant to match the sticker tilt family. */
@keyframes banger-stamp-in {
  0%   { transform: rotate(-6deg) scale(0);    opacity: 0; }
  70%  { transform: rotate(-6deg) scale(1.08); opacity: 1; }
  100% { transform: rotate(-6deg) scale(1);    opacity: 1; }
}

.round-banger-banner__char {
  width: min(100%, clamp(140px, 28cqw, 240px));
  height: auto;
  display: block;
  justify-self: center;
  filter: drop-shadow(3px 3px 0 var(--ink));
  transform: rotate(-6deg);
  transform-origin: center;
  animation: banger-stamp-in 420ms cubic-bezier(0.175, 0.885, 0.32, 1.275) both;
  pointer-events: none;
  user-select: none;
}

.round-banger-banner__copy {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  min-width: 0;
}

.round-banger-banner__label {
  margin: 0;
  font-size: clamp(1.35rem, 5cqw, 2rem);
  line-height: 0.95;
  text-transform: uppercase;
  overflow-wrap: anywhere;
}

.round-banger-banner__songs {
  margin: 0;
  font-size: clamp(1rem, 3.4cqw, 1.45rem);
  line-height: 1.12;
  color: var(--ink);
  word-break: break-word;
}

/* Tied winners — render as a stacked list. Each song gets its own line so
   long titles (esp. with "feat." credits) wrap within their own block instead
   of crashing into the next winner. Slightly smaller font keeps a 3-way tie
   visually contained. */
.round-banger-banner__songs--multi {
  list-style: none;
  padding: 0;
  font-size: clamp(0.95rem, 2.9cqw, 1.25rem);
  line-height: 1.15;
}

.round-banger-banner__song + .round-banger-banner__song {
  margin-top: 0.25em;
}

.round-banger-banner__song::before {
  content: "✦ ";
  margin-right: 0.05em;
  /* Sparkle prefix is part of the wordmark family — keep it ink-colored
     so it reads as a list marker, not decoration. */
}

/* Results rows layout: cassette left, bar right */
.results-rows {
  list-style: none;
  padding: 0;
  margin: 0.5rem 0 1rem;
  display: grid;
  gap: 1.25rem;
}

.result-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 1rem;
  align-items: center;
  position: relative;
}
.result-row > .result-card     { grid-column: 1; }
.result-row > .result-bar-wrap { grid-column: 2; }

/* Winner row highlight */
.result-row--winner .result-card {
  border-color: var(--acid);
  box-shadow: 4px 4px 0 var(--acid);
}

/* Per-row BANGER pill — corner sticker on each winning cassette.
   Sits in the cassette's top-right, slightly poking out for badge feel. */
.result-row__banger-pill {
  position: absolute;
  top: -0.5rem;
  right: -0.4rem;
  z-index: 3;
  font-size: 0.62rem;
  letter-spacing: 0.08em;
  transform: rotate(4deg);
  box-shadow: 2px 2px 0 var(--ink);
}

/* Result card (cassette variant) */
.result-card.cassette {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr) auto;
  gap: 0 0.85rem;
  align-items: center;
  transform: none;
  position: relative;
}

.result-card .meta {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  min-width: 0;
}
.result-card .meta .display {
  font-size: 0.95rem;
  line-height: 1.1;
}
.result-card .meta .num {
  font-size: 0.78rem;
  color: var(--smoke);
}
.result-card .picker {
  color: var(--smoke);
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  line-height: 1.25;
  margin-top: 0.15rem;
  text-transform: uppercase;
}

/* Winner sticker — absolute inside the card so it can't be clipped by the
   row gap or any container overflow. Sits in the upper-right padding area. */
.result-winner-sticker {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  font-size: 0.65rem;
  z-index: 5;
}

/* Vote bar + count — right column */
.result-bar-wrap {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-width: 120px;
}

/* ------------------------------------------------------------
   2B-5a. VOTE BAR
   Acid-lime horizontal bar. --votes: integer.
   24px per vote, max 200px. Collapses gracefully at 0 votes.
   ------------------------------------------------------------ */
.vote-bar {
  height: 14px;
  background: var(--acid);
  border: var(--border-width) solid var(--ink);
  border-radius: 2px;
  width: min(calc(var(--votes, 0) * 24px), 200px);
  min-width: 4px;
  transition: width 400ms cubic-bezier(0.25, 0.46, 0.45, 0.94);
  flex-shrink: 0;
}

.vote-bar-count {
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--ink);
  min-width: 1.5ch;
  text-align: right;
}

/* Countdown */
.results-countdown {
  margin-top: 1.5rem;
  font-size: 0.8rem;
  letter-spacing: 0.04em;
}

/* ------------------------------------------------------------
   2B-6. GAME OVER SCREEN
   ------------------------------------------------------------ */

.game-over-slab {
  padding: 3.5rem 2rem 2.5rem;
}

.game-over-label {
  font-size: clamp(3rem, 8vw, 6rem);
  font-weight: 800;
  line-height: 0.9;
  letter-spacing: -0.04em;
  color: var(--paper);
  margin: 0 0 1.25rem;
}

.game-over-winner-row {
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 0.75rem;
}

.game-over-winner-sticker {
  font-size: 1.1rem;
  padding: 0.35em 0.85em;
  background: var(--acid);
  color: var(--ink);
  border-color: var(--ink);
}

.game-over-winner-char {
  width: auto;
  height: auto;
  max-width: 200px;
  max-height: 200px;
  display: block;
  filter: drop-shadow(2px 2px 0 var(--ink));
}

.game-over-score {
  font-size: 0.9rem;
  color: rgba(255, 246, 233, 0.65);
  margin: 0;
  font-family: var(--font-mono);
}

/* Tie names — only renders when 2+ players are tied for first.
   Display-type names with acid sparkle separators on the cobalt slab. */
.game-over-tie-names {
  font-family: var(--font-display);
  font-size: clamp(1.25rem, 3vw, 2rem);
  line-height: 1.05;
  letter-spacing: -0.01em;
  color: var(--paper);
  margin: 0 0 0.75rem;
  word-break: break-word;
}

.game-over-tie-sep {
  color: var(--acid);
  margin: 0 0.15em;
}

.game-over-section-label {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--smoke);
  margin: 0 0 0.75rem;
}

/* Winner row in final scoreboard gets hot fill */
.scoreboard.final .scoreboard-winner {
  background: var(--hot);
  color: var(--paper);
  border-color: var(--hot);
}
.scoreboard.final .scoreboard-winner::before {
  color: var(--paper);
}
.scoreboard.final .scoreboard-winner .score {
  color: var(--paper);
}

/* CTA row */
.game-over-ctas {
  display: flex;
  gap: 0.75rem;
  flex-wrap: wrap;
  margin: 1.5rem 0;
}

/* Bottom marquee strip */
.game-over-marquee {
  border-top: var(--border-width) solid var(--ink);
  padding: 0.6rem 0;
  background: var(--bone);
}

/* Responsive — stack below 600px */
@media (max-width: 600px) {
  .topbar {
    align-items: center;
    flex-wrap: wrap;
    gap: 0.45rem 0.75rem;
    padding: 0.55rem 0.85rem;
  }
  .brand {
    flex-basis: 100%;
  }
  .lobby-code {
    margin-left: 0;
  }
  .timer .label {
    display: none;
  }
  .slab {
    padding: 2rem 1rem;
  }
  .hero-slab {
    min-height: 17rem;
    padding: 1.75rem 1rem 4.75rem;
  }
  .hero-wordmark {
    font-size: clamp(2rem, 10.5vw, 2.6rem);
    max-width: calc(100vw - 2rem);
  }
  .hero-kicker {
    left: 1rem;
    right: auto;
    bottom: 1rem;
    max-width: calc(100% - 9.5rem);
  }
  .landing-body,
  .lobby-grid,
  .inner {
    padding-left: 1rem;
    padding-right: 1rem;
  }
  .stage-card,
  .rail,
  .card,
  .cassette {
    padding: 1rem;
  }
  .lobby-code-slab {
    padding: 1.25rem 0.75rem;
  }
  .lobby-code-giant {
    font-size: clamp(2.5rem, 15vw, 3.5rem);
    letter-spacing: 0.12em;
    text-indent: 0.12em;
  }
  .config .row {
    display: grid;
    grid-template-columns: 1fr;
  }
  .submit-confirmed,
  .submit-spectator-banner,
  .voted-banner,
  .lobby-waiting-guest {
    align-items: center;
    flex-direction: column;
    text-align: center;
  }
  .cassette-result,
  .submit-pick,
  .vote-card,
  .result-card.cassette {
    grid-template-columns: 48px minmax(0, 1fr);
    gap: 0 0.65rem;
    padding: 0.75rem;
  }
  .cassette-result img,
  .submit-pick img,
  .vote-card img,
  .result-card img {
    width: 48px;
    height: 48px;
  }
  .vote-card .card-actions,
  .result-card > .favorite-song-btn {
    grid-column: 1 / -1;
    justify-self: end;
    margin-top: 0.55rem;
  }
  .card-actions {
    flex-direction: row;
    align-items: center;
    justify-content: flex-end;
  }
  .vote-grid {
    grid-template-columns: 1fr;
    gap: 0.9rem;
  }
  .result-row {
    grid-template-columns: 1fr;
  }
  .result-row > .result-card,
  .result-row > .result-bar-wrap {
    grid-column: auto;
  }
  .result-bar-wrap {
    min-width: unset;
  }
  .round-banger-banner {
    grid-template-columns: 1fr;
    align-items: center;
    text-align: center;
    gap: 0.75rem;
    padding: 1rem 1rem 1.25rem;
  }
  .round-banger-banner__char {
    width: min(220px, 70vw);
  }
  .saved-song-row {
    grid-template-columns: 48px minmax(0, 1fr);
  }
  .saved-song-row img {
    width: 48px;
    height: 48px;
  }
  .saved-song-actions {
    grid-column: 1 / -1;
    justify-content: space-between;
  }
  .saved-song-actions audio {
    max-width: none;
    width: min(260px, calc(100vw - 5rem));
  }
  .game-over-slab {
    padding: 1.75rem 1rem 1.5rem;
  }
  .game-over-label {
    font-size: clamp(2.25rem, 14vw, 3rem);
  }
  .game-over-winner-sticker {
    font-size: 0.9rem;
    white-space: normal;
    overflow-wrap: anywhere;
  }
  .game-over-ctas {
    flex-direction: column;
  }
  .game-over-ctas .btn-chunky {
    width: 100%;
    justify-content: center;
  }
}
