/* ==========================================================================
   Shamaz — design tokens
   Re-skinned to match the surya.place desktop theme: same pastel
   sky-gradient backdrop, window chrome (light panels, #8f8f9a borders,
   drop shadows), Tahoma/Segoe UI type, and the site's blue-for-interaction
   / peach-for-brand accent split. Vinyl/K-pop motif kept only where it's
   game-functional (seek bar, play button, confetti) — everything else now
   reads as one more window on the desktop.
   ========================================================================== */

:root {
  color-scheme: light;

  --bg: #eef1f6;
  --bg-elevated: #f4f2f0;
  --bg-inset: #eceaf2;
  --border: #8f8f9a;
  --border-soft: #c7c5d0;

  /* Warm "brand" accent — the site's titlebar-peach / folder-peach family. */
  --gold: #e5934a;
  --gold-dim: #d9903c;
  --gold-soft: rgba(229, 147, 74, 0.16);

  /* Cool "interactive" accent — the site's hover/selection/focus blue. */
  --accent-blue: #6f9ce8;
  --accent-blue-dim: #4a78d6;
  --accent-blue-soft: rgba(111, 156, 232, 0.22);

  --ink: #3a3a4a;
  --ink-muted: #83839a;

  --good: #4caf7d;
  --good-soft: rgba(76, 175, 125, 0.14);
  --bad: #e2636f;
  --bad-soft: rgba(226, 99, 111, 0.14);

  --team-red: var(--bad);
  --team-blue: var(--accent-blue);

  --ring-track: #e4e2e0;

  /* Surfaces that were hardcoded to white/grey — themed so dark mode can
     re-key them alongside everything else. */
  --input-bg: #fff;
  --btn-ghost-start: #ffffff;
  --btn-ghost-end: #dfe3ec;
  --btn-ghost-border: #9aa0b0;
  --btn-ghost-hover-end: #ffd3e6;
  --btn-ghost-hover-border: #e284ac;

  --bg-gradient: linear-gradient(135deg, #a9c9ec 0%, #f5c6d8 40%, #f7cf9e 100%);

  --font-display: 'Tahoma', 'Segoe UI', Verdana, sans-serif;
  --font-body: 'Tahoma', 'Segoe UI', Verdana, sans-serif;
  --font-mono: 'Courier New', monospace;

  --radius-lg: 6px;
  --radius-md: 4px;
  --radius-pill: 999px;

  /* One height for every interactive control. Buttons, text inputs, selects
     and number inputs had independently-derived heights (46/48/44/44px), so
     any row mixing them stair-stepped. Set once here, applied via min-height
     so a control can still grow for wrapped text. */
  --control-h: 48px;

  --shadow-window: 4px 6px 18px rgba(0, 0, 0, 0.25);
  --shadow-window-soft: 2px 3px 10px rgba(0, 0, 0, 0.18);
}

/* ---- Dark mode ------------------------------------------------------------
   Same token set, re-keyed for a dark desktop. Applies when the toggle sets
   data-theme explicitly, or — with no explicit choice — when the OS is set
   to dark (":not([data-theme=\"light\"])" keeps an explicit "light" choice
   from being overridden by the system preference). The two blocks below
   intentionally duplicate the same values rather than nesting the media
   query, to keep the CSS parseable without relying on native nesting. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;

    --bg: #1c1d26;
    --bg-elevated: #262732;
    --bg-inset: #20212c;
    --border: #4a4b5c;
    --border-soft: #383a4a;

    --gold: #e5934a;
    --gold-dim: #f0a868;
    --gold-soft: rgba(229, 147, 74, 0.22);

    --accent-blue: #7fa8f0;
    --accent-blue-dim: #a8c4f5;
    --accent-blue-soft: rgba(127, 168, 240, 0.24);

    --ink: #e6e6ee;
    --ink-muted: #9797ad;

    --good: #6fd0a0;
    --good-soft: rgba(111, 208, 160, 0.18);
    --bad: #f0838d;
    --bad-soft: rgba(240, 131, 141, 0.18);

    --team-red: var(--bad);
    --team-blue: var(--accent-blue);

    --ring-track: #333442;

    --input-bg: #2b2c38;
    --btn-ghost-start: #3a3b48;
    --btn-ghost-end: #2a2b36;
    --btn-ghost-border: #52546a;
    --btn-ghost-hover-end: #4a2e3c;
    --btn-ghost-hover-border: #e284ac;

    --bg-gradient: linear-gradient(135deg, #1c2436 0%, #2c1f2e 40%, #2e2418 100%);

    --shadow-window: 4px 6px 18px rgba(0, 0, 0, 0.55);
    --shadow-window-soft: 2px 3px 10px rgba(0, 0, 0, 0.4);
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;

  --bg: #1c1d26;
  --bg-elevated: #262732;
  --bg-inset: #20212c;
  --border: #4a4b5c;
  --border-soft: #383a4a;

  --gold: #e5934a;
  --gold-dim: #f0a868;
  --gold-soft: rgba(229, 147, 74, 0.22);

  --accent-blue: #7fa8f0;
  --accent-blue-dim: #a8c4f5;
  --accent-blue-soft: rgba(127, 168, 240, 0.24);

  --ink: #e6e6ee;
  --ink-muted: #9797ad;

  --good: #6fd0a0;
  --good-soft: rgba(111, 208, 160, 0.18);
  --bad: #f0838d;
  --bad-soft: rgba(240, 131, 141, 0.18);

  --team-red: var(--bad);
  --team-blue: var(--accent-blue);

  --ring-track: #333442;

  --input-bg: #2b2c38;
  --btn-ghost-start: #3a3b48;
  --btn-ghost-end: #2a2b36;
  --btn-ghost-border: #52546a;
  --btn-ghost-hover-end: #4a2e3c;
  --btn-ghost-hover-border: #e284ac;

  --bg-gradient: linear-gradient(135deg, #1c2436 0%, #2c1f2e 40%, #2e2418 100%);

  --shadow-window: 4px 6px 18px rgba(0, 0, 0, 0.55);
  --shadow-window-soft: 2px 3px 10px rgba(0, 0, 0, 0.4);
}

.user-avatar {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  object-fit: cover;
  vertical-align: middle;
  display: inline-block;
  margin-right: 6px;
  background-color: var(--bg-inset);
  border: 1px solid var(--border);
}
.user-avatar-fallback {
  display: inline-block;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  vertical-align: middle;
  margin-right: 6px;
  background-color: var(--bg-inset);
  border: 1px solid var(--border);
}

* {
  box-sizing: border-box;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}

html, body {
  margin: 0;
  padding: 0;
}

/* Same diagonal pastel sky + drift animation as the desktop's root
   stylesheet (assets/css/style.css), so a Shamaz tab feels like part of
   the same desktop rather than a separate site. */
body {
  background: var(--bg-gradient);
  background-size: 200% 200%;
  animation: driftBg 22s ease-in-out infinite;
  color: var(--ink);
  font-family: var(--font-body);
  min-height: 100dvh;
  display: flex;
  justify-content: center;
  padding: 2rem 1rem 16rem;
  -webkit-font-smoothing: antialiased;
}

/* The `hidden` attribute is how JS toggles elements off (e.g. the locked-out
   daily view hiding the song chip / points indicator / seek bar). Several
   components below (`.topbar-chip`, `.points-indicator`, `.seek-bar`) set an
   explicit `display` unconditionally, which — same specificity, later origin
   — wins over the UA's `[hidden] { display: none }` default and leaves the
   element visible. Force it back so `el.hidden = true` always actually hides. */
[hidden] {
  display: none !important;
}

/* Hide scrollbar but keep functionality */
html, body {
  -ms-overflow-style: none;  /* IE and Edge */
  scrollbar-width: none;  /* Firefox */
}
html::-webkit-scrollbar, body::-webkit-scrollbar {
  display: none;
}

@keyframes driftBg {
  0%, 100% { background-position: 0% 0%; }
  50% { background-position: 100% 60%; }
}

.page {
  width: 100%;
  max-width: 440px;
}

/* ---- Top bar: home + volume ------------------------------------------- */

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 1.25rem;
  font-size: 0.9rem;
}

