/* player.css — phone controller. Mobile-first, thumb-reachable. */
:root {
  --bg: #10061f; --card: #241246; --ink: #f5f0ff; --muted: #b9a8e0;
  --accent: #ff5ea8; --accent2: #6de3ff; --radius: 16px;
}

/* Pixel avatar sprites. Sized 1em so an <img> drops into whatever slot used to
   hold an emoji glyph (the container's font-size decides the size), and never
   blurs when scaled. */
img.av { width: 1em; height: 1em; image-rendering: pixelated; display: inline-block; vertical-align: middle; }

/* CRITICAL: class rules like .screen{display:flex} override the HTML `hidden`
   attribute (the UA rule [hidden]{display:none} loses on specificity), which
   silently renders every "hidden" screen. This must stay. */
[hidden] { display: none !important; }

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html, body { margin: 0; min-height: 100%; }
/* Rounded, friendly letterforms with ZERO network cost. `ui-rounded` resolves
   to SF Pro Rounded on iOS/macOS — which is where most party guests will see
   this — and every other platform falls through to its own friendly face.
   Deliberately not a web font: an external font would need CSP changes and
   would risk a flash of unstyled text on a phone at a party. */
body {
  font-family: ui-rounded, "SF Pro Rounded", "Hiragino Maru Gothic ProN",
    "Varela Round", "Segoe UI Variable Display", system-ui, -apple-system,
    "Segoe UI", Roboto, sans-serif;
  color: var(--ink); background: radial-gradient(120% 90% at 50% 0%, #1c0b38, var(--bg));
  min-height: 100dvh;
}
.phone { max-width: 480px; margin: 0 auto; padding: 22px 18px 40px; }
.screen { display: flex; flex-direction: column; gap: 18px; }
/* --- Wordmark ------------------------------------------------------------
   Rounded, heavy and warm so it reads as a toy rather than a utility. */
.logo {
  font-weight: 900; font-size: 32px; letter-spacing: -.02em; line-height: 1.05;
  text-align: center; margin: 12px 0 8px;
  background: linear-gradient(100deg, var(--accent) 10%, #ffb347 45%, var(--accent2) 90%);
  -webkit-background-clip: text; background-clip: text; color: transparent;
  filter: drop-shadow(0 3px 14px #ff5ea855);
}
.logo-hero { font-size: 46px; margin-top: 26px; }

/* Couch wordmark (landing hero): the letters sit on two caramel couches at
   varied heights, like people of different sizes sitting together. */
.logo-couch { display: block; max-width: 460px; margin: 22px auto 6px; }
.logo-couch svg { width: 100%; height: auto; display: block;
  filter: drop-shadow(0 8px 26px #ff5ea83a); }

.tagline {
  text-align: center; margin: 2px 0 0;
  font-size: 17px; font-weight: 700; color: var(--muted);
  letter-spacing: .01em;
}


.field { display: flex; flex-direction: column; gap: 8px; font-weight: 600; color: var(--muted); }
.field > span { font-size: 14px; }
input { font: inherit; font-size: 18px; padding: 14px 16px; border-radius: var(--radius);
  border: 2px solid #ffffff22; background: #0004; color: var(--ink); width: 100%; }
input:focus { outline: none; border-color: var(--accent); }
.code-input { text-transform: uppercase; letter-spacing: .35em; font-weight: 800; text-align: center; font-size: 26px; }
.avatar-grid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 8px; }
.avatar-opt { aspect-ratio: 1; font-size: 26px; background: #0004; border: 2px solid transparent;
  border-radius: 12px; cursor: pointer; display: flex; align-items: center; justify-content: center; }
.avatar-opt.sel { border-color: var(--accent); background: #ff5ea822; transform: scale(1.05); }
.btn { font: inherit; font-weight: 800; border: none; border-radius: 999px; padding: 16px;
  font-size: 18px; cursor: pointer; width: 100%; }
.btn.primary { background: linear-gradient(90deg, var(--accent), var(--accent2)); color: #16002a; }
.btn.primary:disabled { filter: grayscale(.7) brightness(.7); }
.btn.ghost { background: transparent; color: var(--ink); border: 2px solid var(--muted); }
.error { color: #ff9a9a; font-weight: 600; margin: 0; }
.muted { color: var(--muted); text-align: center; }
.you { display: flex; flex-direction: column; align-items: center; gap: 8px; margin-top: 24px; }
.you-avatar { font-size: 72px; }
.you-name { font-size: 26px; font-weight: 800; }

/* --- In-game (Trivia Rush) phone controller ------------------------- */
.game-player { display: flex; flex-direction: column; gap: 14px; }
.pg-round { text-align: center; color: var(--muted); font-weight: 700; }
.pg-answers { display: grid; gap: 12px; }
.pg-answer { display: flex; align-items: center; gap: 14px; padding: 18px 16px; border: none; border-radius: 16px; font: inherit; font-weight: 700; font-size: 18px; color: #16002a; cursor: pointer; text-align: left; }
.pg-answer.c0 { background: #ff5ea8; } .pg-answer.c1 { background: #6de3ff; }
.pg-answer.c2 { background: #57e08a; } .pg-answer.c3 { background: #ffd16e; }
/* Neutral answer button — used when the answers are colour words, so the
   button colour can't contradict the label (e.g. a green button saying
   "Brown"). The A/B/C/D letters keep the options distinct. */
.pg-answer.neutral { background: #cfc6e6; }
.pg-answer.neutral .pg-letter { background: #ffffffcc; }
.pg-answer:disabled { opacity: .45; } .pg-answer.chosen { outline: 4px solid #fff; opacity: 1; }
.pg-letter { width: 1.8em; height: 1.8em; flex: none; display: flex; align-items: center; justify-content: center; background: #ffffff55; border-radius: 10px; font-weight: 800; }
.pg-locked { text-align: center; font-size: 24px; font-weight: 800; color: var(--accent2); margin-top: 20px; }
.pg-msg { text-align: center; color: var(--muted); }
.pg-result { border-radius: 20px; padding: 30px 20px; text-align: center; margin-top: 20px; }
.pg-result.good { background: #57e08a26; } .pg-result.bad { background: #ff5c5c26; }
.pg-verdict { font-size: 30px; font-weight: 800; }
.pg-gain { font-size: 40px; font-weight: 800; color: var(--good); margin: 6px 0; }
.pg-standing { color: var(--muted); font-weight: 600; margin-top: 8px; }

/* --- Open-ended phone controls -------------------------------------- */
.pg-question { font-size: 20px; font-weight: 700; text-align: center; margin: 6px 0 4px; }
.pg-openform { display: flex; flex-direction: column; gap: 12px; }
.pg-input { font: inherit; font-size: 20px; padding: 16px; border-radius: 16px; border: 2px solid #ffffff22; background: #0004; color: var(--ink); text-align: center; }
.pg-input:focus { outline: none; border-color: var(--accent); }
.pg-submit { justify-content: center; }
.pg-answerhint { margin-top: 10px; font-weight: 700; color: var(--ink); }

/* open/round sub-header on phone */
.pg-subround { text-align: center; color: var(--muted); font-size: 13px; margin-top: -6px; }

/* --- Landing divider --- */
.divider { display: flex; align-items: center; gap: 12px; color: var(--muted); font-size: 13px; text-transform: uppercase; letter-spacing: .15em; margin: 6px 0; }
.divider::before, .divider::after { content: ''; flex: 1; height: 1px; background: #ffffff22; }

/* --- Lobby --- */
.lobby-top { display: flex; flex-direction: column; align-items: center; gap: 8px; margin-bottom: 6px; }
.code-block { display: flex; flex-direction: column; align-items: center; }
.code-cap { color: var(--muted); font-size: 12px; letter-spacing: .3em; }
.big-code { font-size: 46px; font-weight: 800; letter-spacing: .14em; line-height: 1; }
.qr-box-sm { background: #fff; border-radius: 12px; padding: 10px; width: 160px; height: 160px; margin: 0 auto; display: flex; align-items: center; justify-content: center; }
.qr-box-sm svg { width: 100%; height: 100%; display: block; }
.join-hint { color: var(--muted); font-size: 13px; }
.roster-head { display: flex; justify-content: space-between; align-items: baseline; font-weight: 800; margin: 10px 2px 8px; }
.roster-head .count { color: var(--muted); font-size: .8em; font-weight: 600; }
.roster-list-p { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.rp-item { display: flex; align-items: center; gap: 12px; background: #0004; border-radius: 12px; padding: 10px 14px; }
.rp-item.offline { opacity: .45; }
.rp-av { font-size: 26px; }
.rp-name { flex: 1; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rp-crown { font-size: 18px; }
.rp-you { font-size: 11px; text-transform: uppercase; letter-spacing: .1em; color: #16002a; background: var(--accent2); border-radius: 999px; padding: 2px 8px; font-weight: 800; }

/* --- Admin panel --- */
.admin-panel { display: flex; flex-direction: column; gap: 12px; margin-top: 16px; background: #ffffff0a; border: 1px solid #ffffff1a; border-radius: 16px; padding: 16px; }
.admin-cap { font-weight: 800; color: var(--accent2); }
.wait-panel { margin-top: 20px; }
.setup-game { font-weight: 800; font-size: 18px; }
.setup-row-p { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.setup-label { color: var(--muted); font-weight: 700; text-transform: uppercase; letter-spacing: .1em; font-size: 12px; min-width: 64px; }
.seg { display: inline-flex; background: #0005; border-radius: 999px; padding: 4px; gap: 4px; }
.seg-btn { border: none; background: transparent; color: var(--ink); font: inherit; font-weight: 700; padding: 8px 14px; border-radius: 999px; cursor: pointer; font-size: 14px; }
.seg-btn.on { background: linear-gradient(90deg, var(--accent), var(--accent2)); color: #16002a; }
.setup-select { font: inherit; font-weight: 700; padding: 10px 12px; border-radius: 12px; border: 2px solid #ffffff22; background: var(--card); color: var(--ink); flex: 1; }
.setup-num { font: inherit; font-weight: 700; padding: 10px 12px; border-radius: 12px; border: 2px solid #ffffff22; background: var(--card); color: var(--ink); flex: 1; width: 100%; }
.lobby-status { color: var(--muted); font-weight: 600; font-size: 14px; margin: 2px; min-height: 1.3em; }
.lobby-status.err { color: #ff9a9a; }

/* --- In-game standings board --- */
.pg-board { display: flex; flex-direction: column; gap: 6px; margin-top: 14px; }
.pg-brow { display: flex; align-items: center; gap: 10px; background: #0004; border-radius: 10px; padding: 8px 12px; }
.pg-brank { font-weight: 800; color: var(--muted); min-width: 2em; }
.pg-bav { font-size: 22px; } .pg-bname { flex: 1; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pg-bscore { font-weight: 800; }
.pg-timer { font-weight: 800; color: var(--accent2); }
.pg-final-title { text-align: center; font-weight: 800; margin-top: 14px; color: var(--muted); }

.landing-cap { text-align: center; color: var(--muted); font-weight: 700; margin: -6px 0 6px; letter-spacing: .05em; }

/* ============================================================
   MOTION & HIERARCHY PASS (game-ui-motion-designer)
   Principles applied:
   - Motion is pacing, not decoration. Routine transitions 150-400ms
     ease-out; anticipation/celebration beats get 500ms+.
   - The question is the dominant element; the timer must be glanceable.
   - Waiting states must read "alive", never blank.
   ============================================================ */

/* Routine entrances: fast start, slow finish (ease-out reads natural). */
@keyframes riseIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
@keyframes popIn  { 0% { opacity:0; transform: scale(.86);} 60% { transform: scale(1.04);} 100% { opacity:1; transform: scale(1);} }
@keyframes pulseSoft { 0%,100% { opacity:.55; } 50% { opacity:1; } }
@keyframes urgentPulse { 0%,100% { transform: scale(1); } 50% { transform: scale(1.14); } }
@keyframes shimmer { 0% { background-position: -200% 0; } 100% { background-position: 200% 0; } }

.screen:not([hidden]) { animation: riseIn 240ms cubic-bezier(.2,.8,.2,1) both; }
.pg-answers .pg-answer { animation: riseIn 260ms cubic-bezier(.2,.8,.2,1) both; }
.pg-answers .pg-answer:nth-child(1){animation-delay:30ms}
.pg-answers .pg-answer:nth-child(2){animation-delay:70ms}
.pg-answers .pg-answer:nth-child(3){animation-delay:110ms}
.pg-answers .pg-answer:nth-child(4){animation-delay:150ms}
.pg-answer { transition: transform 120ms ease-out, opacity 150ms ease-out; }
.pg-answer:active { transform: scale(.97); }          /* instant tap feedback */
.pg-answer.chosen { animation: popIn 220ms cubic-bezier(.2,.8,.2,1) both; }

/* --- Question: the dominant element on the screen --- */
.pg-question { font-size: 25px; line-height: 1.25; font-weight: 800; margin: 10px 0 16px; }

/* --- Countdown: glanceable, with urgency escalation --- */
.pg-timerwrap { display: flex; justify-content: center; margin: 2px 0 6px; }
.pg-timer-big { font-size: 40px; font-weight: 800; line-height: 1; color: var(--accent2);
  font-variant-numeric: tabular-nums; transition: color 200ms ease-out; }
.pg-timer-big.warn { color: #ffd16e; }
.pg-timer-big.urgent { color: #ff6b6b; animation: urgentPulse 700ms ease-in-out infinite; }

/* --- Waiting states: alive, with real progress --- */
.pg-waiting { display: flex; flex-direction: column; align-items: center; gap: 10px; margin-top: 26px; }
.pg-waitdots { display: flex; gap: 6px; }
.pg-waitdots i { width: 8px; height: 8px; border-radius: 50%; background: var(--accent2);
  animation: pulseSoft 1.1s ease-in-out infinite; }
.pg-waitdots i:nth-child(2){animation-delay:.18s} .pg-waitdots i:nth-child(3){animation-delay:.36s}
.pg-progress { font-weight: 800; color: var(--ink); }
.pg-progbar { width: 100%; max-width: 260px; height: 8px; border-radius: 999px; background: #ffffff1a; overflow: hidden; }
.pg-progbar > i { display: block; height: 100%; border-radius: 999px;
  background: linear-gradient(90deg, var(--accent), var(--accent2)); transition: width 300ms cubic-bezier(.2,.8,.2,1); }

/* --- Reveal: anticipation beat, then payoff --- */
.pg-anticipate { text-align: center; padding: 40px 0; }
.pg-anticipate .pg-dots { font-size: 40px; letter-spacing: .2em; color: var(--muted);
  background: linear-gradient(90deg, var(--muted) 25%, #fff 50%, var(--muted) 75%);
  background-size: 200% 100%; -webkit-background-clip: text; background-clip: text; color: transparent;
  animation: shimmer 900ms linear infinite; }
.pg-result { animation: popIn 320ms cubic-bezier(.2,.8,.2,1) both; }
.pg-result.good { box-shadow: 0 0 0 2px #57e08a55, 0 12px 40px #57e08a22; }
.pg-gain { animation: popIn 380ms cubic-bezier(.2,.8,.2,1) both; animation-delay: 120ms; }
.pg-brow { animation: riseIn 240ms ease-out both; }
.pg-brow.me { outline: 2px solid var(--accent2); }

/* --- Final: the biggest beat of the session earns more --- */
.pg-final-hero { text-align: center; padding: 26px 16px; border-radius: 20px;
  background: linear-gradient(135deg, #ff5ea833, #6de3ff33); animation: popIn 520ms cubic-bezier(.2,.8,.2,1) both; }
.pg-final-hero .pg-trophy { font-size: 64px; display: block; animation: popIn 640ms cubic-bezier(.2,.8,.2,1) both; }

/* --- Connection state --- */
.pg-reconnect { position: fixed; left: 0; right: 0; top: 0; z-index: 50; text-align: center;
  background: #ffd16e; color: #16002a; font-weight: 800; padding: 10px; animation: riseIn 200ms ease-out both; }

/* --- Roster joins should be noticeable (a live social moment) --- */
.rp-item { animation: riseIn 260ms cubic-bezier(.2,.8,.2,1) both; }

/* Respect users who ask for less motion. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important;
    transition-duration: .001ms !important; }
}

/* ============================================================
   THUMB-REACH LAYOUT (phones) + SOUND TOGGLE
   "Design for one-handed use — controls clustered toward the lower
   half of the screen work better than a layout requiring the far top
   corner." Desktop/tablet layout is intentionally left unchanged.
   ============================================================ */

/* Sound toggle: small, out of the way, always reachable. */
.sound-toggle { position: fixed; top: 10px; right: 10px; z-index: 40;
  width: 40px; height: 40px; border-radius: 50%; border: 1px solid #ffffff22;
  background: #0006; color: var(--ink); font-size: 18px; cursor: pointer;
  display: flex; align-items: center; justify-content: center; backdrop-filter: blur(4px); }
.sound-toggle.off { opacity: .55; }

@media (max-width: 640px) {
  /* Fill the visual viewport (dvh accounts for mobile browser chrome). */
  .phone { min-height: 100dvh; padding-bottom: calc(18px + env(safe-area-inset-bottom, 0px)); }
  .screen { min-height: calc(100dvh - 62px); }

  /* In-game: question reads at the top, controls sit in the thumb zone. */
  .game-player { min-height: calc(100dvh - 62px); display: flex; flex-direction: column; }
  .game-player .pg-answers,
  .game-player .pg-openform { margin-top: auto; }          /* push to the bottom */
  .game-player .pg-result,
  .game-player .pg-final-hero { margin-top: auto; }
  .game-player .pg-board { margin-bottom: auto; }

  /* Bigger tap targets on the thumb-zone controls. */
  .pg-answer { padding: 20px 16px; font-size: 19px; min-height: 60px; }
  .pg-input { font-size: 19px; padding: 18px; }

  #landing .avatar-grid { grid-template-columns: repeat(6, 1fr); }

  /* The host panel used to be `position: sticky; bottom: 0`, meant to keep
     Start within thumb reach. Because the panel has its own background, the
     room code, QR and player list scrolled UNDERNEATH it and disappeared —
     which read as the page having two competing scroll areas. Thumb reach is
     not worth hiding the room code, so the lobby is now one plain scroll with
     nothing pinned over anything else. */
  .admin-panel { position: static; }
  #adminRoomCtl { position: static; }

  /* Keep the focused text input visible above the on-screen keyboard. */
  .pg-openform { scroll-margin-bottom: 220px; }
}

/* Very short viewports (landscape phones): reclaim vertical space. */
@media (max-height: 520px) {
  .pg-question { font-size: 20px; margin: 6px 0 10px; }
  .pg-timer-big { font-size: 30px; }
  .avatar-grid { grid-template-columns: repeat(10, 1fr); }
}

/* --- Host moderation + in-game admin controls --- */
.rp-kick { width: 30px; height: 30px; flex: none; border: none; border-radius: 50%;
  background: #ff5c5c33; color: #ff8f8f; font-weight: 800; cursor: pointer; }
.rp-kick:active { transform: scale(.92); }
.game-admin { display: flex; flex-direction: column; gap: 10px; margin-top: 18px; }
@media (max-width: 640px) { .game-admin { margin-top: auto; padding-bottom: env(safe-area-inset-bottom, 0px); } }

/* --- Round-change beat: the difficulty jump should register --- */
.pg-roundbanner { text-align: center; padding: 26px 16px; border-radius: 18px; margin: 8px 0 4px;
  background: linear-gradient(135deg, #ff5ea833, #6de3ff33); animation: popIn 420ms cubic-bezier(.2,.8,.2,1) both; }
.pg-roundbanner .rb-name { font-size: 30px; font-weight: 800; }
.pg-roundbanner .rb-sub { color: var(--muted); font-weight: 700; margin-top: 4px; }

/* --- Feedback pulse: stands in for haptics where vibrate is unavailable
       (all iOS browsers). Brief, edge-lit, never blocks interaction. --- */
.fb-pulse { position: fixed; inset: 0; pointer-events: none; z-index: 60; opacity: 0;
  transition: opacity 120ms ease-out; }
.fb-pulse.on { opacity: 1; animation: fbFade 260ms ease-out both; }
.fb-pulse.fb-good { box-shadow: inset 0 0 0 4px #57e08a, inset 0 0 60px #57e08a55; }
.fb-pulse.fb-bad  { box-shadow: inset 0 0 0 4px #ff6b6b, inset 0 0 60px #ff6b6b55; }
@keyframes fbFade { from { opacity: .95; } to { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .fb-pulse { display: none; } }

/* --- Paused state -------------------------------------------------------
   Shown on EVERY device, not just the admin's. A phone that simply freezes
   reads as a broken app; an explicit paused state reads as a deliberate
   moment. Fades in fast (200ms) so it feels like a switch, not a stall. --- */
.paused-overlay { position: fixed; inset: 0; z-index: 70; display: flex;
  align-items: center; justify-content: center; padding: 24px;
  background: rgba(16, 6, 31, .82); backdrop-filter: blur(6px);
  animation: pausedIn 200ms cubic-bezier(.2,.8,.2,1) both; }
@keyframes pausedIn { from { opacity: 0; } to { opacity: 1; } }
.paused-card { text-align: center; display: flex; flex-direction: column; align-items: center;
  gap: 10px; max-width: 340px; width: 100%; }
.paused-icon { font-size: 56px; line-height: 1; animation: pausedPulse 2.4s ease-in-out infinite; }
@keyframes pausedPulse { 0%,100% { opacity: .85; transform: scale(1); } 50% { opacity: 1; transform: scale(1.06); } }
.paused-title { font-size: 34px; font-weight: 800; letter-spacing: .02em; }
.paused-sub { color: var(--muted); font-weight: 600; }
.paused-time { color: var(--accent2); font-weight: 800; font-variant-numeric: tabular-nums; }
.paused-card .btn { margin-top: 10px; }
@media (prefers-reduced-motion: reduce) { .paused-icon { animation: none; } }

.cast-hint { color: var(--muted); font-size: 13px; margin: -4px 0 2px; line-height: 1.4; }
.cast-hint strong { color: var(--accent2); }

/* --- Accessibility ------------------------------------------------------
   Visible keyboard focus (there was none) and a screen-reader-only channel
   for announcing phase changes. --- */
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

:focus-visible { outline: 3px solid var(--accent2); outline-offset: 3px; border-radius: 8px; }
.btn:focus-visible, .pg-answer:focus-visible, .avatar-opt:focus-visible,
.seg-btn:focus-visible, .setup-select:focus-visible, .rp-kick:focus-visible,
.sound-toggle:focus-visible { outline: 3px solid #fff; outline-offset: 3px; }
input:focus-visible { outline: 3px solid var(--accent2); outline-offset: 2px; }

/* The countdown updates every 200ms — never expose that to assistive tech. */
.pg-timer-big, .pg-timer { speak: none; }

/* --- Post-game suggestions ---------------------------------------------
   Shown to every player on the final screen. Collapsed by default so it
   never competes with the winner moment. --- */
.feedback-box { margin-top: 16px; display: flex; flex-direction: column; gap: 10px; }
.feedback-form { display: flex; flex-direction: column; gap: 10px;
  background: #ffffff0a; border: 1px solid #ffffff1a; border-radius: 16px; padding: 14px;
  animation: riseIn 240ms cubic-bezier(.2,.8,.2,1) both; }
.fb-title { font-weight: 800; }
.fb-stars { display: flex; gap: 6px; }
.fb-star { font-size: 26px; background: none; border: none; cursor: pointer; padding: 2px 4px;
  filter: grayscale(1) opacity(.45); transition: filter 120ms ease-out, transform 120ms ease-out; }
.fb-star.on { filter: none; transform: scale(1.1); }
.fb-text { font: inherit; font-size: 16px; padding: 12px; border-radius: 12px;
  border: 2px solid #ffffff22; background: #0004; color: var(--ink); resize: vertical; }
.fb-text:focus { outline: none; border-color: var(--accent); }
.fb-thanks { color: var(--good); font-weight: 700; text-align: center; margin: 0; }

/* ===================================================================== *
 * Crowd Control — phone controller
 * The NUMBER is the content; the track is the instrument. Nudges exist
 * because ~3.5px per percentage point is not a thumb-sized target and the
 * scoring bands are tight. Dragging never submits.
 * ===================================================================== */
.cg-youare { text-align: center; font-weight: 700; color: var(--muted); font-size: 15px; }

.cg-dial { display: flex; flex-direction: column; gap: 14px; }
.cg-readout { display: flex; align-items: baseline; justify-content: center; gap: 2px; }
.cg-num { font-size: 68px; font-weight: 900; line-height: 1;
  font-variant-numeric: tabular-nums;
  background: linear-gradient(90deg, var(--accent2), var(--accent));
  -webkit-background-clip: text; background-clip: text; color: transparent; }
.cg-pct { font-size: 28px; font-weight: 800; color: var(--muted); }

.cg-track { position: relative; height: 14px; border-radius: 999px;
  background: #ffffff1a; border: 1px solid #ffffff22; }
.cg-fill { position: absolute; inset: 0 auto 0 0; border-radius: 999px;
  background: linear-gradient(90deg, var(--accent2), var(--accent));
  transition: width .12s ease-out; }
.cg-knob { position: absolute; top: 50%; width: 26px; height: 26px; border-radius: 50%;
  transform: translate(-50%, -50%); background: #fff; box-shadow: 0 2px 10px #0008;
  transition: left .12s ease-out; }

/* The real <input type=range> sits on top, invisible but fully interactive —
   so we get native drag + keyboard + screen-reader behaviour for free. */
/* --- Circular rotary dial ----------------------------------------------
   0% at 12 o'clock, sweeping counter-clockwise to 100%. The centred number is
   the source of truth; the neon fill arc (empty ring = 0, full = 100) removes
   the ambiguity of the lever resting at the top for both 0 and 100. */
/* CRITICAL: the ring MUST have an absolute width AND height. The phone shell is
   shrink-to-fit (a centred flex column), so it has no definite width to resolve
   a relative size against — `aspect-ratio`, `%`, or `vw` widths create a
   circular dependency and collapse the whole dial to 0x0 (it was invisible).
   Fixed px both dimensions breaks the cycle. A media query (viewport-based, not
   parent-based) handles the smallest phones without reintroducing the cycle. */
/* The WRAPPER is the interactive surface: a plain div hit-tests its whole box on
   every browser, unlike an <svg> whose fill:none interior does not. All children
   (svg, readout, range) are pointer-events:none so every pointer lands here. */
.cg-ringwrap { position: relative; width: 230px; height: 230px; margin: 2px auto;
  cursor: grab; touch-action: none; -webkit-user-select: none; user-select: none; }
@media (max-width: 360px) { .cg-ringwrap { width: 190px; height: 190px; } }
.cg-ringwrap.grabbing { cursor: grabbing; }
.cg-ring { width: 100%; height: 100%; display: block; overflow: visible; pointer-events: none; }
.cg-ring-bg { fill: none; stroke: #ffffff1a; stroke-width: 11; }
.cg-ring-fill { fill: none; stroke: url(#cgGrad); stroke-width: 11; stroke-linecap: round; }
.cg-lever { transition: transform .1s ease-out; }
.cg-ringwrap.grabbing .cg-lever { transition: none; }        /* track the finger 1:1 while dragging */
.cg-lever-arm { stroke: #fff; stroke-width: 5; stroke-linecap: round; }
.cg-lever-knob { fill: #fff; stroke: #180a2e; stroke-width: 2; }
.cg-hub { fill: var(--card); stroke: #ffffff33; stroke-width: 2; }
.cg-ringwrap .cg-readout { position: absolute; inset: 0; margin: 0; align-items: center; pointer-events: none; }
.cg-ringwrap .cg-num { font-size: 54px; }

/* Native slider is kept purely as the keyboard / screen-reader control:
   invisible, and pointer-events:none so it never steals the ring's drags. */
.cg-range { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0;
  pointer-events: none; -webkit-appearance: none; appearance: none; background: transparent; }
.cg-range:focus-visible { opacity: .001; outline: 3px solid var(--accent2); outline-offset: 6px; border-radius: 50%; }

@keyframes cgLockPulse { 0% { transform: scale(1); } 40% { transform: scale(1.05); } 100% { transform: scale(1); } }
.cg-ringwrap.cg-lockpulse { animation: cgLockPulse .3s ease-out; }
@media (prefers-reduced-motion: reduce) {
  .cg-lever { transition: none; }
  .cg-ringwrap.cg-lockpulse { animation: none; }
}

.cg-nudges { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
.cg-nudge { font: inherit; font-size: 18px; font-weight: 800; min-height: 52px;
  border-radius: 14px; border: 2px solid #ffffff22; background: #ffffff12; color: var(--ink); }
.cg-nudge:active { background: #ffffff26; transform: scale(.96); }

.cg-lock { font: inherit; font-size: 20px; font-weight: 900; letter-spacing: .04em;
  min-height: 62px; border-radius: var(--radius); border: 0; color: #1a0330;
  background: linear-gradient(90deg, var(--accent2), var(--accent)); }
.cg-lock:disabled { background: #ffffff1a; color: var(--muted); }

/* Watching someone else guess — dead time turned into spectacle. */
.cg-watch { text-align: center; padding: 18px 0; }
.cg-watchnum { font-size: 56px; font-weight: 900; font-variant-numeric: tabular-nums;
  color: var(--accent2); transition: color .2s; }

/* Higher / lower — two targets, nothing else on screen. */
.cg-anchor { display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: 12px; border-radius: var(--radius); background: #ffffff10; }
.cg-anchor-name { font-size: 14px; color: var(--muted); font-weight: 600; }
.cg-anchor-val { font-size: 44px; font-weight: 900; font-variant-numeric: tabular-nums; }

.cg-calls { display: flex; flex-direction: column; gap: 12px; }
.cg-call { font: inherit; display: flex; align-items: center; justify-content: center; gap: 12px;
  min-height: 96px; border-radius: var(--radius); border: 2px solid #ffffff22;
  color: var(--ink); font-weight: 900; font-size: 26px; letter-spacing: .04em;
  transition: transform .12s ease-out, opacity .2s; }
.cg-higher { background: linear-gradient(180deg, #1d7a4a, #12603a); }
.cg-lower { background: linear-gradient(180deg, #8a2f5d, #6b2049); }
.cg-call:active { transform: scale(.97); }
.cg-call.chosen { outline: 3px solid var(--accent2); outline-offset: 2px; }
.cg-arrow { font-size: 30px; }

/* Reveal: the guess is the anchor, the truth travels to meet it. */
.cg-reveal { display: flex; flex-direction: column; gap: 12px; padding: 8px 0; }
.cg-track-reveal { height: 18px; margin: 26px 0 8px; }
.cg-gap { position: absolute; top: 0; bottom: 0; background: #ffffff2e; width: 0;
  transition: left .9s cubic-bezier(.2,.8,.2,1), width .9s cubic-bezier(.2,.8,.2,1); }
.cg-mark { position: absolute; top: 50%; width: 6px; height: 34px; border-radius: 3px;
  transform: translate(-50%, -50%); }
.cg-mark-guess { background: var(--muted); }
.cg-mark-guess::after { content: attr(data-v); position: absolute; top: -22px; left: 50%;
  transform: translateX(-50%); font-size: 13px; font-weight: 700; color: var(--muted); }
.cg-mark-truth { background: var(--accent2); box-shadow: 0 0 16px var(--accent2);
  transition: left .9s cubic-bezier(.2,.8,.2,1); }
.cg-readout-truth .cg-num { background: linear-gradient(90deg, var(--accent2), #fff);
  -webkit-background-clip: text; background-clip: text; }
.cg-truthlabel { text-align: center; font-size: 13px; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase; color: var(--muted); }
.pulsing { animation: cg-pulse .7s ease-in-out infinite; }
@keyframes cg-pulse { 0%,100% { opacity: 1; } 50% { opacity: .45; } }

@media (prefers-reduced-motion: reduce) {
  .cg-fill, .cg-knob, .cg-gap, .cg-mark-truth { transition: none; }
  .pulsing { animation: none; }
}

/* --- Round 2: four-way call. "Much" reads as the risky outer pair, so the
   shape of the stack tells you the stakes before you read a word. --- */
.cg-riskhint { text-align: center; font-size: 13px; font-weight: 700; color: var(--muted);
  padding: 8px 10px; border-radius: 12px; background: #ffffff0d; }
.cg-calls.four .cg-call { min-height: 68px; font-size: 20px; }
.cg-much_higher { background: linear-gradient(180deg, #1f9457, #12703f); }
.cg-much_lower { background: linear-gradient(180deg, #a6316d, #7a1f52); }
.cg-calls.four .cg-much_higher, .cg-calls.four .cg-much_lower { border-color: #ffffff4d; }
.cg-callpts { font-size: 14px; font-weight: 900; padding: 3px 8px; border-radius: 999px;
  background: #0006; letter-spacing: 0; }

/* --- Round 3: the survey board --- */
.cg-pickcount { text-align: center; font-size: 15px; font-weight: 800; color: var(--muted); }
.cg-pickcount.ready { color: var(--accent2); }
.cg-options { display: flex; flex-direction: column; gap: 8px; }
.cg-option { font: inherit; display: flex; align-items: center; gap: 12px; text-align: left;
  min-height: 56px; padding: 10px 14px; border-radius: 14px; border: 2px solid #ffffff22;
  background: #ffffff10; color: var(--ink); font-size: 17px; font-weight: 600;
  transition: background .15s ease-out, opacity .15s, transform .1s; }
.cg-option:active { transform: scale(.985); }
.cg-option .cg-optmark { flex: 0 0 24px; height: 24px; border-radius: 7px;
  border: 2px solid #ffffff44; }
.cg-option.on { background: linear-gradient(90deg, #ff5ea833, #6de3ff33); border-color: var(--accent2); }
.cg-option.on .cg-optmark { background: var(--accent2); border-color: var(--accent2); }
.cg-option.on .cg-optmark::after { content: '✓'; display: block; text-align: center;
  line-height: 20px; color: #10061f; font-weight: 900; font-size: 15px; }
.cg-option.muted { opacity: .42; }
.cg-lock:disabled { background: #ffffff1a; color: var(--muted); }

.cg-mypicks { display: flex; flex-direction: column; gap: 6px; }
.cg-mypick { padding: 10px 14px; border-radius: 12px; background: #ffffff12;
  font-weight: 700; font-size: 16px; }

.cg-boardlist { display: flex; flex-direction: column; gap: 6px; }
.cg-boardrow { display: flex; align-items: center; gap: 10px; padding: 10px 12px;
  border-radius: 12px; background: #ffffff0d; opacity: 0;
  animation: cg-rowin .35s ease-out forwards; }
.cg-boardrow.yours { background: linear-gradient(90deg, #ff5ea82e, #6de3ff2e);
  outline: 2px solid var(--accent2); }
@keyframes cg-rowin { from { opacity: 0; transform: translateX(-10px); } to { opacity: 1; transform: none; } }
.cg-brank { font-weight: 900; color: var(--muted); min-width: 2.4ch; font-size: 14px; }
.cg-btext { flex: 1; font-weight: 600; font-size: 16px; }
.cg-bshare { font-weight: 900; font-variant-numeric: tabular-nums; color: var(--accent2); }
.cg-breakdown { display: flex; flex-direction: column; gap: 4px; margin-top: 10px;
  font-size: 14px; font-weight: 600; color: var(--muted); }
.cg-late { min-height: 1px; }

@media (prefers-reduced-motion: reduce) { .cg-boardrow { animation: none; opacity: 1; } }

/* --- Host's game picker. Absent since the phone-first rewrite, which meant a
   second game could never actually be selected. Only rendered when there is
   more than one game to choose between. --- */
.game-picker { display: flex; flex-direction: column; gap: 8px; }
.game-tiles { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; }
.game-tile { font: inherit; display: flex; flex-direction: column; align-items: center;
  gap: 4px; padding: 14px 10px; min-height: 96px; border-radius: 16px;
  border: 2px solid #ffffff22; background: #ffffff10; color: var(--ink);
  transition: transform .12s ease-out, background .15s, border-color .15s; }
.game-tile:active { transform: scale(.97); }
.game-tile.on { background: linear-gradient(135deg, #ff5ea82e, #6de3ff2e);
  border-color: var(--accent2); }
.gt-thumb { font-size: 30px; line-height: 1; }
.gt-title { font-weight: 800; font-size: 15px; text-align: center; }
.gt-players { font-size: 12px; color: var(--muted); font-weight: 600; }

/* The "Card Games" group tile opens a sub-menu; a small caret hints at it. */
.game-tile.is-group { position: relative; }
.game-tile.is-group::after { content: '▾'; position: absolute; top: 8px; right: 10px;
  font-size: 13px; color: var(--muted); }
.game-tile.is-group[aria-expanded="true"]::after { content: '▴'; color: var(--accent2); }

/* Sub-menu of card games, revealed under the grid when the group is open. */
.game-subtiles { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px;
  margin-top: 8px; padding: 10px; border-radius: 16px;
  background: #ffffff08; border: 1px solid #ffffff1a; }
.game-tile.sub { min-height: 76px; padding: 10px 8px; }
.game-tile.sub .gt-thumb { font-size: 24px; }
.game-tile.sub .gt-title { font-size: 14px; }
.game-tile.soon { opacity: .5; }
.game-tile.soon .gt-players { color: var(--accent2); font-weight: 800;
  text-transform: uppercase; letter-spacing: .04em; }

/* --- Rules, right where the host picks the game. Previously a first-time
   player had no way to learn what "MUCH HIGHER" meant. --- */
.game-rules { border-radius: 14px; background: #ffffff0d; border: 1px solid #ffffff1a;
  padding: 10px 14px; }
.game-rules summary { cursor: pointer; font-weight: 800; font-size: 15px;
  color: var(--accent2); list-style: none; }
.game-rules summary::-webkit-details-marker { display: none; }
.game-rules summary::after { content: ' ▾'; color: var(--muted); }
.game-rules[open] summary::after { content: ' ▴'; }
.rules-blurb { margin: 8px 0 4px; font-size: 14px; color: var(--muted); font-weight: 600; }
.rules-list { margin: 6px 0 2px; padding-left: 18px; display: flex; flex-direction: column; gap: 6px; }
.rules-list li { font-size: 14px; line-height: 1.45; }


/* --- Lobby density -------------------------------------------------------
   The host lobby was ~1000px tall with a single player, so it scrolled two
   full screens before anyone had even joined. Everything here is about
   getting room code, QR, roster and controls into one comfortable scroll,
   with the roster free to grow as people arrive. --- */
#lobby.screen { gap: 12px; }
#lobby .logo { font-size: 26px; margin: 4px 0 2px; }

/* The QR is always visible — it's the fastest way for someone across the
   room to join, and hiding it behind a tap defeated the point. */

/* The roster grows naturally — no inner scroll, no clipping, ever. */
.roster-list-p { max-height: none; overflow: visible; }
.rp-item { padding: 8px 12px; }
.rp-av { font-size: 22px; }

.game-tiles { gap: 8px; }
.game-tile { min-height: 84px; padding: 10px 8px; }
.gt-thumb { font-size: 26px; }

.btn.danger { color: #ff9b9b; border-color: #ff5c5c44; }
.btn.danger:active { background: #ff5c5c1a; }

/* ===================================================================== *
 * LOBBY LAYOUT
 *
 * Desktop (>=900px): three columns.
 *   left   — who you are, and who else is here
 *   centre — the room itself, and the controls that start or end it
 *   right  — what you're going to play
 *
 * Mobile: DELIBERATELY UNCHANGED. The columns collapse via `display:
 * contents`, so their children drop into one flex column and `order`
 * restores the original single-column sequence exactly. The name/avatar
 * editors are desktop-only for now — they'd add height to a phone screen
 * that was already fine.
 * ===================================================================== */

/* ---- phone: same as it ever was ---- */
.lobby-grid { display: flex; flex-direction: column; gap: 16px; }
.lobby-col { display: contents; }

.code-block   { order: 1; }
#qrBox        { order: 2; }
.join-hint    { order: 3; }
.cast-hint    { order: 4; }
.roster-head  { order: 5; }
#rosterList   { order: 6; }
.admin-cap    { order: 7; }
#gamePicker   { order: 8; }
#gameSetup    { order: 9; }
#randomBtn    { order: 10; }
#adminRoomCtl { order: 11; display: flex; flex-direction: column; gap: 10px; }
#waitPanel    { order: 12; }

/* The in-lobby identity editors are a desktop addition — keep phones as-is. */
.lobby-col-you > .field { display: none; }

/* ---- desktop: three real columns ---- */
@media (min-width: 900px) {
  body.in-lobby .phone { max-width: 1180px; }

  .lobby-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    align-items: start;
    gap: 28px;
  }
  /* Columns become real boxes again, so `order` on children stops applying. */
  .lobby-col {
    display: flex; flex-direction: column; gap: 14px;
    background: #ffffff08; border: 1px solid #ffffff14;
    border-radius: 18px; padding: 18px 16px;
  }
  .lobby-col > * { order: 0; }

  .lobby-col-you > .field { display: flex; }
  .lobby-col-you .avatar-grid { grid-template-columns: repeat(6, 1fr); gap: 6px; }
  .lobby-col-you .avatar-opt { font-size: 20px; padding: 6px 0; }

  /* Centre column is the focal point: the code and the two decisive buttons. */
  .lobby-col-room { align-items: center; text-align: center; }
  .lobby-col-room .big-code { font-size: 52px; }
  .lobby-col-room .qr-box-sm { width: 168px; height: 168px; }
  .lobby-col-room .join-hint,
  .lobby-col-room .cast-hint { max-width: 30ch; }
  #adminRoomCtl { width: 100%; margin-top: auto; }
  #adminRoomCtl .btn { width: 100%; }

  #gamePicker .game-tiles { grid-template-columns: repeat(2, 1fr); }
  .lobby-col-game #randomBtn { margin-top: auto; }

  /* The roster grows freely — no inner scrollbar. That was the original
     complaint and re-introducing one here would repeat it. The column is
     `align-items: start`, so a long roster simply makes the page longer. */
  #rosterList { max-height: none; overflow: visible; }
}

/* ===================================================================== *
 * Punchline — phone controller
 * ===================================================================== */
.pu-writecard { background: #ffffff0d; border: 1px solid #ffffff1a; border-radius: 16px; padding: 14px; margin-top: 12px; display: flex; flex-direction: column; gap: 10px; }
.pu-writecard.done { opacity: .7; }
.pu-prompt { font-size: 19px; font-weight: 800; margin: 0; line-height: 1.3; }
.pu-locked { color: var(--accent2); font-weight: 800; }
.pu-err { color: #ff9a9a; font-weight: 600; margin: 0; font-size: 14px; }
.pu-yours { text-align: center; font-weight: 800; color: var(--muted); margin: 8px 0; }
.pu-votes { display: flex; flex-direction: column; gap: 12px; margin-top: 6px; }
.pu-vote { font: inherit; display: flex; align-items: center; gap: 12px; text-align: left; min-height: 84px; padding: 14px 16px; border-radius: 16px; border: 2px solid #ffffff22; color: var(--ink); font-weight: 700; font-size: 18px; transition: transform .12s ease-out, opacity .2s; }
.pu-vote.va { background: linear-gradient(180deg, #7a2f9a, #5a1f74); }
.pu-vote.vb { background: linear-gradient(180deg, #2f6f9a, #1f4f74); }
.pu-vote:active { transform: scale(.98); }
.pu-vote.chosen { outline: 3px solid var(--accent2); outline-offset: 2px; }
.pu-voteletter { width: 1.7em; height: 1.7em; flex: none; display: flex; align-items: center; justify-content: center; background: #ffffff2e; border-radius: 10px; font-weight: 900; }
.pu-votetext { flex: 1; }
.pu-reveal { display: flex; flex-direction: column; gap: 10px; margin-top: 8px; }
.pu-revrow { display: flex; align-items: center; gap: 8px; background: #0004; border-radius: 12px; padding: 10px 12px; flex-wrap: wrap; }
.pu-revrow.win { background: #57e08a26; outline: 2px solid var(--good); }
.pu-revav { font-size: 20px; }
.pu-revname { font-weight: 700; color: var(--muted); }
.pu-revtext { flex: 1 1 100%; font-weight: 600; }
.pu-revvotes { color: var(--accent2); font-weight: 800; font-size: 14px; }
.pu-revgain { font-weight: 900; color: var(--good); margin-left: auto; }
.pu-shout { text-align: center; font-weight: 900; color: var(--accent); letter-spacing: .03em; margin-top: 6px; }
.pu-finalopts { display: flex; flex-direction: column; gap: 10px; margin-top: 6px; }
.pu-finalopt { font: inherit; text-align: left; min-height: 60px; padding: 12px 14px; border-radius: 14px; border: 2px solid #ffffff22; background: #ffffff12; color: var(--ink); font-weight: 600; font-size: 17px; transition: transform .1s ease-out, opacity .2s; }
.pu-finalopt:active { transform: scale(.985); }
.pu-finalopt.chosen { outline: 3px solid var(--accent2); background: linear-gradient(90deg, #ff5ea833, #6de3ff33); }
.pu-finalboard { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; }
.pu-fbrow { display: flex; align-items: center; gap: 8px; background: #ffffff0d; border-radius: 12px; padding: 9px 12px; flex-wrap: wrap; }
.pu-fbrow.top { background: linear-gradient(90deg, #ff5ea82e, #6de3ff2e); outline: 2px solid var(--accent2); }
.pu-fbrank { font-weight: 900; color: var(--muted); min-width: 2.2ch; }
.pu-fbav { font-size: 20px; }
.pu-fbtext { flex: 1 1 60%; font-weight: 600; }
.pu-fbvotes { color: var(--accent2); font-weight: 800; font-size: 14px; }
.pu-fbgain { font-weight: 900; color: var(--good); margin-left: auto; }

/* ===================================================================== *
 * War — phone controller
 * ===================================================================== */
.wr-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.wr-chip { font-weight: 800; font-size: 14px; color: var(--muted);
  background: #ffffff12; border: 1px solid #ffffff1f; border-radius: 999px; padding: 5px 12px; white-space: nowrap; }
.wr-youare { text-align: center; font-weight: 800; font-size: 18px; color: var(--accent2); margin: 6px 0; }

.wr-card { position: relative; align-self: center; width: 116px; height: 158px; border-radius: 16px;
  background: #fbfbff; box-shadow: 0 8px 24px #0007, inset 0 0 0 2px #0000000d;
  display: flex; flex-direction: column; align-items: center; justify-content: center; margin: 8px auto; }
.wr-card.big { width: 150px; height: 206px; }
.wr-card.red { color: #e5484d; }
.wr-card.black { color: #1b1b2e; }
.wr-card .wr-rank { font-size: 54px; font-weight: 900; line-height: 1; }
.wr-card.big .wr-rank { font-size: 72px; }
.wr-card .wr-suit { font-size: 40px; line-height: 1; }
.wr-card.big .wr-suit { font-size: 56px; }
.wr-card.back { background: linear-gradient(135deg, #3a1d6e, #6d28d9); color: #ffffff8c; }
.wr-card .wr-back { font-size: 60px; }
.wr-card.big { animation: wrFlipIn .32s cubic-bezier(.2,.8,.2,1) both; }
@keyframes wrFlipIn { from { transform: rotateY(90deg) scale(.9); opacity: 0; } to { transform: none; opacity: 1; } }

.wr-flip { display: block; width: 100%; min-height: 140px; margin: 10px 0 6px; font: inherit;
  font-size: 40px; font-weight: 900; letter-spacing: .06em; color: #fff; border: none; border-radius: 22px;
  background: linear-gradient(135deg, var(--accent2), var(--accent)); box-shadow: 0 10px 30px #ff5ea840; }
.wr-flip:active { transform: scale(.98); }
.wr-flip:disabled { filter: grayscale(.4) brightness(.8); }
@media (prefers-reduced-motion: reduce) { .wr-card.big { animation: none; } }

/* ===================================================================== *
 * Blackjack — phone controller
 * ===================================================================== */
.bj-prompt { text-align: center; font-size: 17px; font-weight: 800; margin: 4px 0; position: relative; }

/* ===== The casino table (phone) ===== */
/* The table is one full-bleed printed-felt SVG scene (drawn in blackjack.player.js);
 * live DOM (cards, chips, seats) is an overlay on the same coordinate grid.
 * Depth comes from the artwork's ellipse geometry — no CSS tilt. */
/* Full-bleed on phones, but CAPPED and centered on the app column — on a
 * desktop window an uncapped 100vw stretched the design grid, piling the
 * seat spots to one side. Capped, print and seats stay aligned everywhere. */
.bj-stage { position: relative; width: min(100vw, 520px);
  margin-left: calc(50% - min(50vw, 260px));
  height: min(82vw, 330px); overflow: hidden; }
.bj-svg-hold { position: absolute; inset: 0; }
.bj-svg-hold svg { display: block; width: 100%; height: 100%; }
.bj-overlay { position: absolute; inset: 0; }
.bj-ov { position: absolute; transform: translate(-50%, -50%);
  display: flex; flex-direction: column; align-items: center; }
.bj-ov.mine { z-index: 2; }
.bj-cluster { display: flex; flex-direction: column; align-items: center; gap: 3px; }

/* Seats ON the printed circles: ten spots along the felt's bottom arc,
 * position 1 rightmost. Occupied spots carry the player's avatar + name +
 * bet, with their overlapped cards just above; empties keep the printed
 * circle with a faint number. */
.bj-spot { display: flex; flex-direction: column; align-items: center; gap: 1px; width: 70px; }
.bj-spot-circle { width: 34px; height: 34px; border-radius: 50%;
  background: #ffffff1f; border: 2px solid #ffffff59;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 0 10px #ffffff2b, inset 0 0 8px #ffffff24; }
.bj-spot-av { font-size: 19px; line-height: 1; }
.bj-spot-num { font-size: 12px; font-weight: 900; color: #ffffff3d; }
.bj-spot-name { font-size: 9px; font-weight: 800; color: #eafff3d9; max-width: 66px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-shadow: 0 1px 2px #000c; }
.bj-spot-meta { display: flex; align-items: center; gap: 4px; }
.bj-spot.empty .bj-spot-circle { background: #ffffff0d; border-color: #ffffff2b; box-shadow: none; }
.bj-spot.you .bj-spot-circle { border-color: #ffd76e; background: #ffd76e2b; box-shadow: 0 0 12px #ffd76e59; }
.bj-spot.acting .bj-spot-circle { border-color: var(--accent); box-shadow: 0 0 16px #ff5ea88c; }
.bj-spot.sitout { opacity: .55; }
/* Their cards overlap like a held hand on a real table. */
.bj-spot .cc-hand { gap: 0; margin-bottom: 2px; flex-wrap: nowrap; }
.bj-spot .cc-card:not(:first-child) { margin-left: -27px; }
.bj-mini-bet { font-size: 10px; font-weight: 900; color: #ffe9a8; text-shadow: 0 1px 2px #000a; }
.bj-mini-delta { font-size: 11px; font-weight: 900; color: var(--muted); }
.bj-mini-delta.up { color: #57e08a; } .bj-mini-delta.down { color: #ff6b6b; }
.bj-badge.sm { min-width: 20px; font-size: 11px; padding: 2px 5px; border-width: 1.5px; border-radius: 7px; }

/* A REAL blackjack table: the classic D-shape seen from your seat — flat
 * dealer side at the top, the padded burgundy rail sweeping in a big arc
 * toward you at the bottom (image 1). The border-radius IS the table shape;
 * the leather trim follows the curve. */
.bj-table-phone { position: relative; margin: 6px 0 0; padding: 42px 18px 54px;
  border-radius: 16px 16px 48% 48% / 16px 16px 150px 150px;
  border: 8px solid #7a1f2b; border-bottom-width: 12px;
  background:
    url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.07 0'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E"),
    radial-gradient(ellipse at 50% 8%, #1e6f48 0%, #155a34 55%, #0e3f24 100%);
  box-shadow: inset 0 0 0 2px #ffffff10, inset 0 0 52px #00000066, inset 0 10px 14px -10px #ffffff2b, 0 12px 28px #0008; }
/* Stitched seam where the leather rail meets the felt. */
.bj-table-phone::after { content: ''; position: absolute; inset: 2px; border-radius: inherit;
  border: 1.5px dashed #ffffff30; pointer-events: none; }
/* Dealer dressing: chip tray + card shoe along the top edge. */
.bj-dress { position: absolute; top: 7px; left: 0; right: 0; display: flex;
  justify-content: space-between; padding: 0 12px; pointer-events: none; }
/* The dealer's chip rack: a real tray — five slots, each a stack of chips
 * seen edge-on (the striped column IS the stack of chip edges). */
.bj-tray { display: flex; align-items: flex-end; gap: 4px;
  background: linear-gradient(180deg, #1d1d28, #0c0c13);
  border: 1px solid #ffffff26; border-bottom-color: #00000088;
  border-radius: 6px; padding: 4px 5px 3px; box-shadow: inset 0 2px 4px #000c, 0 2px 5px #0007; }
.bj-tray-chip { width: 12px; height: 22px; border-radius: 2.5px; display: block;
  background: repeating-linear-gradient(180deg, var(--c) 0 3px, var(--s, #f4f1e6) 3px 4px) !important;
  box-shadow: inset 0 0 2px #0009, inset 1px 0 1px #ffffff2c; }
/* The dealing shoe: black casino shoe with the next card peeking out. */
.bj-shoe-box { position: relative; width: 38px; height: 24px; border-radius: 4px 11px 5px 5px;
  background: linear-gradient(160deg, #2c2c38, #131320);
  box-shadow: 0 3px 7px #0009, inset 0 1px 0 #ffffff26, inset 0 -3px 5px #00000066; }
.bj-shoe-box::after { content: ''; position: absolute; left: 4px; bottom: 3px; width: 12px; height: 16px;
  border-radius: 2px; background: linear-gradient(155deg, #ffffff, #efede5);
  box-shadow: 0 1px 2px #0007; transform: rotate(-9deg); }
/* Curved felt text — what this table actually pays. */
.bj-arc-text { display: block; width: 82%; margin: 0 auto -6px; }
.bj-arc-text text { fill: #ffffff3d; font-size: 14.5px; font-weight: 800; letter-spacing: .12em; }
/* MIN/MAX placard (real table limits) — top-left of the felt. */
.bj-sign { position: absolute; top: 42px; left: 8px; display: flex; flex-direction: column;
  font-size: 9.5px; font-weight: 900; letter-spacing: .06em; color: #ffe9a8;
  background: #00000055; border: 1px solid #ffd76e66; border-radius: 6px; padding: 3px 6px; line-height: 1.35; }

/* A hand row on the felt: label, cards + total badge, bet stack. */
.bj-row { display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 6px 0; }
.bj-row + .bj-row { border-top: 1px dashed #ffffff1a; }
.bj-row-label { font-size: 12px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; color: #d9f7e6b8; }
.bj-row-cards { display: flex; align-items: center; gap: 8px; }
/* Navy total badge pinned beside the cards (the "11" style in image 1). */
.bj-badge { min-width: 30px; text-align: center; background: #16233a; color: #fff;
  border: 2px solid #ffffff2e; border-radius: 9px; padding: 4px 7px;
  font-size: 15px; font-weight: 900; box-shadow: 0 2px 6px #0006; }
.bj-badge.red { background: #7a1f2b; }
.bj-badge.gold { background: #8a6a12; border-color: #ffd76e; color: #ffe9a8; }
/* The bet as a stack of chips with the amount underneath (image 1). */
.bj-bet-stack { display: flex; flex-direction: column; align-items: center; gap: 2px; }
.bj-pile { position: relative; width: 34px; height: 42px; }
.bj-pile-chip { position: absolute; left: 0; width: 34px; height: 34px; display: block;
  box-shadow: 0 3px 0 var(--cd), 0 3px 6px #0008, inset 0 -2px 4px #00000042, inset 0 1px 2px #ffffff30; }
.bj-pile-chip:nth-child(1) { bottom: 0; } .bj-pile-chip:nth-child(2) { bottom: 5px; } .bj-pile-chip:nth-child(3) { bottom: 10px; }
.bj-pile-amt { font-size: 13px; font-weight: 900; color: #ffe9a8; text-shadow: 0 1px 2px #000a; }

/* Joined BALANCE | STREAK | WIN strip — small, always visible. */
.bj-bank-bar { display: grid; grid-template-columns: 1fr 1fr; margin-top: 8px;
  background: #101018; border: 1px solid #ffffff1f; border-radius: 12px; overflow: hidden; }
.bj-bank-bar.three { grid-template-columns: 1.2fr 1fr 1fr; }
.bj-cell.streak-w .bj-cell-val { color: #57e08a; font-weight: 900; }
.bj-cell.streak-l .bj-cell-val { color: #ff6b6b; font-weight: 900; }
.bj-cell { display: flex; align-items: baseline; justify-content: center; gap: 7px; padding: 8px 6px; }
.bj-cell + .bj-cell { border-left: 1px solid #ffffff1f; }
.bj-cell-label { font-size: 10.5px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; color: var(--muted); }
.bj-cell-val { font-size: 17px; font-weight: 900; }
.bj-cell.win .bj-cell-val { color: #57e08a; }

/* Chip-token bet composer: dashed gold bet circle on the felt, the five
 * casino chips on the wooden rim below, Clear + Bet Now (image 3). */
.bj-composer { display: flex; flex-direction: column; gap: 8px; }
.bj-bet-circle { position: relative; width: 108px; height: 108px; margin: 6px auto; border-radius: 50%;
  border: 3px dashed #ffd76e99; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
  background: #00000022; }
.bj-circle-hint { font-size: 9px; font-weight: 900; letter-spacing: .12em; color: #ffe9a891; }
.bj-bet-circle.empty .bj-chip.stage { opacity: .35; }
/* The wooden chip ledge in front of you, tucked under the table's curved
 * rail (image 3) — a separate piece of furniture, not part of the felt. */
.bj-wood { position: relative; z-index: 1; margin: -10px 10px 0; padding: 8px 8px;
  border-radius: 14px;
  background:
    repeating-linear-gradient(91deg, #00000024 0 2px, #00000000 2px 11px),
    repeating-linear-gradient(89deg, #ffffff12 0 1px, #ffffff00 1px 17px),
    linear-gradient(180deg, #7c4e2b, #5a3419 55%, #3c2311);
  box-shadow: 0 6px 16px #0007, inset 0 2px 4px #ffffff2e, inset 0 -4px 9px #00000073; }
.bj-chip-row { display: flex; justify-content: center; gap: 8px; flex-wrap: wrap; }
/* A REAL clay casino chip: 8 edge spots (repeating-conic), a solid center
 * inlay with an inner print ring (radial), a specular sheen, and visible
 * thickness (the darker rim under it). One recipe, colored per value. */
.bj-chip, .bj-pile-chip, .bj-tray-chip {
  --s: #f4f1e6;
  border: none; border-radius: 50%;
  background:
    radial-gradient(circle at 50% 24%, #ffffff4a 0%, #ffffff00 40%),
    radial-gradient(circle, var(--c) 0 36%, #f4f1e6 36.5% 43%, var(--c) 43.5% 55.5%, #ffffff00 56%),
    repeating-conic-gradient(var(--c) 0deg 24deg, var(--s) 24deg 45deg);
  box-shadow: 0 3px 0 var(--cd), 0 6px 12px #0008, inset 0 -2px 5px #00000042, inset 0 1px 2px #ffffff30;
  color: var(--t, #fff); text-shadow: 0 1px 2px #00000073;
}
.bj-chip { width: 52px; height: 52px; font: inherit; font-size: 12.5px; font-weight: 900;
  display: flex; align-items: center; justify-content: center; }
.bj-chip:active { transform: scale(.94); }
.bj-chip:disabled { opacity: .32; filter: grayscale(.7); }
/* Classic casino colours: $1 white (blue spots), $5 red, $25 green,
 * $100 black (white spots), $250 purple. */
.bj-chip.v1, .bj-pile-chip.v1, .bj-tray-chip.v1 { --c: #ece9df; --cd: #b3b0a3; --s: #2d6bb5; --t: #2b2b33; text-shadow: none; }
.bj-chip.v5, .bj-pile-chip.v5, .bj-tray-chip.v5 { --c: #c22532; --cd: #7f121d; }
.bj-chip.v25, .bj-pile-chip.v25, .bj-tray-chip.v25 { --c: #1f8a4c; --cd: #0e5a2e; }
.bj-chip.v100, .bj-pile-chip.v100, .bj-tray-chip.v100 { --c: #23232e; --cd: #0b0b12; --s: #e8e6dd; }
.bj-chip.v250, .bj-pile-chip.v250, .bj-tray-chip.v250 { --c: #6d28d9; --cd: #431689; }
/* The staged-bet chip sitting inside the bet circle (a div, not a button). */
.bj-chip.mini { width: 52px; height: 52px; font-size: 12px;
  display: flex; align-items: center; justify-content: center; font-weight: 900; }
.bj-staged { text-align: center; font-size: 34px; font-weight: 900; color: #ffd76e; }
.bj-composer-actions { display: grid; grid-template-columns: 1fr 2fr; gap: 10px; }
.bj-clear { font: inherit; font-size: 16px; font-weight: 800; padding: 18px 8px; border-radius: 16px;
  border: 2px solid #ffffff2c; background: #ffffff10; color: var(--ink); }
.bj-clear:disabled { opacity: .4; }
.bj-betnow { font: inherit; font-size: 20px; font-weight: 900; padding: 18px 8px; border: none; border-radius: 16px;
  background: linear-gradient(135deg, var(--accent2), var(--accent)); color: #16002a; }
.bj-betnow:disabled { filter: grayscale(.6) brightness(.75); }
.bj-betnow:active, .bj-clear:active { transform: scale(.98); }

.bj-dealer-label, .bj-you-label { text-align: center; color: var(--muted); font-weight: 700; font-size: 14px; margin: 8px 0 2px; }
.bj-hand { display: flex; justify-content: center; gap: 6px; flex-wrap: wrap; }
.bj-card { position: relative; width: 60px; height: 84px; border-radius: 9px; background: #fbfbff;
  box-shadow: 0 4px 12px #0006; display: flex; flex-direction: column; align-items: center; justify-content: center; }
.bj-card.red { color: #e5484d; } .bj-card.black { color: #1b1b2e; }
.bj-card .bj-rank { font-size: 26px; font-weight: 900; line-height: 1; }
.bj-card .bj-suit { font-size: 18px; }
.bj-card.back { background: linear-gradient(135deg, #3a1d6e, #6d28d9); color: #ffffff8c; }
.bj-card .bj-back { font-size: 30px; }
.bj-total { text-align: center; font-size: 26px; font-weight: 900; margin: 8px 0; }
.bj-total.bust { color: #ff6b6b; } .bj-total.bj { color: #ffd76e; }
.bj-chips { font-weight: 800; font-size: 14px; color: var(--muted); background: #ffffff12;
  border: 1px solid #ffffff1f; border-radius: 999px; padding: 5px 12px; white-space: nowrap; }
.bj-actions { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 10px; }
.bj-act { font: inherit; font-size: 26px; font-weight: 900; padding: 26px 8px; border: none; border-radius: 20px; color: #fff; }
.bj-act.hit { background: linear-gradient(135deg, #ff8a3d, #ff5ea8); }
.bj-act.stand { background: linear-gradient(135deg, #6de3ff, #57e08a); color: #06232a; }
.bj-act:active { transform: scale(.98); } .bj-act:disabled { filter: grayscale(.5) brightness(.8); }
/* Double / Surrender: real options, but visually secondary to Hit/Stand. */
.bj-actions.secondary { margin-top: 8px; }
.bj-actions.secondary.solo { grid-template-columns: 1fr; }
.bj-act.double, .bj-act.surrender { font-size: 16px; padding: 14px 8px; }
.bj-act.double { background: #ffd76e1a; border: 2px solid #ffd76e; color: #ffe9a8; }
.bj-act.surrender { background: #ffffff10; border: 2px solid #ffffff2c; color: var(--muted); }

/* War — DOUBLE token */
.wr-double { display: block; width: 100%; margin: 10px 0 0; font: inherit; font-size: 18px; font-weight: 900;
  padding: 16px; border-radius: 16px; border: 2px solid #ffd76e; background: #ffd76e1a; color: #ffe9a8; }
.wr-double:active { transform: scale(.98); } .wr-double:disabled { opacity: .5; }
.wr-armed { text-align: center; font-weight: 900; color: #ffd76e; background: #ffd76e14;
  border: 1px solid #ffd76e55; border-radius: 14px; padding: 12px; margin-top: 10px; }

/* Blackjack — human dealer (player mode) */
.bj-dealer-tag { text-align: center; font-weight: 900; font-size: 18px; color: #ffd76e;
  background: #ffd76e14; border: 1px solid #ffd76e55; border-radius: 14px; padding: 10px; margin: 6px 0; }