.topbar a {
  color: var(--ink-muted);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  transition: color 0.15s ease;
}

.topbar a:hover,
.topbar a:focus-visible {
  color: var(--accent-blue-dim);
}

/* ---- Card shell (styled like a desktop window) -------------------------- */

.card {
  position: relative;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 1.75rem 1.5rem 2rem;
  box-shadow: var(--shadow-window);
}

/* A thin "titlebar" strip standing in for real window chrome, using the
   same three-hue gradient as the desktop background. */
.card::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 6px;
  background: linear-gradient(90deg, #6f9ce8, #ee9fc0 50%, #f3b871);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
}

.eyebrow {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gold-dim);
  margin: 0 0 0.4rem;
}

h1 {
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  font-size: clamp(1.9rem, 6vw, 2.4rem);
  line-height: 1;
  margin: 0 0 0.5rem;
  color: var(--ink);
}

.subtitle {
  color: var(--ink-muted);
  font-size: 0.95rem;
  margin: 0 0 1.5rem;
}

/* ---- Seek-bar stage indicator -------------------------------------------
   Each stage is a segment sized proportionally to that stage's actual
   snippet duration (a 16s stage is visually ~16x wider than a 1s stage), so
   the bar reads as a real timeline of cumulative snippet length. The active
   stage's fill sweeps left-to-right over its real playback duration, like a
   video seek bar's progress indicator; passed stages sit fully filled. */

.stage-bar,
.seek-bar {
  display: flex;
  gap: 6px;
  margin: 0 0 1.5rem;
}

.seek-segment {
  height: 10px;
  min-width: 6px;
  border-radius: var(--radius-pill);
  background: var(--ring-track);
  overflow: hidden;
  transition: box-shadow 0.25s ease, background 0.25s ease;
}

/* The stage you're currently positioned on (fresh load, or just after
   Skip) — a visibly different shade from both "already passed" (full
   gold fill) and "not reached yet" (plain dark track), so Skip has an
   obvious, immediate effect. */
.seek-segment.is-current {
  background: var(--gold-soft);
  box-shadow: 0 0 0 1px var(--gold-dim) inset;
}

.seek-fill {
  height: 100%;
  width: 0%;
  background: var(--gold);
  box-shadow: 0 0 12px rgba(229, 147, 74, 0.55);
  border-radius: var(--radius-pill);
}

/* ---- Points-available indicator -----------------------------------------
   Mirrors Scoring::STAGE_POINTS client-side: a number plus a shrinking bar
   that ticks down every time the player advances to the next clue, so the
   cost of "one more clue" is visible before they ask for it. */

.points-indicator {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin: -0.75rem 0 1.25rem;
}

.points-indicator-label {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-muted);
  white-space: nowrap;
}

.points-indicator-track {
  flex: 1;
  height: 6px;
  border-radius: var(--radius-pill);
  background: var(--ring-track);
  overflow: hidden;
}

.points-indicator-fill {
  height: 100%;
  width: 100%;
  background: var(--indicator-color, var(--gold));
  border-radius: var(--radius-pill);
  /* The width change itself is the "shrinking bar" — animate it so a stage
     advance visibly sweeps down instead of jump-cutting. */
  transition: width 0.5s ease, background-color 0.5s ease;
}

.points-indicator-value {
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: 0.85rem;
  color: var(--indicator-color, var(--gold));
  min-width: 3ch;
  text-align: right;
  transition: color 0.5s ease;
}

/* Toggled briefly on every update() call so even a same-value refresh
   (e.g. re-rendering the current stage) still reads as a change. */
.points-indicator.did-update .points-indicator-value {
  animation: points-value-pulse 0.45s ease;
}

@keyframes points-value-pulse {
  0% { transform: scale(1); }
  40% { transform: scale(1.25); color: var(--ink); }
  100% { transform: scale(1); }
}

/* ---- The record: signature play button ---------------------------------
   A circular button sits like a record label. While idle it holds a slow
   ambient glow pulse; while a snippet is actually playing (.is-playing)
   a dashed ring spins around it like a turntable in motion. */

.player-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.6rem;
  margin: 0.5rem 0 1.75rem;
}

.play-btn {
  position: relative;
  width: 84px;
  height: 84px;
  /* A <button> in both single-player and multiplayer now, so it inherits the
     base button padding/min-height — neither of which suits a fixed circle. */
  min-height: 0;
  padding: 0;
  border-radius: 50%;
  border: 2px solid var(--gold-dim);
  background: radial-gradient(circle at 35% 30%, #ffd9ad, var(--gold) 60%);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: 0 0 0 0 rgba(229, 147, 74, 0.5);
  animation: pulse-glow 2.6s ease-in-out infinite;
}

/* An inline SVG triangle rather than the ▶ glyph it replaces — glyph
   vertical metrics vary across fonts/platforms and made the icon look
   vertically squashed or off-center on some displays. Fixed pixel sizing
   here renders identically everywhere. The 3px left margin re-centers the
   triangle's visual weight (a right-pointing shape sits left-heavy in a
   perfectly centered box). */
.play-btn svg {
  display: block;
  width: 30px;
  height: 30px;
  margin-left: 3px;
}

/* The multiplayer vinyl-note glyph isn't an SVG icon like the single-player
   play button — keep it centered on its own font metrics. (This rule used to
   target #host-vinyl, an id that exists on no page, so it never applied.) */
#vinyl.play-btn {
  font-size: 1.6rem;
}

.play-btn::before {
  content: '';
  position: absolute;
  inset: -10px;
  border-radius: 50%;
  border: 2px dashed var(--accent-blue-dim);
  opacity: 0;
  animation: none;
}

.play-btn.is-playing::before {
  opacity: 0.7;
  animation: spin 3s linear infinite;
}

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

@keyframes pulse-glow {
  0%, 100% { box-shadow: 0 0 0 0 rgba(229, 147, 74, 0.35); }
  50% { box-shadow: 0 0 0 14px rgba(229, 147, 74, 0); }
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

.topbar-chip {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  color: var(--ink);
  letter-spacing: 0.04em;
  background: var(--bg-inset);
  border: 1px solid var(--border-soft);
  padding: 0.3rem 0.9rem;
  border-radius: var(--radius-pill);
  transition: transform 0.2s ease, background 0.2s ease, border-color 0.2s ease;
}

/* Toggled briefly whenever the chip's text actually changes, so a change
   that reads identically to the previous state (e.g. streak going 0 -> 0)
   doesn't look frozen. */
.topbar-chip.did-update {
  animation: chip-pulse 0.45s ease;
}

@keyframes chip-pulse {
  0% { transform: scale(1); background: var(--bg-inset); border-color: var(--border-soft); }
  40% { transform: scale(1.14); background: var(--gold-soft); border-color: var(--gold-dim); }
  100% { transform: scale(1); background: var(--bg-inset); border-color: var(--border-soft); }
}

/* ---- Volume ------------------------------------------------------------ */

.volume-row {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  color: var(--ink-muted);
  font-size: 0.8rem;
  margin: 0 0 1.25rem;
}

.volume-row input[type="range"] {
  flex: 1;
  accent-color: var(--accent-blue);
}

/* ---- Inputs & buttons ---------------------------------------------------- */

input[type="text"] {
  width: 100%;
  min-height: var(--control-h);
  box-sizing: border-box;
  padding: 0.85rem 1.1rem;
  border-radius: var(--radius-md);
  border: 1px solid var(--border-soft);
  background: var(--input-bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 1rem;
  margin-bottom: 0.75rem;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

input[type="text"]:focus-visible {
  outline: none;
  border-color: var(--accent-blue);
  box-shadow: 0 0 0 2px var(--accent-blue-soft);
}

input[type="text"]::placeholder {
  color: var(--ink-muted);
}

/* ---- Autocomplete -------------------------------------------------------- */

.autocomplete-wrap {
  position: relative;
}

/* Only reserve room for the overlaid Guess/clear controls when they are
   actually present. An unscoped rule left 8rem of dead padding in any wrap
   without an .input-actions overlay. */
.autocomplete-wrap:has(.input-actions) input[type="text"] {
  padding-right: 8rem;
}

.input-actions {
  position: absolute;
  top: 0;
  right: 0.5rem;
  height: calc(100% - 0.75rem);
  display: flex;
  align-items: center;
  gap: 0.4rem;
}

/* Overlaid inside the field, so it must be shorter than a standalone
   control — the shared --control-h would fill the whole input. */
.guess-btn-inline {
  min-height: 0;
  padding: 0.55rem 1rem;
}

.clear-btn-inline {
  width: 1.9rem;
  height: 1.9rem;
  min-height: 0;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: transparent;
  color: var(--ink-muted);
  border: none;
  font-size: 1.2rem;
  line-height: 1;
}

.clear-btn-inline:hover:not(:disabled) {
  color: var(--ink);
  background: var(--bg-inset);
}

.autocomplete-dropdown {
  position: absolute;
  top: calc(100% - 0.75rem + 2px);
  left: 0;
  right: 0;
  z-index: 20;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-window);
  max-height: 260px;
  overflow-y: auto;
}

.autocomplete-item {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.5rem 1rem;
  cursor: pointer;
  font-size: 0.92rem;
}

.autocomplete-item:hover,
.autocomplete-item.is-active {
  background: var(--accent-blue-soft);
}

.autocomplete-thumb {
  width: 36px;
  height: 36px;
  border-radius: 6px;
  object-fit: cover;
  flex-shrink: 0;
  background: var(--bg-inset);
}

.autocomplete-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.autocomplete-title {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.autocomplete-item .autocomplete-artist {
  color: var(--ink-muted);
  font-size: 0.78rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ---- Reveal card (correct guess / failed reveal) ------------------------ */

.reveal-card {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-top: 1.25rem;
  padding: 0.85rem;
  background: var(--bg-inset);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-md);
}

/* A stack of reveal-cards (e.g. Daily Challenge's history of past songs),
   as opposed to a single-slot reveal-card. */
.reveal-history {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  margin-top: 1.25rem;
}

.reveal-history .reveal-card {
  margin-top: 0;
}

.reveal-card.is-correct {
  border-color: rgba(76, 175, 125, 0.4);
}

.reveal-card.is-wrong {
  border-color: rgba(226, 99, 111, 0.4);
}

.reveal-cover {
  width: 64px;
  height: 64px;
  border-radius: 8px;
  object-fit: cover;
  flex-shrink: 0;
  background: var(--bg-elevated);
}

.reveal-info {
  min-width: 0;
}

.reveal-status {
  margin: 0 0 0.15rem;
  font-size: 0.78rem;
  font-family: var(--font-mono);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

.reveal-card.is-correct .reveal-status {
  color: var(--good);
}

.reveal-card.is-wrong .reveal-status {
  color: var(--bad);
}

.reveal-title {
  margin: 0;
  font-weight: 700;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.reveal-artist {
  margin: 0.1rem 0 0;
  color: var(--ink-muted);
  font-size: 0.85rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.reveal-links {
  margin: 0.4rem 0 0;
  display: flex;
  gap: 0.6rem;
}

.reveal-link {
  display: inline-flex;
  color: var(--ink-muted);
  transition: color 0.15s ease;
}

.reveal-link svg {
  width: 20px;
  height: 20px;
}

.reveal-link:hover {
  color: var(--accent-blue-dim);
}

/* ---- Game-over summary (end of a Daily/Endless run) --------------------- */
/* Rendered inline in .card in place of the gameplay controls — the run is
   over, so the seek bar, player, guess box, and action buttons are hidden
   in favor of the summary + leaderboard below. */

.card.game-over-active #guest-note,
.card.game-over-active #stage-bar,
.card.game-over-active #points-indicator,
.card.game-over-active .player-wrap,
.card.game-over-active .volume-row,
.card.game-over-active .autocomplete-wrap,
.card.game-over-active > .button-row,
.card.game-over-active #result {
  display: none;
}

.game-over-card {
  margin-top: 1.5rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--border-soft);
}

.game-over-summary {
  margin: 0 0 1rem;
  font-size: 1.1rem;
  font-weight: 700;
}

.game-over-actions {
  margin-top: 1.25rem;
}

.game-over-menu-btn,
.game-over-play-again-btn {
  display: inline-block;
  text-decoration: none;
  text-align: center;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 0.95rem;
  border: none;
  border-radius: var(--radius-pill);
  padding: 0.8rem 1.4rem;
  cursor: pointer;
}

/* ---- Give up (distinct from Skip: reveals the answer and moves on) ----- */

.btn-danger {
  background: transparent;
  color: var(--bad);
  border: 1px solid rgba(226, 99, 111, 0.4);
}

.btn-danger:hover:not(:disabled) {
  background: var(--bad-soft);
  border-color: var(--bad);
}

/* ---- Confetti burst (correct-guess celebration) ------------------------- */

.confetti-piece {
  position: fixed;
  width: 8px;
  height: 8px;
  border-radius: 2px;
  pointer-events: none;
  z-index: 999;
  top: 0;
  left: 0;
  animation: confetti-burst 0.9s ease-out forwards;
}

@keyframes confetti-burst {
  0% { transform: translate(-50%, -50%) rotate(0deg); opacity: 1; }
  100% { transform: translate(calc(-50% + var(--dx)), calc(-50% + var(--dy))) rotate(var(--rot)); opacity: 0; }
}

.button-row {
  display: flex;
  justify-content: center;
  gap: 0.6rem;
  flex-wrap: wrap;
}

.button-grid {
  display: flex !important;
  background: var(--bg-inset) !important;
  border: 1px solid var(--border-soft) !important;
  border-radius: var(--radius-lg) !important;
  padding: 0.35rem !important;
  gap: 0 !important;
  overflow-x: auto !important;
  scrollbar-width: none !important;
  flex-wrap: nowrap !important;
}

.button-grid::-webkit-scrollbar {
  display: none !important;
}

.button-grid button {
  flex: 1 !important;
  min-width: max-content !important;
  background: transparent !important;
  border: none !important;
  box-shadow: none !important;
  color: var(--ink-muted) !important;
  border-radius: var(--radius-md) !important;
  padding: 0.6rem 0.55rem !important;
  font-size: 0.78rem !important;
  white-space: nowrap !important;
  transition: all 0.2s ease !important;
  margin: 0 !important;
}

.button-grid button.btn-ghost {
  background: transparent !important;
  border: none !important;
  color: var(--ink-muted) !important;
}

.button-grid button.btn-primary {
  background: var(--bg-elevated) !important;
  color: var(--ink) !important;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1) !important;
  border: none !important;
}

.button-grid button:not(.btn-primary):hover {
  color: var(--ink) !important;
  background: rgba(0,0,0,0.03) !important;
}

button {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 0.95rem;
  border: none;
  border-radius: var(--radius-pill);
  min-height: var(--control-h);
  box-sizing: border-box;
  padding: 0.8rem 1.4rem;
  cursor: pointer;
  transition: transform 0.1s ease, filter 0.15s ease, background 0.15s ease;
}

button:active {
  transform: scale(0.97);
}

button:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* Primary CTA styled like the desktop's peach titlebar (titlebar-peach /
   folder-peach gradient stops), white text for contrast. */
.btn-primary {
  background: linear-gradient(180deg, #f3b871, #e5934a);
  border: 1px solid #d9903c;
  color: #fff;
}

.btn-primary:hover:not(:disabled) {
  filter: brightness(1.06);
}

/* Secondary action styled like the desktop's neutral window-control
   buttons (white-to-grey gradient, pink hover), so it reads as "chrome"
   rather than a competing brand color. */
.btn-ghost {
  background: linear-gradient(180deg, var(--btn-ghost-start), var(--btn-ghost-end));
  color: var(--ink);
  border: 1px solid var(--btn-ghost-border);
}

.btn-ghost:hover:not(:disabled) {
  color: var(--ink);
  background: linear-gradient(180deg, var(--btn-ghost-start), var(--btn-ghost-hover-end));
  border-color: var(--btn-ghost-hover-border);
}

/* Fallback for any bare <button> not yet given a variant class.
   NOTE: :not() takes its argument's specificity, so this selector is (0,5,1) —
   every class listed here must be excluded by name or the fallback will
   out-specify that class's own rules (see .mp-team-join's selected state). */
button:not(.btn-primary):not(.btn-ghost):not(.btn-danger):not(.tier-btn):not(.mp-team-join):not(.play-btn):not(.mp-hint):not(.clear-btn-inline) {
  background: linear-gradient(180deg, #f3b871, #e5934a);
  border: 1px solid #d9903c;
  color: #fff;
}

/* ---- Feedback / result banners ------------------------------------------ */

.result-banner {
  margin-top: 1.25rem;
  padding: 0.75rem 0.9rem;
  background: var(--bg-inset);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-md);
  font-size: 0.95rem;
  color: var(--ink-muted);
}

.result-banner.is-correct {
  color: var(--good);
  border-color: rgba(76, 175, 125, 0.4);
}

.result-banner.is-wrong {
  color: var(--bad);
  border-color: rgba(226, 99, 111, 0.4);
}

/* ---- Home page: mode picker -------------------------------------------- */

.mode-list {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  margin-top: 1.5rem;
}

.mode-card {
  display: block;
  padding: 1rem 1.2rem;
  border-radius: var(--radius-md);
  border: 1px solid var(--border-soft);
  background: var(--bg-inset);
  color: var(--ink);
  text-decoration: none;
  font-weight: 600;
  transition: border-color 0.15s ease, background 0.15s ease, transform 0.1s ease;
}

.mode-card:hover,
.mode-card:focus-visible {
  border-color: var(--accent-blue);
  background: var(--accent-blue-soft);
  transform: translateY(-1px);
}

.mode-card .mode-desc {
  display: block;
  font-weight: 400;
  font-size: 0.82rem;
  color: var(--ink-muted);
  margin-top: 0.2rem;
}

/* ---- Multiplayer specifics ---------------------------------------------- */

.room-code {
  font-family: var(--font-mono);
  font-size: 2rem;
  letter-spacing: 0.14em;
  color: var(--gold-dim);
  text-align: center;
  margin: 0.5rem 0 1.25rem;
}

.player-list {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin-bottom: 1.25rem;
}

.player-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.6rem 0.9rem;
  border-radius: var(--radius-md);
  background: var(--bg-inset);
  border: 1px solid var(--border-soft);
  font-size: 0.9rem;
}

.player-row .score {
  font-family: var(--font-mono);
  color: var(--gold-dim);
  font-weight: 600;
}

.player-row .lock-status {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.tier-btn {
  padding: 0.5rem 1rem;
  border-radius: var(--radius-pill);
  border: 1px solid var(--border-soft);
  background: transparent;
  color: var(--ink);
  cursor: pointer;
}

.tier-btn.is-selected {
  background: var(--accent-blue-soft);
  border-color: var(--accent-blue);
  color: var(--accent-blue-dim);
}

.stage-toggle-list {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin: 1rem 0;
}

.stage-toggle {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.5rem 0.9rem;
  border-radius: var(--radius-pill);
  border: 1px solid var(--border-soft);
  background: transparent;
  font-size: 0.9rem;
  font-family: var(--font-mono);
  color: var(--ink-muted);
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s, color 0.15s;
}

.stage-toggle:has(input:checked) {
  background: var(--accent-blue-soft);
  border-color: var(--accent-blue);
  color: var(--accent-blue-dim);
}

.stage-toggle input[type="checkbox"] {
  width: 15px;
  height: 15px;
  accent-color: var(--accent-blue);
  cursor: pointer;
}

.lock-tag {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  padding: 0.15rem 0.5rem;
  border-radius: var(--radius-pill);
  border: 1px solid var(--border-soft);
  color: var(--ink-muted);
}

.lock-tag.is-correct {
  color: var(--good);
  border-color: rgba(76, 175, 125, 0.4);
  background: var(--good-soft);
}

.lock-tag.is-gave-up {
  color: var(--bad);
  border-color: rgba(226, 99, 111, 0.4);
  background: var(--bad-soft);
}

.lock-tag.is-deciding {
  animation: pulse-text 1.6s ease-in-out infinite;
}

@keyframes pulse-text {
  0%, 100% { opacity: 0.55; }
  50% { opacity: 1; }
}

.status-line {
  font-family: var(--font-mono);
  font-size: 0.82rem;
  color: var(--ink-muted);
  margin-bottom: 1rem;
}

.status-row {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-top: 1rem;
  margin-bottom: 1rem;
}

.status-row .status-line {
  margin-bottom: 0;
}

.live-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--good);
  background: var(--good-soft);
  border: 1px solid rgba(76, 175, 125, 0.4);
  border-radius: var(--radius-pill);
  padding: 0.35rem 0.7rem 0.35rem 0.6rem;
}

.live-badge::before {
  content: '';
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--good);
  animation: pulse-glow 1.4s ease-in-out infinite;
}

/* ---- Confirm modal (in-theme replacement for window.confirm) ----------- */

.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(40, 38, 54, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  padding: 1rem;
  animation: modal-fade-in 0.15s ease;
}

/* .modal-overlay sets display:flex, which beats the UA [hidden] rule no matter
   the specificity — markup that toggles `hidden` needs this to stay hidden. */
.modal-overlay[hidden] {
  display: none;
}

.modal-card {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 1.5rem;
  max-width: 360px;
  width: 100%;
  box-shadow: var(--shadow-window);
  animation: modal-pop-in 0.18s ease;
}

.modal-message {
  margin: 0 0 1.25rem;
  color: var(--ink);
  font-size: 0.95rem;
  line-height: 1.4;
}

@keyframes modal-fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes modal-pop-in {
  from { opacity: 0; transform: scale(0.94); }
  to { opacity: 1; transform: scale(1); }
}

/* ---- Toast notifications ------------------------------------------------ */

.toast-container {
  position: fixed;
  top: 1rem;
  right: 1rem;
  z-index: 2000;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  max-width: 320px;
  pointer-events: none;
}

.toast {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-left: 3px solid var(--gold);
  border-radius: var(--radius-md);
  padding: 0.7rem 0.75rem;
  box-shadow: 0 16px 40px -12px rgba(0, 0, 0, 0.7);
  pointer-events: auto;
  animation: toast-in 0.2s ease;
}

.toast-error {
  border-left-color: var(--bad);
}

.toast-info {
  border-left-color: var(--gold);
}

.toast-message {
  flex: 1;
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 0.85rem;
  line-height: 1.35;
}

.toast-close {
  background: none;
  border: none;
  color: var(--ink-muted);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  padding: 0 0.15rem;
}

.toast-close:hover {
  color: var(--ink);
}

.toast-leaving {
  animation: toast-out 0.18s ease forwards;
}

@keyframes toast-in {
  from { opacity: 0; transform: translateY(-8px); }
  to { opacity: 1; transform: translateY(0); }
}

@keyframes toast-out {
  from { opacity: 1; transform: translateY(0); }
  to { opacity: 0; transform: translateY(-8px); }
}

/* ---------- Multiplayer ---------- */

/* Mobile-first: both roles are expected to be on a phone. */
.mp-section { margin-block: 1.25rem; }

/* Several .mp-* classes below set `display`, which beats the UA [hidden] rule
   no matter the specificity. Every element the multiplayer JS toggles with
   `hidden` needs its display restored here or it never actually hides. */
.mp-setup[hidden],
.mp-setup label[hidden],
.mp-scores[hidden],
.mp-standings[hidden],
.mp-room-actions[hidden],
.mp-team-bar[hidden],
.mp-rejoin[hidden] {
  display: none;
}

.mp-room-code {
  font-family: var(--font-mono);
  font-size: 2rem;
  letter-spacing: 0.25em;
  text-align: center;
  color: var(--gold);
}

.mp-teams {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.75rem;
}
/* Two columns, not three: "Unassigned" is no longer one of them. It is a
   staging tray you leave, not a team you can choose to sit in. */
@media (min-width: 40rem) {
  .mp-teams { grid-template-columns: repeat(2, 1fr); }
}

/* ---- Unassigned tray ----------------------------------------------------
   Holds players who have not picked yet. Visually subordinate to the two
   team columns, and it offers no join button of its own. */
.mp-tray {
  margin-bottom: 0.75rem;
  padding: 0.6rem 0.75rem;
  border: 1px dashed var(--border-soft);
  border-radius: var(--radius-md);
  background: var(--bg-inset);
}
.mp-tray[hidden] { display: none; }

.mp-tray-title {
  margin: 0 0 0.4rem;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-muted);
}

.mp-tray-players {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.mp-tray .mp-player {
  flex: 0 1 auto;
}

.mp-team {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--bg-inset);
  padding: 0.75rem;
  min-height: 5rem;
}
.mp-team[data-team="1"] { border-color: var(--team-red); }
.mp-team[data-team="2"] { border-color: var(--team-blue); }

.mp-team-title { font-size: 0.85rem; margin: 0 0 0.5rem; color: var(--ink-muted); }
.mp-team[data-team="1"] .mp-team-title { color: var(--team-red); }
.mp-team[data-team="2"] .mp-team-title { color: var(--team-blue); }

/* Tap target: joining a team is the player's primary lobby action. */
.mp-team-join {
  display: block;
  width: 100%;
  min-height: 2.75rem;
  margin-top: 0.5rem;
  border-radius: var(--radius-pill);
  border: 1px solid var(--border);
  background: var(--input-bg);
  color: var(--ink);
  font: inherit;
  cursor: pointer;
}
.mp-team-join[aria-pressed="true"] { border-color: var(--gold); color: var(--gold); }

.mp-player {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.35rem 0;
}

.mp-avatar {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  flex: 0 0 auto;
  object-fit: cover;
  background: var(--bg-inset);
  border: 2px solid var(--border);
}
.mp-avatar[data-team="1"] { border-color: var(--team-red); }
.mp-avatar[data-team="2"] { border-color: var(--team-blue); }

.mp-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mp-score { font-family: var(--font-mono); color: var(--gold); }

.mp-tag {
  font-size: 0.7rem;
  padding: 0.1rem 0.5rem;
  border-radius: var(--radius-pill);
  border: 1px solid var(--border);
  color: var(--ink-muted);
}
.mp-tag[data-state="correct"] { color: var(--good); border-color: var(--good); }
.mp-tag[data-state="gave_up"] { color: var(--bad); border-color: var(--bad); }
.mp-tag[data-state="locked_this_clue"] { color: var(--ink-muted); }

.mp-counters {
  display: flex;
  gap: 0.5rem;
  justify-content: center;
  flex-wrap: wrap;
  font-size: 0.9rem;
  color: var(--ink-muted);
}

/* Round status and team scores read as chips rather than loose text, so the
   live numbers are scannable at a glance mid-round. */
.mp-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.3rem 0.7rem;
  border-radius: var(--radius-pill);
  border: 1px solid var(--border-soft);
  background: var(--bg-inset);
  font-size: 0.8rem;
  line-height: 1.4;
  white-space: nowrap;
}

.mp-chip-value {
  color: var(--ink);
  font-family: var(--font-mono);
  font-weight: 700;
}

.mp-chip[data-kind="guessed"] { border-color: var(--good); color: var(--good); }
.mp-chip[data-kind="guessed"] .mp-chip-value { color: var(--good); }
.mp-chip[data-kind="ready"] { border-color: var(--gold); color: var(--gold); }
.mp-chip[data-kind="ready"] .mp-chip-value { color: var(--gold); }

.mp-counter-value { color: var(--ink); font-family: var(--font-mono); }

.mp-scores { display: flex; gap: 0.75rem; justify-content: center; flex-wrap: wrap; }

/* Team score pills carry the team colour as a tinted fill, not just text. */
.mp-scores .mp-chip[data-team="1"] {
  border-color: var(--team-red);
  color: var(--team-red);
  background: var(--bad-soft);
}
.mp-scores .mp-chip[data-team="1"] .mp-chip-value { color: var(--team-red); }
.mp-scores .mp-chip[data-team="2"] {
  border-color: var(--team-blue);
  color: var(--team-blue);
  background: var(--accent-blue-soft);
}
.mp-scores .mp-chip[data-team="2"] .mp-chip-value { color: var(--team-blue); }

/* ---- Room code bar ------------------------------------------------------
   Code and its copy button are one control, not two stacked blocks. */
.mp-code-bar {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.35rem 0.35rem 0.35rem 1rem;
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-pill);
  background: var(--bg-inset);
}
.mp-code-bar[hidden] { display: none; }

.mp-code-bar-label {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-muted);
}

.mp-code-bar-value {
  flex: 1 1 auto;
  font-family: var(--font-mono);
  font-size: 1.5rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  color: var(--gold);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Trailing copy control sits inside the bar, so it can be shorter than the
   shared --control-h without reintroducing a mismatched row. */
.mp-code-bar button {
  flex: 0 0 auto;
  min-height: 2.25rem;
  padding: 0.4rem 0.9rem;
  font-size: 0.8rem;
}

/* The phase buttons are mutually exclusive — only one is ever visible — so
   they share one full-width footprint instead of each sizing to its own
   label and landing at a different left edge. */
#start-btn,
#next-btn,
#newgame-btn {
  display: block;
  width: 100%;
  margin-top: 0.75rem;
}
#start-btn[hidden],
#next-btn[hidden],
#newgame-btn[hidden] {
  display: none;
}

/* ---- In-room header -----------------------------------------------------
   Replaces the page <h1> once a room exists: the big "Host a room" /
   "Join a room" titles are wayfinding for the entry screen only, and just
   eat vertical space (especially on a phone) once you are actually in one. */
.mp-room-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  flex-wrap: wrap;
  margin-bottom: 0.75rem;
}
.mp-room-head[hidden] { display: none; }

.mp-room-head-title {
  margin: 0;
  font-family: var(--font-display);
  font-size: 1.1rem;
  color: var(--ink);
}

.mp-room-head-sub {
  margin: 0;
  font-size: 0.8rem;
  color: var(--ink-muted);
}

/* ---- Join row -----------------------------------------------------------
   Code field + paste button. The old inline `display:flex` had no
   align-items, so the button stretched to 60px against a 48px field and
   hung 12px below it. */
.mp-join-row {
  display: flex;
  align-items: stretch;
  gap: 0.5rem;
  margin-bottom: 0.75rem;
}

.mp-join-row input[type="text"] {
  flex: 1 1 auto;
  margin-bottom: 0;
}

.mp-join-row button {
  flex: 0 0 auto;
}

/* ---- Setting hints ------------------------------------------------------
   Hover on pointer devices, tap-to-toggle on touch (the JS sets
   aria-expanded, which drives the same visible state as :hover). */
.mp-hint {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.15rem;
  height: 1.15rem;
  min-height: 0;
  padding: 0;
  margin-left: 0.35rem;
  border-radius: 50%;
  border: 1px solid var(--border-soft);
  background: var(--bg-inset);
  color: var(--ink-muted);
  font-size: 0.7rem;
  font-weight: 700;
  line-height: 1;
  cursor: help;
}

.mp-hint-text {
  position: absolute;
  bottom: calc(100% + 0.4rem);
  left: 50%;
  transform: translateX(-50%);
  z-index: 5;
  width: max-content;
  max-width: 15rem;
  padding: 0.5rem 0.65rem;
  border-radius: var(--radius-md);
  border: 1px solid var(--border-soft);
  background: var(--input-bg);
  box-shadow: var(--shadow-window-soft);
  color: var(--ink);
  font-size: 0.75rem;
  font-weight: 400;
  line-height: 1.45;
  text-align: left;
  white-space: normal;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.12s ease;
}

.mp-hint:hover .mp-hint-text,
.mp-hint:focus-visible .mp-hint-text,
.mp-hint[aria-expanded="true"] .mp-hint-text {
  opacity: 1;
  visibility: visible;
}

/* Near the card's right edge a centred tooltip would overflow; this flips it
   to hang from the right instead. */
.mp-hint[data-align="end"] .mp-hint-text {
  left: auto;
  right: 0;
  transform: none;
}

/* On a phone the card is barely wider than the tooltip, so centring on the
   hint pushes it off the left edge. Hang it from the hint's left edge
   instead (measured: every hint then lands inside a 375px viewport), and
   keep the right-aligned ones right-aligned. */
@media (max-width: 40rem) {
  .mp-hint-text {
    left: 0;
    right: auto;
    transform: none;
    max-width: min(15rem, 70vw);
  }
  .mp-hint[data-align="end"] .mp-hint-text {
    left: auto;
    right: 0;
  }
}

.mp-turn {
  text-align: center;
  padding: 0.5rem;
  border-radius: var(--radius-md);
  border: 2px solid transparent;
  /* Steal-pulse colour follows the team that's on the buzzer. */
  --mp-pulse: var(--gold-soft);
}
.mp-turn[data-team="1"] { border-color: var(--team-red); color: var(--team-red); --mp-pulse: var(--bad-soft); }
.mp-turn[data-team="2"] { border-color: var(--team-blue); color: var(--team-blue); --mp-pulse: var(--accent-blue-soft); }
.mp-turn[data-steal="1"] { animation: mp-steal-pulse 1s ease-in-out infinite; }

.mp-reveal { text-align: center; }
.mp-reveal-cover { width: 160px; max-width: 60%; border-radius: var(--radius-md); }
.mp-reveal-title { font-family: var(--font-display); margin: 0.5rem 0 0; }
.mp-reveal-artist { color: var(--ink-muted); margin: 0; }

.mp-settings-locked { opacity: 0.55; }
.mp-settings-note { font-size: 0.8rem; color: var(--ink-muted); }

/* The coloured frame is the one with spread — a 0-spread coloured shadow and a
   transparent 0.5rem shadow are both invisible, which is what this used to be. */
@keyframes mp-steal-pulse {
  0%, 100% { box-shadow: 0 0 0 0 transparent; }
  50%      { box-shadow: 0 0 0 0.5rem var(--mp-pulse); }
}

@keyframes mp-pop {
  0%   { transform: scale(1); }
  40%  { transform: scale(1.18); }
  100% { transform: scale(1); }
}
.mp-pop { animation: mp-pop 0.28s ease-out; }

/* ---- Setup / settings forms -------------------------------------------
   Scoped to .mp-setup so the site's bare <select>/<input type=number>
   elements elsewhere are left alone. Labels are block rows with a stacked
   caption, and every control clears a 2.75rem tap target. */
.mp-setup {
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
  margin-top: 1rem;
}

.mp-setup label {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  font-size: 0.8rem;
  color: var(--ink-muted);
}

/* Caption + its hint button share a line above the control. */
.mp-setup-caption {
  display: inline-flex;
  align-items: center;
  flex-wrap: wrap;
}

/* Checkbox rows read the other way round: control first, caption beside it. */
.mp-setup label.mp-setup-check {
  flex-direction: row;
  align-items: center;
  gap: 0.6rem;
  min-height: 2.75rem;
  font-size: 0.9rem;
  color: var(--ink);
}

.mp-setup select,
.mp-setup input[type="number"] {
  width: 100%;
  min-height: var(--control-h);
  box-sizing: border-box;
  padding: 0.6rem 0.75rem;
  border-radius: var(--radius-md);
  border: 1px solid var(--border-soft);
  background: var(--input-bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 1rem;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.mp-setup select:focus-visible,
.mp-setup input[type="number"]:focus-visible,
.mp-setup input[type="checkbox"]:focus-visible {
  outline: none;
  border-color: var(--accent-blue);
  box-shadow: 0 0 0 2px var(--accent-blue-soft);
}

.mp-setup select:disabled,
.mp-setup input:disabled {
  cursor: not-allowed;
}

.mp-setup input[type="checkbox"] {
  flex: 0 0 auto;
  width: 1.3rem;
  height: 1.3rem;
  accent-color: var(--accent-blue);
  border-radius: var(--radius-md);
}

.mp-setup > button {
  width: 100%;
  margin-top: 0.25rem;
}

/* ---- Settings modal ---------------------------------------------------- */

.mp-settings-card {
  max-width: 26rem;
  max-height: 85vh;
  overflow-y: auto;
}

.mp-settings-card h2 {
  margin: 0 0 0.35rem;
  font-size: 1.15rem;
}

.mp-settings-group {
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-md);
  background: var(--bg-inset);
  padding: 0.75rem 0.8rem;
  margin-top: 0.9rem;
}

.mp-settings-group .eyebrow { margin: 0; }
.mp-settings-group .mp-setup { margin-top: 0.6rem; }

.mp-settings-actions {
  margin-top: 1rem;
}
.mp-settings-actions .btn-primary { width: 100%; }

/* ---- Room header / rejoin ---------------------------------------------- */

.mp-room-actions {
  display: flex;
  gap: 0.5rem;
  justify-content: center;
  flex-wrap: wrap;
}
.mp-room-actions button { min-height: 2.75rem; }

.mp-rejoin {
  border: 1px solid var(--gold);
  background: var(--gold-soft);
  border-radius: var(--radius-md);
  padding: 0.85rem;
  margin-bottom: 1rem;
  text-align: center;
}
.mp-rejoin p { margin: 0 0 0.6rem; color: var(--ink); font-size: 0.9rem; }
.mp-rejoin .mp-rejoin-buttons { display: flex; gap: 0.5rem; justify-content: center; flex-wrap: wrap; }
.mp-rejoin button { min-height: 2.75rem; }

/* ---- Scoreboard -------------------------------------------------------- */

.mp-scoreboard { margin-block: 1.25rem; }

.mp-scoreboard-title {
  text-align: center;
  font-family: var(--font-display);
  font-size: 1rem;
  margin: 0 0 0.75rem;
  color: var(--ink);
}

.mp-standings {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}

.mp-standing {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.4rem 0.6rem;
  border-radius: var(--radius-md);
  border: 1px solid var(--border-soft);
  background: var(--bg-inset);
}
.mp-standing[data-rank="1"] {
  border-color: var(--gold);
  background: var(--gold-soft);
}

.mp-rank {
  flex: 0 0 1.5rem;
  font-family: var(--font-mono);
  color: var(--ink-muted);
}
.mp-standing[data-rank="1"] .mp-rank { color: var(--gold); }

.mp-standing .mp-player { flex: 1 1 auto; min-width: 0; padding: 0; }

/* Red-vs-Blue proportional bar for teams mode. */
.mp-team-bar {
  display: flex;
  height: 1.75rem;
  border-radius: var(--radius-pill);
  overflow: hidden;
  border: 1px solid var(--border);
  background: var(--bg-inset);
}

.mp-team-bar-seg {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  color: var(--input-bg);
  overflow: hidden;
  white-space: nowrap;
  transition: width 0.4s ease;
}
.mp-team-bar-seg[data-team="1"] { background: var(--team-red); }
.mp-team-bar-seg[data-team="2"] { background: var(--team-blue); }

.mp-team-bar-labels {
  display: flex;
  justify-content: space-between;
  font-size: 0.8rem;
  margin-top: 0.35rem;
}

.mp-winner {
  text-align: center;
  font-family: var(--font-display);
  font-size: 1.2rem;
  color: var(--gold);
  margin: 0 0 0.75rem;
}

.mp-waiting {
  text-align: center;
  color: var(--ink-muted);
  font-size: 0.9rem;
  margin-top: 0.85rem;
}

@media (prefers-reduced-motion: reduce) {
  .mp-turn[data-steal="1"],
  .mp-pop { animation: none; }
  .mp-team-bar-seg { transition: none; }
}
