/* ═══════════════ Trivia Rumble — drenched party palette ═══════════════ */
* { margin: 0; padding: 0; box-sizing: border-box; }
[hidden] { display: none !important; }
html { -webkit-text-size-adjust: 100%; }
body {
  font-family: "Outfit", system-ui, sans-serif;
  background: var(--bg);
  background-image:
    radial-gradient(1100px 700px at 85% -10%, oklch(0.30 0.06 25 / 0.55), transparent 60%),
    radial-gradient(900px 600px at -10% 110%, oklch(0.28 0.05 255 / 0.45), transparent 60%);
  color: var(--ink);
  min-height: 100dvh;
  overflow-x: hidden;
}

/* ─────────── screens ─────────── */
.screen {
  display: none;
  min-height: 100dvh;
  padding: max(20px, env(safe-area-inset-top)) 20px max(20px, env(safe-area-inset-bottom));
}
.screen.active { display: flex; flex-direction: column; align-items: center; justify-content: center; animation: screen-in 0.45s var(--ease); }
@keyframes screen-in { from { opacity: 0; transform: translateY(14px) scale(0.985); } }

/* ─────────── buttons ─────────── */
.btn {
  font: inherit; font-weight: 800; letter-spacing: 0.01em;
  border: 0; border-radius: var(--r-ctl); cursor: pointer;
  color: var(--gold-ink); background: var(--gold);
  box-shadow: 0 4px 0 var(--gold-edge);
  padding: 14px 24px; font-size: 1.05rem;
  transition: transform 0.15s var(--ease), box-shadow 0.15s var(--ease), filter 0.2s;
  touch-action: manipulation; -webkit-tap-highlight-color: transparent;
}
.btn:hover { filter: brightness(1.06); }
.btn:active { transform: translateY(3px) scale(0.99); box-shadow: 0 1px 0 var(--gold-edge); }
.btn:disabled { opacity: 0.45; cursor: not-allowed; }
.btn-big { width: 100%; padding: 18px; font-size: 1.2rem; }
.btn-primary { background: var(--gold); }
.btn-secondary { background: var(--teal); color: oklch(0.16 0.04 200); box-shadow: 0 4px 0 var(--teal-edge); }
.btn-secondary:active { box-shadow: 0 1px 0 var(--teal-edge); }
.btn-ghost { background: transparent; color: var(--ink-dim); box-shadow: inset 0 0 0 2px var(--line); font-weight: 600; }
.btn-ghost:active { transform: scale(0.98); }

/* ─────────── home ─────────── */
.home-wrap { width: min(420px, 100%); display: flex; flex-direction: column; gap: 26px; }
.logo { text-align: center; }
.logo h1 {
  font-size: clamp(3rem, 13vw, 4.2rem); font-weight: 900; line-height: 0.92;
  letter-spacing: -0.03em; text-transform: uppercase;
}
.tagline { color: var(--ink-dim); font-weight: 500; margin-top: 10px; }
.logo-badges { display: flex; justify-content: center; gap: 10px; margin-bottom: 18px; }
.badge {
  width: 44px; height: 44px; border-radius: 14px; display: grid; place-items: center;
  font-size: 1.15rem; color: oklch(0.98 0.01 85); animation: badge-bob 2.6s var(--ease) infinite;
}
.badge:nth-child(2) { animation-delay: 0.2s; } .badge:nth-child(3) { animation-delay: 0.4s; } .badge:nth-child(4) { animation-delay: 0.6s; }
@keyframes badge-bob { 0%, 100% { transform: translateY(0) rotate(-3deg); } 50% { transform: translateY(-7px) rotate(3deg); } }
.b-coral { background: var(--coral); box-shadow: 0 4px 0 var(--coral-edge); }
.b-amber { background: var(--amber); box-shadow: 0 4px 0 var(--amber-edge); }
.b-teal  { background: var(--teal);  box-shadow: 0 4px 0 var(--teal-edge); }
.b-blue  { background: var(--blue);  box-shadow: 0 4px 0 var(--blue-edge); }

#home-form { display: flex; flex-direction: column; gap: 16px; }
.field { display: flex; flex-direction: column; gap: 8px; }
.field-label { font-weight: 700; font-size: 0.9rem; color: var(--ink-dim); }
input[type="text"], input[type="email"], input[type="password"] {
  font: inherit; font-weight: 600; font-size: 1.1rem;
  background: var(--bg-sink); color: var(--ink);
  border: 2px solid var(--line); border-radius: var(--r-ctl);
  padding: 14px 16px; outline: none; width: 100%;
  transition: border-color 0.2s;
}
input[type="text"]:focus, input[type="email"]:focus, input[type="password"]:focus { border-color: var(--gold); }
input::placeholder { color: oklch(0.5 0.02 60); font-weight: 500; }

.divider { display: flex; align-items: center; gap: 12px; color: var(--ink-dim); font-size: 0.85rem; font-weight: 600; }
.divider::before, .divider::after { content: ""; flex: 1; height: 2px; background: var(--line); border-radius: 1px; }

.join-row { display: grid; grid-template-columns: 1fr auto; gap: 10px; }
.code-input {
  text-transform: uppercase; text-align: center;
  font-weight: 900 !important; font-size: 1.5rem !important; letter-spacing: 0.35em;
}
.error-msg {
  background: oklch(0.32 0.09 25); color: oklch(0.9 0.05 25);
  border-radius: 12px; padding: 10px 14px; font-weight: 600; font-size: 0.95rem;
  animation: shake 0.4s var(--ease);
}
@keyframes shake { 0%,100% { transform: translateX(0); } 25% { transform: translateX(-6px); } 75% { transform: translateX(6px); } }

/* ─────────── lobby ─────────── */
.lobby-wrap { width: min(460px, 100%); display: flex; flex-direction: column; gap: 22px; text-align: center; }
.lobby-hint { color: var(--ink-dim); font-weight: 500; font-size: 0.95rem; }
.room-code {
  font: inherit; border: 0; cursor: pointer; -webkit-tap-highlight-color: transparent;
  background: var(--bg-raise); border-radius: var(--r-panel);
  padding: 18px 20px 14px; display: flex; flex-direction: column; gap: 2px; align-items: center;
  box-shadow: inset 0 0 0 2px var(--line);
  transition: transform 0.15s var(--ease);
}
.room-code:active { transform: scale(0.98); }
#room-code-text {
  font-size: clamp(3.4rem, 18vw, 5rem); font-weight: 900; letter-spacing: 0.18em;
  color: var(--gold); line-height: 1; text-indent: 0.18em;
}
.copy-hint { color: var(--ink-dim); font-size: 0.8rem; font-weight: 600; }

.lobby-players h2 { font-size: 1rem; font-weight: 700; color: var(--ink-dim); margin-bottom: 12px; }
.player-list { list-style: none; display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; }
/* The roster item is a container: the pill itself is .chip--s, which every
   other screen also uses, and the kick button rides alongside it. The host used
   to wear the gold ring here. It now means "you", which is the one thing a
   person needs to find in a roster of twenty. */
.roster-item {
  display: inline-flex; align-items: center; gap: 4px;
  animation: chip-in 0.4s var(--ease);
}
@keyframes chip-in { from { opacity: 0; transform: scale(0.6); } }
.lobby-empty { color: var(--ink-dim); font-weight: 500; margin-top: 10px; }

/* Your own seat (Home board, lobby frames): a card above the roster for a
   player who is not signed in, cream ringed, with a reroll on the avatar's
   corner and a pencil that turns the name into a field in place. */
.me-card {
  display: flex; align-items: center; gap: 12px; padding: 14px; margin-bottom: 14px;
  background: var(--bg-raise); border-radius: 24px; box-shadow: inset 0 0 0 2px var(--ink);
  text-align: left;
}
.me-face { position: relative; flex: none; }
.me-avatar {
  width: 56px; height: 56px; border-radius: 17px; background: var(--bg-sink);
  display: grid; place-items: center; font-size: 32px; line-height: 1;
}
.me-reroll {
  position: absolute; right: -4px; bottom: -4px; width: 22px; height: 22px; padding: 0; border: 0;
  border-radius: 999px; background: var(--bg-raise); color: var(--ink); box-shadow: inset 0 0 0 2px var(--line);
  display: grid; place-items: center; cursor: pointer; -webkit-tap-highlight-color: transparent;
}
/* A 22px badge is too small to hit, so its target reaches past it. */
.me-reroll::after { content: ""; position: absolute; inset: -11px; }
.me-reroll:active svg { transform: rotate(-90deg); transition: transform 0.2s var(--ease); }
.me-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.me-name { font-weight: 800; font-size: 20px; line-height: 1.2; overflow-wrap: anywhere; }
.me-crown { font-size: 16px; margin-left: 6px; }
.me-you { font-weight: 600; font-size: 12px; color: var(--ink-dim); }
.me-edit, .me-ok {
  flex: none; width: 44px; height: 44px; border: 0; border-radius: 14px; cursor: pointer;
  display: grid; place-items: center; -webkit-tap-highlight-color: transparent;
}
.me-edit { background: var(--bg-sink); color: var(--ink); box-shadow: inset 0 0 0 2px var(--line); }
.me-ok { background: var(--good); color: var(--bg-sink); box-shadow: 0 3px 0 color-mix(in oklch, var(--good), black 22%); }
.me-ok:active { transform: translateY(2px); box-shadow: 0 1px 0 color-mix(in oklch, var(--good), black 22%); }
.me-reroll:focus-visible, .me-edit:focus-visible, .me-ok:focus-visible {
  outline: none; box-shadow: 0 0 0 3px var(--bg), 0 0 0 5px var(--ink);
}
.me-rename { flex: 1; min-width: 0; display: flex; align-items: center; gap: 12px; }
.me-rename input {
  flex: 1; min-width: 0; font: inherit; font-weight: 800; font-size: 16px; white-space: nowrap;
  padding: 12px 10px; border: 0; border-radius: 14px; outline: none;
  background: var(--bg-sink); color: var(--ink); box-shadow: inset 0 0 0 2px var(--gold); caret-color: var(--gold);
}
.me-rename input::selection { background: color-mix(in oklch, var(--gold) 30%, transparent); }
/* Editing: the avatar steps down and only the field and the tick remain. */
.me-card.is-editing .me-avatar { width: 48px; height: 48px; border-radius: 15px; font-size: 28px; }
.me-card.is-editing .me-reroll, .me-card.is-editing .me-text, .me-card.is-editing .me-edit { display: none; }
.me-count {
  font-weight: 600; font-size: 12px; color: var(--ink-dim); text-align: left;
  padding-left: 4px; margin: -8px 0 14px; font-variant-numeric: tabular-nums;
}
@media (prefers-reduced-motion: reduce) {
  .me-reroll:active svg, .me-ok:active { transform: none; }
}

.host-settings {
  background: var(--bg-raise); border-radius: var(--r-panel); padding: 20px;
  display: flex; flex-direction: column; gap: 16px; text-align: left;
  box-shadow: inset 0 0 0 2px var(--line);
}
.setting { display: flex; flex-direction: column; gap: 8px; }
.setting-label { font-weight: 700; font-size: 0.85rem; color: var(--ink-dim); }
.seg { display: flex; gap: 6px; background: var(--bg-sink); border-radius: 12px; padding: 4px; }
.seg-btn {
  flex: 1; font: inherit; font-weight: 700; font-size: 0.95rem;
  background: transparent; color: var(--ink-dim); border: 0; border-radius: 9px;
  padding: 9px 4px; cursor: pointer; transition: background 0.2s, color 0.2s;
  -webkit-tap-highlight-color: transparent;
}
.seg-btn.active { background: var(--gold); color: var(--gold-ink); }
.select {
  font: inherit; font-weight: 600; font-size: 1rem;
  background: var(--bg-sink); color: var(--ink);
  border: 2px solid var(--line); border-radius: 12px; padding: 11px 12px; outline: none;
}
.waiting-host { color: var(--ink-dim); font-weight: 600; animation: pulse-dim 1.8s ease-in-out infinite; }
@keyframes pulse-dim { 50% { opacity: 0.55; } }

/* ─────────── countdown ─────────── */
.countdown-wrap { text-align: center; }
.countdown-label { font-weight: 700; color: var(--ink-dim); font-size: 1.2rem; }
.countdown-num {
  font-size: clamp(7rem, 40vw, 12rem); font-weight: 900; color: var(--gold); line-height: 1;
}
.countdown-num.tick { animation: count-pop 0.9s var(--ease); }
@keyframes count-pop { 0% { transform: scale(1.6); opacity: 0; } 30% { transform: scale(1); opacity: 1; } }

/* ─────────── question ─────────── */
.q-wrap { width: min(560px, 100%); display: flex; flex-direction: column; gap: 16px; flex: 1; max-height: 860px; }
.q-header { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.q-progress { font-weight: 800; color: var(--ink-dim); font-variant-numeric: tabular-nums; }
.q-category {
  background: var(--bg-raise); border-radius: 999px; padding: 5px 14px;
  font-weight: 700; font-size: 0.85rem; box-shadow: inset 0 0 0 2px var(--line);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 55%;
}
.q-timer-num {
  font-weight: 900; font-size: 1.3rem; color: var(--gold); min-width: 2ch; text-align: right;
  font-variant-numeric: tabular-nums;
}
.q-timer-num.urgent { color: var(--bad); animation: pulse-dim 0.5s ease-in-out infinite; }
.timer-track { height: 10px; background: var(--bg-sink); border-radius: 999px; overflow: hidden; }
.timer-bar {
  height: 100%; width: 100%; border-radius: 999px; background: var(--gold);
  transform-origin: left; transform: scaleX(1);
}
.timer-bar.run { transition: transform linear; transform: scaleX(0); }
.timer-bar.urgent { background: var(--bad); }

.q-text {
  font-size: clamp(1.3rem, 5.4vw, 1.8rem); font-weight: 800; line-height: 1.25;
  text-wrap: balance; min-height: 2.5em; display: flex; align-items: center;
  animation: screen-in 0.4s var(--ease);
}

.answers { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
@media (max-width: 480px) { .answers { grid-template-columns: 1fr; } }
/* The four answer identities now live in answers.css, shared with the hub. */
.answer .a-count {
  font-weight: 800; font-size: 0.85rem; background: oklch(0 0 0 / 0.25);
  border-radius: 999px; padding: 3px 10px; flex-shrink: 0;
}

.q-footer { display: flex; justify-content: space-between; align-items: center; min-height: 1.6em; }
.answer-status { font-weight: 800; color: var(--gold); }
.answer-count { color: var(--ink-dim); font-weight: 600; font-variant-numeric: tabular-nums; }

/* reveal panel */
.reveal-panel {
  background: var(--bg-raise); border-radius: var(--r-panel); padding: 18px;
  box-shadow: inset 0 0 0 2px var(--line);
  display: flex; flex-direction: column; gap: 12px;
  animation: panel-up 0.45s var(--ease);
}
@keyframes panel-up { from { opacity: 0; transform: translateY(24px); } }
.reveal-verdict { font-weight: 900; font-size: 1.25rem; }
.reveal-verdict.good { color: var(--good); }
.reveal-verdict.bad { color: var(--bad); }
.mini-board { list-style: none; display: flex; flex-direction: column; gap: 6px; }
.mini-board li {
  display: flex; align-items: center; gap: 10px; font-weight: 600;
  padding: 6px 10px; border-radius: 10px; background: var(--bg-sink);
}
.mini-board .rank { font-weight: 800; color: var(--ink-dim); width: 1.4em; font-variant-numeric: tabular-nums; }
.mini-board .chip { flex: 1; min-width: 0; }
.mini-board .mb-score { font-weight: 800; font-variant-numeric: tabular-nums; }
.mini-board .mb-gain { color: var(--good); font-weight: 800; font-size: 0.85rem; }
.mini-board li.is-me { background: oklch(0.33 0.05 85); }
.btn-ready { width: 100%; padding: 13px; font-size: 1rem; margin-bottom: 8px; }
.btn-ready[disabled] { opacity: 1; background: transparent; color: var(--ink-dim); box-shadow: inset 0 0 0 2px var(--line); cursor: default; }
.reveal-next { color: var(--ink-dim); font-weight: 600; font-size: 0.9rem; text-align: center; }

/* floating score */
.score-float {
  position: fixed; left: 50%; top: 38%; transform: translateX(-50%);
  font-size: 2.6rem; font-weight: 900; color: var(--good); opacity: 0;
  pointer-events: none; text-shadow: 0 3px 0 oklch(0.3 0.1 150 / 0.5);
}
.score-float.go { animation: float-up 1.4s var(--ease); }
@keyframes float-up {
  0% { opacity: 0; transform: translate(-50%, 20px) scale(0.6); }
  25% { opacity: 1; transform: translate(-50%, 0) scale(1.1); }
  100% { opacity: 0; transform: translate(-50%, -70px) scale(1); }
}

/* ─────────── podium ─────────── */
.podium-wrap { width: min(500px, 100%); display: flex; flex-direction: column; gap: 24px; text-align: center; }
.podium-title { font-size: 1.6rem; font-weight: 900; }
.podium { display: flex; align-items: flex-end; justify-content: center; gap: 10px; min-height: 240px; }
.podium-spot { display: flex; flex-direction: column; align-items: center; gap: 8px; flex: 1; max-width: 130px; }
.podium-spot .chip-tile { animation: badge-bob 2.4s var(--ease) infinite; }
.podium-spot .chip { width: 100%; }
.podium-score { color: var(--ink-dim); font-weight: 700; font-variant-numeric: tabular-nums; font-size: 0.9rem; }
.podium-block {
  width: 100%; border-radius: 14px 14px 0 0; display: grid; place-items: center;
  font-weight: 900; font-size: 1.8rem; transform-origin: bottom;
  animation: block-rise 0.7s var(--ease) backwards;
}
@keyframes block-rise { from { transform: scaleY(0); } }
.podium-spot.p1 .podium-block { height: 130px; background: var(--gold); color: var(--gold-ink); box-shadow: 0 4px 0 var(--gold-edge); animation-delay: 0.5s; }
.podium-spot.p2 .podium-block { height: 92px; background: var(--teal); color: oklch(0.16 0.04 200); box-shadow: 0 4px 0 var(--teal-edge); animation-delay: 0.25s; }
.podium-spot.p3 .podium-block { height: 64px; background: var(--coral); color: oklch(0.98 0.01 85); box-shadow: 0 4px 0 var(--coral-edge); animation-delay: 0.1s; }
.final-board { list-style: none; display: flex; flex-direction: column; gap: 6px; text-align: left; }
.final-board li {
  display: flex; align-items: center; gap: 10px; font-weight: 600;
  background: var(--bg-raise); border-radius: 12px; padding: 10px 14px;
  box-shadow: inset 0 0 0 2px var(--line);
}
.final-board .rank { font-weight: 800; color: var(--ink-dim); width: 1.6em; font-variant-numeric: tabular-nums; }
.final-board .chip { flex: 1; min-width: 0; }
.final-board .mb-score { font-weight: 800; font-variant-numeric: tabular-nums; }
.final-board li.is-me { box-shadow: inset 0 0 0 2px var(--gold); }
/* ─────────── spectator (Spectator board) ─────────── */
.spect-wrap {
  min-height: 100dvh; max-width: 430px; margin: 0 auto; padding: 20px;
  box-sizing: border-box; display: flex; flex-direction: column; gap: 16px; justify-content: center;
}
.spect-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.spect-room {
  background: var(--bg-raise); border-radius: 999px; padding: 5px 14px;
  font-weight: 800; font-size: 13px; box-shadow: inset 0 0 0 2px var(--line);
}
.spect-room b { color: var(--gold); letter-spacing: 0.14em; }
.spect-me {
  display: flex; align-items: center; gap: 8px;
  background: oklch(0.33 0.05 85); border-radius: 999px; padding: 6px 14px 6px 9px;
  font-weight: 700; font-size: 14px; box-shadow: inset 0 0 0 2px var(--gold);
}
.spect-me #spect-me-avatar { font-size: 17px; }
.spect-head { text-align: center; display: flex; flex-direction: column; gap: 8px; padding: 8px 0 4px; }
.spect-head h2 { font-weight: 900; font-size: 40px; line-height: 0.95; letter-spacing: -0.03em; text-transform: uppercase; }
.spect-head p { font-weight: 600; font-size: 15px; color: var(--ink-dim); text-wrap: balance; }
.spect-card {
  background: var(--bg-raise); border-radius: var(--r-panel); padding: 18px;
  box-shadow: inset 0 0 0 2px var(--line);
  display: flex; flex-direction: column; gap: 12px;
}
.spect-live-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.spect-live {
  display: flex; align-items: center; gap: 7px;
  font-weight: 800; font-size: 13px; color: var(--bad);
  text-transform: uppercase; letter-spacing: 0.06em;
}
.spect-live i { width: 8px; height: 8px; border-radius: 999px; background: var(--bad); animation: spect-pulse 1.6s var(--ease) infinite; }
@keyframes spect-pulse { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(0.7); opacity: 0.55; } }
.spect-meta { font-weight: 800; font-size: 14px; color: var(--ink-dim); font-variant-numeric: tabular-nums; }
.spect-track { height: 8px; background: var(--bg-sink); border-radius: 999px; overflow: hidden; }
.spect-bar { height: 100%; border-radius: 999px; background: var(--gold); transform-origin: left; transition: transform 0.25s linear; }
.spect-question { font-size: 18px; font-weight: 800; line-height: 1.3; text-wrap: balance; }
.spect-shapes { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
.spect-shapes span { border-radius: 12px; height: 40px; display: grid; place-items: center; font-size: 13px; }
.ss-coral { background: var(--coral); box-shadow: 0 3px 0 var(--coral-edge); color: oklch(0.98 0.01 85); }
.ss-amber { background: var(--amber); box-shadow: 0 3px 0 var(--amber-edge); color: oklch(0.22 0.05 75); }
.ss-teal  { background: var(--teal);  box-shadow: 0 3px 0 var(--teal-edge);  color: oklch(0.16 0.04 200); }
.ss-blue  { background: var(--blue);  box-shadow: 0 3px 0 var(--blue-edge);  color: oklch(0.98 0.01 85); }
.spect-note { font-weight: 600; font-size: 13px; color: var(--ink-dim); text-align: center; }
.spect-label { font-weight: 800; font-size: 13px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-dim); }
.spect-list { display: flex; flex-direction: column; gap: 6px; }
.spect-row {
  display: flex; align-items: center; gap: 10px;
  font-weight: 600; font-size: 14px; padding: 6px 10px; border-radius: 10px;
  background: var(--bg-sink);
}
.spect-row.is-me { background: oklch(0.33 0.05 85); box-shadow: inset 0 0 0 2px var(--gold); }
.sr-rank { font-weight: 800; color: var(--ink-dim); width: 18px; font-variant-numeric: tabular-nums; }
.spect-row .chip { flex: 1; min-width: 0; }
.sr-score { font-weight: 800; font-variant-numeric: tabular-nums; }
.spect-banner {
  border-radius: var(--r-ctl); background: var(--bg-raise);
  box-shadow: inset 0 0 0 2px var(--line);
  color: var(--gold); font-weight: 800; font-size: 17px; padding: 16px; text-align: center;
}
.spect-leave {
  border: 0; background: transparent; cursor: pointer; font: inherit;
  font-weight: 600; font-size: 14px; color: var(--ink-dim); padding-bottom: 4px;
  -webkit-tap-highlight-color: transparent;
}
.mb-late { font-weight: 600; font-size: 0.75em; color: var(--ink-dim); }

/* ─────────── kick (host removes a player) ─────────── */
.chip-kick {
  width: 22px; height: 22px; border-radius: 8px; margin-left: 2px;
  border: 0; padding: 0; cursor: pointer; font: inherit;
  font-size: 11px; font-weight: 800; line-height: 1;
  background: transparent; color: var(--ink-dim);
  box-shadow: inset 0 0 0 2px var(--line);
  display: grid; place-items: center;
  -webkit-tap-highlight-color: transparent;
}
.roster-item.kick-armed .chip { box-shadow: inset 0 0 0 2px var(--bad); }
.roster-item.kick-armed { animation: kick-shake 0.3s var(--ease); }
.roster-item.kick-armed .chip-kick {
  background: var(--bad); color: oklch(0.98 0.01 85);
  box-shadow: 0 2px 0 oklch(0.46 0.18 25);
}
@keyframes kick-shake {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-3px); }
  75% { transform: translateX(3px); }
}

/* ─────────── reactions ─────────── */
.react-bar { display: flex; justify-content: center; gap: 8px; }
.react-btn {
  width: 42px; height: 42px; border-radius: 12px;
  border: 0; padding: 0; cursor: pointer; font-size: 20px;
  background: transparent; box-shadow: inset 0 0 0 2px var(--line);
  display: grid; place-items: center;
  transition: transform 0.15s var(--ease);
  touch-action: manipulation; -webkit-tap-highlight-color: transparent;
}
.react-btn:active { transform: scale(0.88); }
#react-layer { position: fixed; inset: 0; pointer-events: none; z-index: 70; overflow: hidden; }
.react-float {
  position: absolute; bottom: 12vh;
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  animation: react-rise 2s var(--ease) forwards;
}
.react-float b { font-size: 34px; }
.react-float i { font-size: 15px; font-style: normal; opacity: 0.85; }
@keyframes react-rise {
  0% { transform: translateY(0) scale(0.6); opacity: 0; }
  12% { opacity: 1; transform: translateY(-4vh) scale(1.05); }
  100% { transform: translateY(-46vh) scale(1); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .react-float { animation-duration: 0.6s; }
}

/* ─────────── podium awards ─────────── */
.awards { display: flex; flex-direction: column; gap: 8px; text-align: left; }
.award-row {
  display: flex; align-items: center; gap: 12px;
  background: var(--bg-raise); border-radius: var(--r-ctl); padding: 12px 14px;
  box-shadow: inset 0 0 0 2px var(--line);
}
.award-emoji { font-size: 22px; flex: none; }
.award-main { display: flex; flex-direction: column; gap: 1px; flex: 1; min-width: 0; }
.award-main b { font-weight: 800; font-size: 0.95rem; }
.award-main small { font-weight: 600; font-size: 0.75rem; color: var(--ink-dim); }
/* Capped, because the award's own name is the point of the row. Both sides can
   shrink, and without this a 24 character nickname takes most of the width and
   "Fastest fingers" is what gives way. */
.award-who { display: flex; align-items: center; min-width: 0; max-width: 45%; }

/* ─────────── sound toggle ─────────── */
#sound-toggle {
  position: fixed; right: 16px; bottom: 16px; z-index: 65;
  width: 40px; height: 40px; border-radius: 12px;
  border: 0; padding: 0; cursor: pointer; font-size: 17px;
  background: var(--bg-raise); box-shadow: inset 0 0 0 2px var(--line);
  display: grid; place-items: center;
  -webkit-tap-highlight-color: transparent;
}
#sound-toggle.is-muted { opacity: 0.6; }
#sound-toggle:active { transform: scale(0.92); }

/* ─────────── next round vote (Podium board) ─────────── */
.vote-panel {
  background: var(--bg-raise); border-radius: var(--r-panel);
  box-shadow: inset 0 0 0 2px var(--line);
  padding: 18px; display: flex; flex-direction: column; gap: 12px; text-align: left;
}
.vote-head { display: flex; align-items: center; justify-content: space-between; }
.vote-kicker { font-weight: 800; font-size: 0.8rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-dim); }
.vote-tally { font-weight: 800; font-size: 0.8rem; color: var(--gold); font-variant-numeric: tabular-nums; }
.vote-multi {
  margin-top: -6px; font-weight: 600; font-size: 0.8rem; color: var(--ink-dim);
}
.vote-options { display: flex; flex-direction: column; gap: 12px; }
.vote-row {
  display: flex; align-items: center; gap: 12px; width: 100%;
  border-radius: var(--r-ctl); background: var(--bg-sink); padding: 12px 14px;
  box-shadow: inset 0 0 0 2px var(--line);
  border: 0; font: inherit; color: var(--ink); text-align: left; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.vote-row:active { transform: scale(0.99); }
.vote-row.is-leader { box-shadow: inset 0 0 0 2px var(--gold); }
/* A row you have ticked. The ballot builds a mix now, so more than one row can
   be yours at once and the state has to be visible on each of them rather than
   implied by which one is gold. */
.vote-row.is-mine { background: var(--bg-raise); }
.vote-row.is-mine .vote-dot { box-shadow: 0 0 0 3px var(--ink); }
.vote-dot { width: 14px; height: 14px; border-radius: 5px; flex: none; }
.vd-coral { background: var(--coral); box-shadow: 0 2px 0 var(--coral-edge); }
.vd-amber { background: var(--amber); box-shadow: 0 2px 0 var(--amber-edge); }
.vd-teal  { background: var(--teal);  box-shadow: 0 2px 0 var(--teal-edge); }
.vd-blue  { background: var(--blue);  box-shadow: 0 2px 0 var(--blue-edge); }
.vote-row-main { display: flex; flex-direction: column; gap: 1px; flex: 1; min-width: 0; }
.vote-row-name { font-weight: 800; font-size: 0.95rem; }
.vote-row-sub { font-weight: 600; font-size: 0.75rem; color: var(--ink-dim); }
.vote-row-sub.is-gold { color: var(--gold); }
.vote-voters { display: flex; }
.vote-voters span { font-size: 1rem; }
.vote-voters span + span { margin-left: -5px; }
.vote-none { font-weight: 600; font-size: 0.75rem; color: oklch(0.5 0.02 60); }
.vote-field {
  display: flex; align-items: center; gap: 10px;
  background: var(--bg-sink); border: 2px solid var(--line); border-radius: var(--r-ctl);
  padding: 12px 14px; color: var(--ink-dim);
}
.vote-field:focus-within { border-color: var(--gold); }
.vote-field input {
  flex: 1; min-width: 0; font: inherit; font-weight: 600; font-size: 0.9rem;
  background: transparent; border: 0; outline: none; color: var(--ink);
}
.vote-field input::placeholder { color: oklch(0.5 0.02 60); }
.vote-results { display: flex; flex-direction: column; gap: 6px; }
.vote-result {
  display: flex; align-items: center; gap: 10px; width: 100%;
  background: var(--bg-sink); border-radius: 12px; padding: 10px 12px;
  box-shadow: inset 0 0 0 2px var(--line);
  border: 0; font: inherit; font-weight: 700; font-size: 0.9rem; color: var(--ink);
  text-align: left; cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.vote-result:active { transform: scale(0.99); }
.vote-result small { margin-left: auto; font-weight: 600; font-size: 0.75rem; color: var(--ink-dim); }
.vote-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.vote-chip {
  border-radius: 999px; padding: 8px 14px;
  font: inherit; font-weight: 700; font-size: 0.8rem;
  box-shadow: inset 0 0 0 2px var(--line); color: var(--ink-dim);
  background: transparent; border: 0; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.vote-chip:active { transform: scale(0.96); }
.vote-caption { font-weight: 600; font-size: 0.75rem; color: var(--ink-dim); text-align: center; }

/* lobby topic mix: the ballot's field and result rows, with removable chips */
.topic-mix { display: flex; flex-direction: column; gap: 10px; }
.topic-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.topic-chip {
  display: inline-flex; align-items: center; gap: 8px;
  border-radius: 999px; padding: 8px 10px 8px 14px;
  font-weight: 700; font-size: 0.8rem;
  box-shadow: inset 0 0 0 2px var(--line); color: var(--ink);
}
.topic-chip.is-solo { padding-right: 14px; }
.topic-x {
  font: inherit; font-size: 0.7rem; line-height: 1; color: var(--ink-dim);
  background: transparent; border: 0; border-radius: 999px; padding: 4px;
  cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.topic-x:hover { color: var(--bad); }
.topic-x:active { transform: scale(0.9); }

.podium-actions { display: flex; flex-direction: column; gap: 12px; align-items: center; }
.podium-actions .btn-ghost { width: auto; }

/* confetti */
.confetti { position: fixed; inset: 0; pointer-events: none; overflow: hidden; }
.confetti i {
  position: absolute; top: -4vh; width: 10px; height: 16px; border-radius: 3px;
  animation: confetti-fall linear infinite;
}
@keyframes confetti-fall {
  to { transform: translateY(110vh) rotate(720deg); }
}

/* ─────────── toast & loading ─────────── */
.toast {
  position: fixed; bottom: max(24px, env(safe-area-inset-bottom)); left: 50%; transform: translateX(-50%);
  background: var(--ink); color: var(--bg); font-weight: 700;
  border-radius: 999px; padding: 10px 20px; z-index: 50;
  animation: toast-in 0.35s var(--ease); max-width: 90vw; text-align: center;
}
@keyframes toast-in { from { opacity: 0; transform: translate(-50%, 16px); } }
.loading-overlay {
  position: fixed; inset: 0; background: oklch(0.19 0.025 40 / 0.88); z-index: 40;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px;
  font-weight: 700; font-size: 1.1rem;
}
.loading-dice { font-size: 3.4rem; animation: dice-spin 1.1s var(--ease) infinite; }
@keyframes dice-spin { 50% { transform: rotate(180deg) scale(1.15); } 100% { transform: rotate(360deg); } }

/* ─────────── reduced motion ─────────── */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; }
  .timer-bar.run { transition: transform linear !important; transition-duration: inherit !important; }
}

/* ─────────── accounts ─────────── */
/* The top right corner holds Sign in and, to its left, the language switch.
   A flex row rather than two absolutely positioned links, because "Sign in"
   and "Σύνδεση" are different widths and anything anchored to the left of a
   variable width element has to be measured to be placed. */
.home-corner {
  position: absolute; top: max(20px, env(safe-area-inset-top)); right: 20px;
  display: flex; align-items: center; gap: 14px;
}
.home-signin {
  color: var(--ink-dim); font-weight: 700; font-size: 0.9rem; text-decoration: none;
}
.home-signin:active { opacity: 0.7; }
/* The switch is injected into the corner by localizeStatic, so it arrives
   wearing the header's classes and needs its own placement here.
   Only the home screen carries it: changing language reloads the page, and a
   reload during a game drops you out of the room, so offering it in the lobby
   or mid question would be offering a way to lose your seat. */
#screen-home .lang-switch {
  color: var(--ink-dim); font-weight: 700; font-size: 0.9rem; text-decoration: none;
  padding: 2px 8px; border-radius: 8px; background: var(--bg-raise);
  -webkit-tap-highlight-color: transparent;
}
#screen-home .lang-switch:active { opacity: 0.7; }
/* Mirrors Sign in on the opposite corner: the way back out to the site. */
.home-back {
  position: absolute; top: max(20px, env(safe-area-inset-top)); left: 20px;
  color: var(--ink-dim); font-weight: 700; font-size: 0.9rem; text-decoration: none;
  -webkit-tap-highlight-color: transparent;
}
.home-back:active { opacity: 0.7; }
/* Leave room, per the Lobby boards. */
.lobby-leave {
  border: 0; background: transparent; cursor: pointer; font: inherit;
  font-weight: 600; font-size: 0.875rem; color: var(--ink-dim);
  align-self: center; padding: 4px 12px;
  -webkit-tap-highlight-color: transparent;
}
.lobby-leave:active { opacity: 0.7; }
#screen-home { position: relative; }
.personal-strip {
  background: var(--bg-raise); border-radius: var(--r-panel); padding: 16px 20px;
  box-shadow: inset 0 0 0 2px var(--gold);
  display: flex; justify-content: space-between; gap: 8px;
}
.personal-strip .ps-item { display: flex; flex-direction: column; gap: 2px; }
.personal-strip .ps-big { font-weight: 900; font-size: 1.3rem; font-variant-numeric: tabular-nums; }
.personal-strip .ps-sub { font-weight: 600; font-size: 0.72rem; color: var(--ink-dim); }
/* Wraps rather than breaking. The button says "Save my stats" in English and
   "Αποθήκευσε τα στατιστικά μου" in Greek, which is nowrap and 260px wide, so
   on a 320px phone it ran a hundred pixels off the side of the podium. The
   basis lets the copy hold a sensible column and the button drop underneath it
   when there is no room, at any width, without a breakpoint to maintain. */
.save-cta {
  background: var(--bg-raise); border-radius: var(--r-panel); padding: 16px 20px;
  box-shadow: inset 0 0 0 2px var(--line);
  display: flex; align-items: center; gap: 14px; text-align: left; flex-wrap: wrap;
}
.save-cta-copy { display: flex; flex-direction: column; gap: 3px; flex: 1 1 150px; }
.save-cta-copy b { font-weight: 800; font-size: 1rem; }
.save-cta-copy span { font-weight: 500; font-size: 0.82rem; color: var(--ink-dim); }
.save-cta-btn { padding: 10px 16px; font-size: 0.9rem; border-radius: 12px; white-space: nowrap; flex: 1 1 auto; }
.saved-note { color: var(--good); font-weight: 700; font-size: 0.95rem; }
.save-modal {
  position: fixed; inset: 0; z-index: 60;
  background: oklch(0.19 0.025 40 / 0.72);
  display: flex; align-items: flex-end; justify-content: center;
}
.save-sheet {
  width: min(430px, 100%); background: var(--bg-raise);
  border-radius: var(--r-panel) var(--r-panel) 0 0; padding: 24px 20px max(24px, env(safe-area-inset-bottom));
  box-shadow: inset 0 0 0 2px var(--line);
  display: flex; flex-direction: column; gap: 14px; text-align: center;
  animation: panel-up 0.45s var(--ease);
}
.save-sheet-title { font-weight: 900; font-size: 1.5rem; text-transform: uppercase; letter-spacing: -0.02em; }
.save-sheet-sub { font-weight: 600; font-size: 0.9rem; color: var(--ink-dim); }
.save-sheet .field { text-align: left; }

.pack-line {
  font-weight: 700; font-size: 0.95rem; text-align: center;
  background: var(--bg-sink); border-radius: 12px; padding: 12px 14px;
  box-shadow: inset 0 0 0 2px var(--teal);
}
.host-settings-controls { display: flex; flex-direction: column; gap: 16px; }
.host-settings-controls[hidden] { display: none; }

/* ——— final question wager ———
   design/canvas/Wager.dc.html. Four states on one screen: above the floor,
   below it, locked, and the last few seconds with nothing picked.

   The clock is the whole reason this screen reads differently from the question
   screen. It is dim ink rather than gold and a quarter of the width, so it says
   deadline rather than race, and until now it was not on screen at all: the
   server has always sent it and the client threw it away. */
.wager-wrap {
  display: flex; flex-direction: column; gap: 14px; align-items: stretch;
  width: 100%; max-width: 460px; min-width: 0; margin: 0 auto;
}
#screen-wager.active { justify-content: flex-start; }
.wager-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.wager-before { font-weight: 800; font-size: 0.875rem; color: var(--ink-dim); }
.wager-clock {
  display: flex; align-items: center; gap: 8px; font-weight: 800; font-size: 0.875rem;
  color: var(--ink-dim); font-variant-numeric: tabular-nums;
}
.wager-clock-track {
  width: 64px; height: 6px; border-radius: 999px; background: var(--bg-sink);
  overflow: hidden; display: block; flex: none;
}
.wager-clock-track i { display: block; height: 100%; border-radius: 999px; background: var(--ink-dim); }
/* The last few seconds, and only for somebody who has not picked. Error red on
   a clock is the one place this screen raises its voice. */
.wager-clock.is-urgent { color: var(--bad); font-size: 1.25rem; font-weight: 900; animation: wager-pulse 1s var(--ease) infinite; }
.wager-clock.is-urgent .wager-clock-track i { background: var(--bad); }

.wager-head { display: flex; flex-direction: column; gap: 6px; text-align: center; padding-top: 10px; }
.wager-kicker {
  font-weight: 800; font-size: 0.75rem; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--gold);
}
.wager-title {
  font-weight: 900; font-size: clamp(1.75rem, 11vw, 2.75rem); text-transform: uppercase;
  letter-spacing: -0.03em; line-height: 0.95; margin: 0;
}
.wager-title.is-locked { color: var(--good); }
.wager-sub {
  font-weight: 600; font-size: 0.875rem; line-height: 1.45; color: var(--ink-dim);
  text-wrap: balance; margin: 0;
}
.wager-sub.is-warning { color: var(--bad); font-weight: 700; }

.wager-tiers { display: flex; flex-direction: column; gap: 10px; }
.wager-tiers.is-locked { opacity: 0.4; pointer-events: none; }
.wager-tier {
  border: 0; font: inherit; color: inherit; text-align: left; cursor: pointer;
  border-radius: var(--r-ctl); background: var(--bg-raise);
  box-shadow: inset 0 0 0 2px var(--line); padding: 14px 16px;
  display: flex; align-items: center; gap: 12px;
  -webkit-tap-highlight-color: transparent;
}
.wager-tier:active { transform: scale(0.98); }
/* The picked tier is ringed gold and its numbers go gold with it. A fill would
   read as a pressed button rather than as a choice standing. */
.wager-tier.is-picked { box-shadow: inset 0 0 0 2px var(--gold); }
.wager-tier.is-picked .wager-tier-name, .wager-tier.is-picked .wager-tier-points { color: var(--gold); }
.wager-tier-body { display: flex; flex-direction: column; gap: 1px; flex: 1; min-width: 0; }
.wager-tier-name { font-weight: 900; font-size: 1.125rem; text-transform: uppercase; }
.wager-tier-note { font-weight: 600; font-size: 0.75rem; color: var(--ink-dim); line-height: 1.3; }
.wager-tier-points { font-weight: 800; font-size: 1rem; font-variant-numeric: tabular-nums; flex: none; }

.wager-panel {
  background: var(--bg-sink); border-radius: var(--r-panel); padding: 16px;
  box-shadow: inset 0 0 0 2px var(--line);
  display: flex; flex-direction: column; align-items: center; gap: 2px;
}
.wager-panel.is-locked { box-shadow: inset 0 0 0 2px var(--good); }
.wager-panel.is-warning { box-shadow: inset 0 0 0 2px var(--bad); }
.wager-panel-label {
  font-weight: 700; font-size: 0.6875rem; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--ink-dim);
}
.wager-value {
  font-weight: 900; font-size: 3.25rem; line-height: 1; color: var(--gold);
  font-variant-numeric: tabular-nums;
}
/* Nothing staked is not a gold number. */
.wager-panel.is-warning .wager-value, .wager-value.is-zero { color: var(--ink-dim); }

/* Locked is not a disabled primary button, it is its own state: the tick and
   the green say the decision stands rather than that the control is dead. */
#btn-wager.is-locked {
  background: transparent; box-shadow: inset 0 0 0 2px var(--good); color: var(--good);
  display: flex; align-items: center; justify-content: center; gap: 10px;
}
.wager-out {
  border: 0; background: transparent; font: inherit; cursor: pointer;
  font-weight: 700; font-size: 0.875rem; color: var(--ink-dim); padding: 4px;
  -webkit-tap-highlight-color: transparent;
}
.wager-out:active { opacity: 0.7; }
.wager-out[hidden] { display: none; }

.wager-room { margin-top: auto; display: flex; flex-direction: column; gap: 8px; align-items: center; }
.wager-tiles { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; }
.wager-tile {
  width: 34px; height: 34px; border-radius: 10px; background: var(--bg-raise);
  display: grid; place-items: center; font-size: 1.125rem;
  box-shadow: inset 0 0 0 2px var(--line); opacity: 0.45;
}
.wager-tile.is-locked { box-shadow: inset 0 0 0 2px var(--good); opacity: 1; }
/* The one the room is waiting on, so it is a person rather than a number. */
.wager-tile.is-waiting { animation: wager-pulse 1.4s var(--ease) infinite; }
.wager-status {
  font-weight: 700; font-size: 0.75rem; color: var(--ink-dim); text-align: center; min-height: 1.2em;
}
@keyframes wager-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.55; } }
@media (prefers-reduced-motion: reduce) {
  /* The colours still change, only the pulse stops: the warning must survive
     motion being turned down, because it is information rather than flourish. */
  .wager-clock.is-urgent, .wager-tile.is-waiting { animation: none; }
}

/* a lost bet is the one number that should not be gold */
.mb-gain.is-loss { color: var(--bad); }
.score-float.is-loss { color: var(--bad); text-shadow: 0 3px 0 oklch(0.3 0.1 25 / 0.5); }

/* ═══════════ teams: the fight ═══════════
   design/canvas/TeamsFight.dc.html.

   Sides carry no hue. Left is cream and right is gold, both already in the
   palette, both carrying no answer information. That is the whole answer to
   the problem that ▲◆●■ have already spent the four colours a player reads
   first: a fifth and sixth hue would land in the same channel as the answers,
   so a side is a position instead, and the bar makes left and right a spatial
   fact rather than something to memorise. */

/* ─── the VS screen ─── */
/* .screen.active already centres this and supplies the padding, so the wrap
   only carries the stack. width:100% matters: .screen centres its child, which
   means the child sizes to its own content, and a long side name was making
   this box wider than the phone rather than being made smaller by it. */
.vs-wrap {
  width: 100%; min-width: 0;
  display: flex; flex-direction: column; gap: 22px;
}
.vs-meta {
  align-self: center; background: var(--bg-raise); border-radius: 999px;
  padding: 6px 16px; font-weight: 700; font-size: 0.875rem;
  box-shadow: inset 0 0 0 2px var(--line);
}
/* min-width: 0 because a flex item defaults to min-width: auto, which lets it
   grow past its container to fit a long word. That made a 15 character Greek
   name run off both edges of the screen while every overflow check reported
   the name fitted, because it had simply taken the extra width. */
.vs-side { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.vs-b { align-items: flex-end; }
/* 72px is the design's size and it is what a short English name gets.
   "Octopuses" is nine characters and "Καμηλοπαρδάλεις" is fifteen, so a name
   shrinks to fit rather than wrapping: breaking OCTOPUSES across two lines
   reads as a bug and a smaller name reads as a long name. This is the ceiling,
   and fitName measures the rendered text and steps down from here, because a
   constant for the width of a character is a guess that Greek capitals break. */
.vs-name {
  /* Full width even on the right hand side, which is otherwise laid out
     flex-end and would shrink this to fit the text. fitName compares the text
     against this box, so a box that grows with the text can never overflow and
     the name would never be shrunk. */
  width: 100%;
  font-weight: 900; font-size: clamp(1.75rem, 19vw, 4.5rem);
  text-transform: uppercase; letter-spacing: -0.04em; line-height: 0.9;
  white-space: nowrap;
}
.vs-b .vs-name { color: var(--gold); text-align: right; }
.vs-crew { display: flex; gap: 6px; flex-wrap: wrap; }
.vs-face {
  width: 40px; height: 40px; border-radius: 12px; background: var(--bg-raise);
  display: grid; place-items: center; font-size: 1.3rem;
  box-shadow: inset 0 0 0 2px var(--ink);
}
.vs-b .vs-face { box-shadow: inset 0 0 0 2px var(--gold); }
.vs-clash { display: flex; align-items: center; gap: 14px; }
.vs-rule { flex: 1; height: 14px; border-radius: 999px; background: var(--ink); }
.vs-rule-b { background: var(--gold); }
.vs-word {
  font-weight: 900; font-size: 5.5rem; line-height: 0.8; color: var(--gold);
  letter-spacing: -0.06em;
  animation: vs-slam 0.6s var(--ease) 0.5s both;
}
.vs-call {
  font-weight: 800; font-size: 1.25rem; text-transform: uppercase;
  letter-spacing: -0.02em; padding-top: 10px; text-align: center;
}
.vs-a { animation: vs-in-left 0.7s var(--ease) both; }
.vs-b { animation: vs-in-right 0.7s var(--ease) both; }
@keyframes vs-slam { from { transform: scale(2.2); opacity: 0; } to { transform: none; opacity: 1; } }
@keyframes vs-in-left { from { transform: translateX(-60px); opacity: 0; } to { transform: none; opacity: 1; } }
@keyframes vs-in-right { from { transform: translateX(60px); opacity: 0; } to { transform: none; opacity: 1; } }

/* ─── the strip, on the question screen ─── */
.fight { display: flex; flex-direction: column; gap: 5px; margin-bottom: 10px; }
.fight-line {
  display: flex; align-items: center; justify-content: space-between;
  font-weight: 800; font-size: 0.6875rem; text-transform: uppercase; letter-spacing: 0.06em;
  gap: 8px;
}
.fight-team { display: flex; align-items: baseline; gap: 5px; min-width: 0; flex: 0 1 auto; }
.fight-team-a { color: var(--ink); }
.fight-team-b { color: var(--gold); }
/* Two long Greek names and a lead line do not fit 280px. At 320, with both
   sides on twelve characters, "ΚΟΥΚΟΥΒΑΓΙΕΣ" ran under the status and
   "ΤΥΡΑΝΝΟΣΑΥΡΟ" ran off the screen. The names are the part that gives, and
   they give the way TeamsGreek asks for, cut with no ellipsis, because a
   truncated name still reads as a name and a lead of +2.410 read wrong is
   worse. The lock count sits inboard of the name, so it is never the thing
   that gets cut. */
.fight-side-name { overflow: hidden; white-space: nowrap; min-width: 0; }
.fight-status { flex: 0 0 auto; }
/* A count of who has committed, never who is right. The lock count is the only
   thing on this strip that moves during a question, and a number cannot leak
   an answer the way a verdict would. */
.fight-locks {
  color: var(--ink-dim); font-weight: 700; text-transform: none; letter-spacing: 0;
  font-variant-numeric: tabular-nums;
}
.fight-status {
  color: var(--ink-dim); font-weight: 700; text-transform: none; letter-spacing: 0;
  white-space: nowrap;
}
.fight-status.is-lead { font-weight: 800; color: var(--gold); }
.fight-status.is-lead-a { color: var(--ink); }
.fight-status.is-ko { color: var(--bad); font-weight: 900; animation: fight-pulse 1.2s var(--ease) infinite; }
.fight-bar {
  height: 10px; border-radius: 999px; background: var(--bg-sink);
  box-shadow: inset 0 0 0 2px var(--line); position: relative; overflow: hidden;
}
/* Error red on a component that is not an error. Reused deliberately for the
   one moment the fight is dangerous, and both sides see it: one reads danger,
   the other reads blood. */
.fight-bar.is-ko { box-shadow: inset 0 0 0 2px var(--bad); }
.fight-fill { position: absolute; top: 0; bottom: 0; transition: width 0.6s var(--ease); }
.fight-fill-a { left: 0; background: var(--ink); }
.fight-fill-b { right: 0; background: var(--gold); }
.fight-mid {
  position: absolute; left: 50%; top: -2px; bottom: -2px; width: 3px;
  margin-left: -1.5px; background: var(--bg);
}
@keyframes fight-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.55; } }
@media (prefers-reduced-motion: reduce) {
  .vs-word, .vs-a, .vs-b, .fight-status.is-ko { animation: none; }
  .fight-fill { transition: none; }
}

/* ═══════════ teams: picking the sides ═══════════
   design/canvas/TeamsLobby.dc.html. Same rule as the fight: a side is cream on
   the left and gold on the right, never a new hue, because ▲◆●■ own the
   colours a player reads first. */

/* The mode cards moved into the rebuilt lobby, beside the game card, and
   shrank from two 150px cards to two rows. Their rules live with the lobby
   now: see "the mode cards, now a pair of small rows". */

/* ─── the team lobby ─── */
.teams-wrap { width: 100%; max-width: 460px; min-width: 0; display: flex; flex-direction: column; gap: 16px; }
.teams-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.teams-back {
  border: 0; background: transparent; font: inherit; cursor: pointer;
  font-weight: 700; font-size: 0.875rem; color: var(--ink-dim); padding: 4px 0;
  -webkit-tap-highlight-color: transparent;
}
.teams-room {
  background: var(--bg-raise); border-radius: 999px; padding: 5px 14px;
  font-weight: 800; font-size: 0.8125rem; box-shadow: inset 0 0 0 2px var(--line);
}
/* The room code is still a pill of its own. The player beside it is a chip. */
.teams-me { display: flex; align-items: center; min-width: 0; }
.teams-room b { color: var(--gold); letter-spacing: 0.14em; }
.teams-title {
  font-weight: 900; font-size: 1.875rem; text-transform: uppercase;
  letter-spacing: -0.03em; line-height: 1; margin: 0 0 14px;
}
.side-cards { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.side-card {
  background: var(--bg-raise); border-radius: var(--r-panel); padding: 14px;
  display: flex; flex-direction: column; gap: 10px; min-width: 0;
}
.side-a { box-shadow: inset 0 0 0 2px var(--ink); }
.side-b { box-shadow: inset 0 0 0 2px var(--gold); }
.side-head { display: flex; align-items: center; gap: 6px; color: var(--ink-dim); }
/* An input rather than a tap target that opens a dialog: renaming in place is
   one gesture, and the dashed underline is what says it can be typed in. */
.side-name {
  /* Shrinks on a narrow phone rather than clipping. At 320px a 17px name shows
     about eight characters, and ΑΛΕΠΟΥΔΕΣ is nine, so the Greek default name
     was being cut in half in the one place it can be edited. */
  flex: 1; min-width: 0; font: inherit; font-weight: 900;
  font-size: clamp(0.8125rem, 4.2vw, 1.0625rem);
  text-transform: uppercase; letter-spacing: -0.02em; color: var(--ink);
  background: transparent; border: 0; border-bottom: 2px dashed var(--line);
  padding: 0 0 2px; border-radius: 0;
}
.side-b .side-name { color: var(--gold); }
.side-name:focus { outline: none; border-bottom-color: var(--gold); }
.side-count {
  font-weight: 700; font-size: 0.6875rem; color: var(--ink-dim);
  text-transform: uppercase; letter-spacing: 0.06em;
}
.side-list { display: flex; flex-direction: column; gap: 6px; }
.side-chip {
  display: flex; align-items: center; gap: 6px; min-width: 0;
  background: var(--bg-sink); border: 0; border-radius: 999px; padding: 6px 10px 6px 7px;
  font: inherit; font-weight: 700; font-size: 0.8125rem; color: var(--ink);
  text-align: left; -webkit-tap-highlight-color: transparent;
}
.side-a .side-chip { box-shadow: inset 0 0 0 2px var(--ink); }
.side-b .side-chip { box-shadow: inset 0 0 0 2px var(--gold); }
button.side-chip { cursor: pointer; }
button.side-chip:active { transform: scale(0.97); }
.side-chip span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.teams-hint { font-weight: 600; font-size: 0.75rem; color: var(--ink-dim); text-align: center; margin: 0; }
.teams-actions { display: flex; gap: 10px; }
.teams-actions .btn { flex: 1; }
.teams-summary {
  background: var(--bg-raise); border-radius: var(--r-panel); padding: 14px 16px;
  box-shadow: inset 0 0 0 2px var(--line); display: flex; flex-direction: column; gap: 10px;
}
.teams-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; font-weight: 700; font-size: 0.875rem; }
.teams-row b { font-weight: 800; font-variant-numeric: tabular-nums; text-align: right; }

/* ─── the player's view ─── */
.mine { display: flex; flex-direction: column; gap: 6px; padding-top: 24px; text-align: center; }
.mine-where {
  font-weight: 700; font-size: 0.875rem; color: var(--ink-dim);
  text-transform: uppercase; letter-spacing: 0.08em;
}
.mine-name {
  width: 100%; font-weight: 900; font-size: 4rem; text-transform: uppercase;
  letter-spacing: -0.03em; line-height: 0.95; white-space: nowrap;
}
.mine-bar {
  height: 14px; border-radius: 999px; display: flex; overflow: hidden;
  box-shadow: inset 0 0 0 2px var(--line); margin: 16px 0;
}
.mine-bar i { flex: 1; }
#mine-bar-a { background: var(--ink); }
#mine-bar-b { background: var(--gold); }
/* The side you are not on is dimmed rather than removed, so the shape of the
   fight is the same object here as it is on the strip. */
.mine-bar i.is-theirs { opacity: 0.35; }
.mine-card {
  background: var(--bg-raise); border-radius: var(--r-panel); padding: 18px;
  display: flex; flex-direction: column; gap: 12px;
}
.mine-card.is-a { box-shadow: inset 0 0 0 2px var(--ink); }
.mine-card.is-b { box-shadow: inset 0 0 0 2px var(--gold); }
.mine-label {
  font-weight: 700; font-size: 0.75rem; color: var(--ink-dim);
  text-transform: uppercase; letter-spacing: 0.06em;
}
.mine-them { display: flex; flex-direction: column; gap: 8px; margin-top: 18px; text-align: center; }
.mine-mates { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; }
.mine-wait {
  margin-top: 18px; background: var(--bg-raise); border-radius: var(--r-panel); padding: 20px;
  box-shadow: inset 0 0 0 2px var(--line);
  display: flex; flex-direction: column; gap: 8px; align-items: center; text-align: center;
}
.mine-wait-line { display: flex; align-items: center; gap: 10px; font-weight: 800; font-size: 1rem; }
.mine-dot {
  width: 9px; height: 9px; border-radius: 999px; background: var(--gold); flex: none;
  animation: mine-pulse 1.6s var(--ease) infinite;
}
.mine-meta { font-weight: 600; font-size: 0.8125rem; color: var(--ink-dim); }
@keyframes mine-pulse { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(0.7); opacity: 0.55; } }
@media (prefers-reduced-motion: reduce) { .mine-dot { animation: none; } }

/* The board lays this screen out from the top, not centred: the back link and
   room code belong at the top edge the way they do on every other header. */
#screen-teams.active { justify-content: flex-start; }
/* "To the bell" is three words in a control sized for "Off", and it is
   "Μέχρι το κουδούνι" in Greek. Tighter type and no wrapping keeps the row one
   line high in both. */
.teams-summary .seg-btn { font-size: 0.75rem; padding: 6px 12px; white-space: nowrap; }

/* ═══════════ teams: how it ended ═══════════
   design/canvas/TeamsVictory.dc.html.

   The rule that shapes both endings: nothing on either screen says "lost". The
   losing side gets its own headline, its own MVP and the gap, and the winning
   side's name stays gold because gold is theirs tonight. */
#screen-victory.active { justify-content: flex-start; }
.vic-wrap {
  width: 100%; max-width: 460px; min-width: 0; position: relative;
  display: flex; flex-direction: column; gap: 18px; text-align: center;
}
.vic-bar {
  height: 14px; border-radius: 999px; background: var(--bg-sink);
  box-shadow: inset 0 0 0 2px var(--line); position: relative; overflow: hidden; flex: none;
}
.vic-bar i { position: absolute; top: 0; bottom: 0; }
#vic-bar-a { left: 0; background: var(--ink); }
#vic-bar-b { right: 0; background: var(--gold); }
.vic-mid {
  position: absolute; left: 50%; top: -2px; bottom: -2px; width: 3px;
  margin-left: -1.5px; background: var(--bg);
}
/* A knockout pushed the bar all the way, so the centre tick has nothing left
   to measure and only clutters the win. */
.vic-bar.is-ko .vic-mid { display: none; }

.vic-head { display: flex; flex-direction: column; gap: 4px; padding-top: 10px; }
.vic-kicker {
  font-weight: 800; font-size: 0.875rem; color: var(--ink-dim);
  text-transform: uppercase; letter-spacing: 0.08em;
}
/* 128px, slammed in from 2.4x and left slightly off square, because a
   knockout is the loudest moment the product has. */
.vic-ko {
  font-weight: 900; font-size: 8rem; line-height: 0.85; letter-spacing: -0.06em;
  color: var(--gold); animation: vic-slam 0.7s var(--ease) both;
}
.vic-headline {
  width: 100%; font-weight: 900; text-transform: uppercase;
  letter-spacing: -0.03em; line-height: 0.95; white-space: nowrap;
  font-size: clamp(1.75rem, 11vw, 3.25rem);
  /* A hard stop under fitName. A pathological side name that still does not
     fit at the smallest size gets clipped rather than pushing the whole page
     sideways, which is the worse of the two failures. */
  overflow: hidden;
}
.vic-sub {
  font-weight: 900; font-size: 1.25rem; text-transform: uppercase;
  letter-spacing: -0.02em; line-height: 1.1;
}
.vic-detail { font-weight: 700; font-size: 0.9375rem; color: var(--ink-dim); font-variant-numeric: tabular-nums; }

.vic-faces { display: flex; justify-content: center; flex-wrap: wrap; gap: 10px; }
.vic-face { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.vic-face i {
  width: 64px; height: 64px; border-radius: 18px; background: var(--bg-raise);
  display: grid; place-items: center; font-size: 2.125rem; font-style: normal;
}
.vic-face.is-a i { box-shadow: inset 0 0 0 3px var(--ink); }
.vic-face.is-b i { box-shadow: inset 0 0 0 3px var(--gold); }
.vic-face span { font-weight: 800; font-size: 0.8125rem; max-width: 72px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.vic-you {
  background: var(--bg-raise); border-radius: var(--r-panel); padding: 16px 18px;
  display: flex; justify-content: space-between; gap: 8px; text-align: left;
}
.vic-you.is-a { box-shadow: inset 0 0 0 2px var(--ink); }
.vic-you.is-b { box-shadow: inset 0 0 0 2px var(--gold); }
.vic-stat { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.vic-stat b { font-weight: 900; font-size: 1.25rem; font-variant-numeric: tabular-nums; }
.vic-stat span { font-weight: 600; font-size: 0.6875rem; color: var(--ink-dim); }

.vic-boards { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.vic-board {
  background: var(--bg-raise); border-radius: var(--r-panel); padding: 14px;
  display: flex; flex-direction: column; gap: 8px; text-align: left; min-width: 0;
}
.vic-board-a { box-shadow: inset 0 0 0 2px var(--ink); }
.vic-board-b { box-shadow: inset 0 0 0 2px var(--gold); }
/* The same side card as the reveal's, so the same rule from TeamsGreek: the
   name goes above its number rather than beside it. "Χταπόδια" was clipped to
   "ΧΤΑΠΟ…" next to 995 on the screen that announces who won, which is the
   worst place to lose half a side's name. */
.vic-board-head { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.vic-board-head span { font-weight: 900; font-size: 0.8125rem; text-transform: uppercase; overflow-wrap: anywhere; }
.vic-board-b .vic-board-head span { color: var(--gold); }
.vic-board-head b { font-weight: 900; font-size: 0.9375rem; font-variant-numeric: tabular-nums; }
.vic-row { display: flex; align-items: center; justify-content: space-between; gap: 6px; font-weight: 600; font-size: 0.8125rem; }
.vic-row > .chip { min-width: 0; }
.vic-row b { font-weight: 800; font-variant-numeric: tabular-nums; }

.vic-story { display: flex; flex-direction: column; gap: 8px; text-align: left; }
.vic-story-label {
  font-weight: 800; font-size: 0.8125rem; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--ink-dim);
}
.vic-beat {
  display: flex; align-items: center; gap: 10px; font-weight: 600; font-size: 0.8125rem;
  padding: 8px 12px; border-radius: 10px; background: var(--bg-sink);
}
.vic-beat i { color: var(--ink-dim); width: 32px; flex: none; font-style: normal; font-variant-numeric: tabular-nums; }
.vic-beat > span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The sentence gives way, not the name. "First blood, Foxes" still reads when
   it is cut; "Mar" is not a person. */
.vic-beat > b { flex: none; }

/* Rows narrow enough that the tile has to give way before the name does. A
   smaller face is still a face; a name cut to three letters is not a name. */
.ss-row > .chip, .vic-row > .chip, .vic-beat > b > .chip { gap: 7px; font-size: 0.8125rem; }
.ss-row > .chip .chip-tile,
.vic-row > .chip .chip-tile,
.vic-beat > b > .chip .chip-tile { width: 22px; height: 22px; border-radius: 7px; font-size: 0.85rem; }
.vic-beat b { font-weight: 800; }
.vic-beat.is-b b { color: var(--gold); }

.vic-actions { display: flex; gap: 10px; margin-top: 10px; }
.vic-actions .btn { flex: 1; }
.vic-wait { font-weight: 700; font-size: 0.9375rem; color: var(--ink-dim); }

/* Confetti, from the palette, and only for a knockout. Transform and opacity
   only, and nothing at all when motion is turned down. */
.vic-confetti { position: absolute; inset: -8px -8px auto; height: 200px; pointer-events: none; overflow: hidden; }
.vic-confetti i {
  position: absolute; width: 10px; height: 16px; border-radius: 3px;
  animation: vic-fall 2.4s var(--ease) both;
}
@keyframes vic-slam {
  from { transform: scale(2.4) rotate(-6deg); opacity: 0; }
  55%  { transform: scale(1) rotate(-3deg); opacity: 1; }
  to   { transform: scale(1) rotate(-3deg); opacity: 1; }
}
@keyframes vic-fall {
  from { transform: translateY(-40px) rotate(0deg); opacity: 0; }
  20%  { opacity: 1; }
  to   { transform: translateY(190px) rotate(220deg); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .vic-ko { animation: none; }
  .vic-confetti { display: none; }
}

/* ═══════════ the lobby, rebuilt ═══════════
   design/canvas/Lobby.dc.html, revised. Three things a host can answer out
   loud, then one sentence for everything else.

   The sentence is what makes this survive Greek. Four segmented controls in a
   column do not wrap and cannot shrink; a sentence does both. */
.lobby-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.lobby-heading { font-weight: 900; font-size: 1.375rem; text-transform: uppercase; letter-spacing: -0.02em; }
/* A holder, not a pill. The chip inside is the pill, and the gold ring this
   used to draw by hand is what the component calls "you". */
.lobby-me { display: flex; align-items: center; min-width: 0; }
.invite { display: flex; flex-direction: column; gap: 8px; align-items: center; }

/* The player chip's away state. The seat is held for two minutes, so the chip
   is faded and breathing rather than gone: somebody whose phone locked has not
   left the party. */
/* The range is the whole state, not a pulse laid over an opacity: a keyframe
   that returns to 1 would make the held seat the brightest chip in the room,
   which is the opposite of away. */
@keyframes lobby-breathe { 0%, 100% { opacity: 0.5; } 50% { opacity: 0.28; } }

/* ─── the mode cards, now a pair of small rows ─── */
.mode-select { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.mode-card {
  text-align: left; font: inherit; color: inherit; cursor: pointer; border: 0;
  background: var(--bg-raise); border-radius: var(--r-ctl); padding: 12px 14px;
  box-shadow: inset 0 0 0 2px var(--line);
  display: flex; align-items: center; gap: 10px; min-width: 0;
  -webkit-tap-highlight-color: transparent;
  transition: box-shadow 0.2s var(--ease);
}
.mode-card:active { transform: scale(0.98); }
.mode-card .mode-name {
  /* "Free for all" is two words and "Όλοι εναντίον όλων" is three, in a card
     that is half a phone wide minus its swatch. Shrinking beats wrapping to
     two lines and taking the row with it. */
  font-weight: 900; font-size: clamp(0.6875rem, 3.1vw, 0.875rem);
  text-transform: uppercase; letter-spacing: -0.02em; color: var(--ink-dim);
  min-width: 0; line-height: 1.15;
}
.mode-card.is-picked .mode-name { color: var(--ink); }
/* On a phone the swatch goes above the name rather than beside it. The card is
   half the width of the screen, and the swatch plus its gap takes 58 of the
   112 left inside it, so "Ελεύθερα" needs 63 and gets 56. The name is already
   at the floor of its clamp, and it is one word, so it can neither shrink nor
   wrap its way out: it was simply cut, with no ellipsis to admit it. The row
   only fits from about 400px up, so the split is at the phone breakpoint the
   answers already use rather than at the 320 floor. */
@media (max-width: 480px) {
  .mode-card { flex-direction: column; align-items: flex-start; gap: 6px; }
}
#mode-solo.is-picked { box-shadow: inset 0 0 0 2px var(--gold); }
#mode-teams.is-picked { box-shadow: inset 0 0 0 2px var(--gold); }
.mode-swatch { display: flex; gap: 3px; flex: none; }
.mode-swatch i { width: 10px; height: 10px; border-radius: 3px; }
.ms-coral { background: var(--coral); } .ms-amber { background: var(--amber); }
.ms-teal  { background: var(--teal); }  .ms-blue  { background: var(--blue); }
.mode-bar { width: 40px; height: 10px; border-radius: 999px; display: flex; overflow: hidden; flex: none; }
.mode-bar i { flex: 1; }
.mode-bar i:first-child { background: var(--ink); }
.mode-bar i:last-child { background: var(--gold); }

/* ─── the game card ─── */
.game-card {
  background: var(--bg-raise); border-radius: var(--r-panel);
  box-shadow: inset 0 0 0 2px var(--line); display: flex; flex-direction: column;
}
.gc-row { padding: 12px 18px; border-bottom: 2px solid var(--line); }
.gc-row:last-child { border-bottom: 0; }
.gc-topics { padding: 16px 18px 14px; display: flex; flex-direction: column; gap: 10px; }
.gc-inline { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.gc-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.gc-label {
  font-weight: 800; font-size: 0.8125rem; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--ink-dim);
}
.gc-label-stack { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.gc-cap { font-weight: 600; font-size: 0.75rem; color: var(--ink-dim); line-height: 1.3; }

/* Four digits read off a television, so they are spaced like the thing being
   copied rather than like a form field, and there is no submit: the fourth
   digit is the whole gesture. */
/* input.pair-code, not .pair-code: the base rule is input[type="text"], which
   outranks a bare class and was setting this to width 100%. */
input.pair-code {
  font: inherit; font-weight: 900; font-size: 1.05rem; letter-spacing: 0.25em;
  /* Four digits plus their tracking. Six characters of room clipped the last
     one, in the placeholder and in what you type. */
  width: 8ch; text-align: center; flex: none;
  background: var(--bg-sink); border: 2px solid var(--line); border-radius: var(--r-ctl);
  color: var(--ink); padding: 8px 6px 8px 12px; outline: none;
}
input.pair-code:focus { border-color: var(--gold); }
input.pair-code::placeholder { color: var(--ink-dim); opacity: 0.5; letter-spacing: 0.25em; }
/* Greek's "Τελικό στοίχημα" plus its caption pushes the control off the edge
   at 320, so the caption is the part that goes. The label and the control are
   what the host is actually reaching for. */
@media (max-width: 359px) {
  .gc-cap { display: none; }
  /* The board's own 320 frame: tighter card padding, 12px labels at 0.04em,
     and a smaller segmented control. Together they give the label enough room
     to stay on one line, which "Τελικό στοίχημα" needs and did not have. */
  .gc-row { padding: 10px 14px; }
  .gc-topics { padding: 14px 14px 12px; }
  .gc-summary { padding-bottom: 12px; }
  .gc-label { font-size: 0.75rem; letter-spacing: 0.04em; }
  .game-card .seg-btn { font-size: 0.8125rem; padding: 6px 11px; }
  /* The board's own 320 frame shrinks these, and it has to: the swatch and its
     gap were eating enough of a 140px card that "Ελεύθερα" was clipped. */
  .mode-card { padding: 10px 12px; gap: 6px; }
  .mode-swatch { gap: 2px; }
  .mode-swatch i { width: 8px; height: 8px; border-radius: 2px; }
  .mode-bar { width: 28px; height: 8px; }
}
.gc-note { font-weight: 700; font-size: 0.75rem; color: var(--ink-dim); }
.gc-add-line { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
.gc-add {
  border: 2px dashed var(--line); background: transparent; font: inherit; cursor: pointer;
  border-radius: 999px; padding: 7px 14px; font-weight: 700; font-size: 0.875rem;
  color: var(--ink-dim); -webkit-tap-highlight-color: transparent;
}
.gc-add:active { opacity: 0.7; }
.gc-summary { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding-bottom: 14px; }
.gc-summary-text { font-weight: 600; font-size: 0.8125rem; color: var(--ink-dim); line-height: 1.4; }
/* The classic clause is the one part of the sentence that is a setting rather
   than a default, so it is the one part in ink. */
.gc-summary-text b { color: var(--ink); font-weight: 700; }
.gc-tweak {
  border: 0; background: transparent; font: inherit; cursor: pointer;
  font-weight: 800; font-size: 0.8125rem; color: var(--gold); white-space: nowrap;
  padding: 4px; -webkit-tap-highlight-color: transparent;
}

/* ─── the tweak sheet ─── */
.tweak-scrim { position: fixed; inset: 0; background: oklch(0.19 0.025 40 / 0.72); z-index: 40; }
.tweak-sheet {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 41;
  background: var(--bg-raise); border-radius: var(--r-panel) var(--r-panel) 0 0;
  box-shadow: inset 0 0 0 2px var(--line);
  padding: 14px 20px max(24px, env(safe-area-inset-bottom));
  display: flex; flex-direction: column;
  max-height: 88dvh; overflow-y: auto;
  animation: tweak-up 0.32s var(--ease);
}
.tweak-sheet[hidden], .tweak-scrim[hidden] { display: none; }
@keyframes tweak-up { from { transform: translateY(100%); } }
.tweak-grab { width: 44px; height: 5px; border-radius: 999px; background: var(--line); align-self: center; margin-bottom: 10px; }
.tweak-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding-bottom: 8px; }
.tweak-head h2 { margin: 0; font-weight: 900; font-size: 1.375rem; text-transform: uppercase; letter-spacing: -0.02em; }
.tweak-done {
  border: 0; background: transparent; font: inherit; cursor: pointer;
  font-weight: 700; font-size: 0.875rem; color: var(--gold); padding: 4px;
  -webkit-tap-highlight-color: transparent;
}
.tweak-row {
  padding: 12px 0; border-top: 2px solid var(--line);
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
}
.tweak-row.is-bare { border-top: 0; padding: 8px 0 12px; }

/* A conditional member is a box, never a row. A row that disappears leaves an
   orphaned divider and a hole where a setting used to be; a box that
   disappears leaves nothing at all, which is what "sometimes not there" should
   look like. */
.tweak-box {
  margin-top: 10px; border-radius: var(--r-ctl); padding: 4px 14px;
  box-shadow: inset 0 0 0 2px var(--line); display: flex; flex-direction: column;
}
.tweak-box[hidden] { display: none; }
.tweak-box.is-teams { box-shadow: inset 0 0 0 2px var(--gold); }
.tweak-box-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 10px 0 4px; }
.tweak-box-label {
  font-weight: 800; font-size: 0.6875rem; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--ink-dim);
}
.is-teams .tweak-box-label { color: var(--gold); }
.tweak-escape {
  border: 0; background: transparent; font: inherit; cursor: pointer;
  font-weight: 700; font-size: 0.6875rem; color: var(--gold); padding: 2px;
  -webkit-tap-highlight-color: transparent;
}
/* "To the bell" is three words in a control sized for "Off", and "Μέχρι το
   κουδούνι" in Greek. Same tightening the teams lobby needed. */
.tweak-box .seg-btn { font-size: 0.75rem; padding: 6px 10px; white-space: nowrap; }
.tweak-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; padding: 8px 0 12px; }
.tweak-field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
@media (prefers-reduced-motion: reduce) {
  .tweak-sheet { animation: none; }
}

/* ═══════════ teams: the reveal ═══════════
   design/canvas/TeamsReveal.dc.html. A fight's reveal is two sides, not one
   ranked list, so the mini leaderboard steps aside for these. */
.clean-round { display: flex; flex-direction: column; gap: 4px; text-align: center; }
.clean-round[hidden] { display: none; }
.clean-title {
  font-weight: 900; font-size: clamp(1.75rem, 9vw, 2.5rem); text-transform: uppercase;
  letter-spacing: -0.03em; line-height: 0.95; color: var(--gold);
}
.clean-sub { font-weight: 700; font-size: 0.9375rem; }
.side-scores { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.side-scores[hidden] { display: none; }
.side-score {
  background: var(--bg-raise); border-radius: var(--r-panel); padding: 14px;
  display: flex; flex-direction: column; gap: 8px; text-align: left; min-width: 0;
}
.side-score-a { box-shadow: inset 0 0 0 2px var(--ink); }
.side-score-b { box-shadow: inset 0 0 0 2px var(--gold); }
/* Name over delta, not beside it. The two do not share a card this narrow in
   Greek: "Χταπόδια" is already clipped next to "+995" on a 375px phone, and
   "Κουκουβάγιες" is four characters longer. TeamsGreek.dc.html stacks them,
   which costs one line and fits every name the game can generate. */
.ss-head { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
/* Wraps rather than ellipsising. The board drew it nowrap, which holds for
   "Κουκουβάγιες" at exactly the 390 it was drawn at, and fails on both sides
   of that: at 320 the card is 89px against 105 of name, and even at 390
   "Καμηλοπαρδάλεις" is 133 against 124. A side's name is its identity on the
   screen that reports the round, so it takes a second line instead of losing
   its ending. Everything shorter still fits on one. */
.ss-head span {
  font-weight: 900; font-size: 0.8125rem; text-transform: uppercase;
  overflow-wrap: anywhere;
}
.side-score-b .ss-head span { color: var(--gold); }
.ss-head b { font-weight: 900; font-size: 0.9375rem; font-variant-numeric: tabular-nums; }
.ss-list { display: flex; flex-direction: column; gap: 8px; }
.ss-row { display: flex; align-items: center; justify-content: space-between; gap: 6px; font-weight: 600; font-size: 0.8125rem; }
.ss-row > .chip { min-width: 0; }
.ss-row b { font-weight: 800; font-variant-numeric: tabular-nums; color: var(--good); }
/* Somebody who scored nothing shows what they picked rather than a zero: the
   shape says more than the number, and a column of zeroes reads as a fault. */
.ss-row.is-miss { color: var(--ink-dim); }
.ss-row.is-miss b { color: var(--ink-dim); font-weight: 600; }
.ss-foot {
  font-weight: 700; font-size: 0.6875rem; color: var(--ink-dim);
  border-top: 2px solid var(--line); padding-top: 6px;
}
/* The ghost: where the bar was, hatched, fading on opacity only. It is the
   swing for anyone who has motion turned down, so it must not be an
   animation that reduced motion removes. */
.fight-ghost {
  position: absolute; top: 0; bottom: 0;
  background: repeating-linear-gradient(135deg, var(--ink) 0 4px, transparent 4px 8px);
  opacity: 0.55; transition: opacity 2s var(--ease);
}
.fight-ghost.is-fading { opacity: 0; }

/* ═══════════ teams: the finisher ═══════════
   design/canvas/TeamsReveal.dc.html. The same tiers, clock and bet panel as the
   solo wager, because it is the same decision with the side's money. The only
   differences are the voters on the tiers, the pill on the median, and the
   panel's label. */
.wager-fight { display: flex; flex-direction: column; gap: 5px; }
.wager-fight[hidden] { display: none; }
/* The voters who picked this tier, so a side can see itself deciding. */
.tier-voters { display: flex; flex: none; }
.tier-voters span { font-size: 1.125rem; }
.tier-voters span + span { margin-left: -5px; }
.wager-tier.is-median {
  box-shadow: inset 0 0 0 2px var(--gold); position: relative;
}
.tier-pill {
  position: absolute; top: -9px; left: 14px; background: var(--gold); color: var(--gold-ink);
  border-radius: 999px; padding: 3px 10px; font-weight: 800; font-size: 0.625rem;
  text-transform: uppercase; letter-spacing: 0.06em; white-space: nowrap;
}

/* ═══════════ teams: the edges ═══════════
   design/canvas/TeamsEdges.dc.html. The states a party game actually hits. */

/* A side down a player. Said out loud, because a fight that quietly becomes
   2 v 3 reads as the bar being unfair rather than as somebody's phone locking. */
.short-side {
  display: flex; align-items: center; gap: 12px; margin-bottom: 10px;
  background: var(--bg-raise); border-radius: var(--r-ctl); padding: 12px 14px;
  box-shadow: inset 0 0 0 2px var(--line); text-align: left;
}
.short-side[hidden] { display: none; }
.short-avatar { font-size: 1.375rem; filter: grayscale(1); opacity: 0.6; flex: none; }
.short-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.short-text b { font-weight: 800; font-size: 0.875rem; }
.short-sub { font-weight: 600; font-size: 0.75rem; color: var(--ink-dim); line-height: 1.35; }

/* An empty side. The start button goes dead rather than a dialog appearing,
   and the gold is on the fix. */
.side-card.is-empty {
  background: transparent; box-shadow: none;
  border: 2px dashed var(--bad); align-items: center; justify-content: center; text-align: center;
}
.side-card.is-empty .side-list, .side-card.is-empty .side-count { display: none; }
/* The card centres its contents when empty, which left the full width name
   field hanging over the neighbouring card. */
.side-card.is-empty .side-head { width: 100%; }
.side-card.is-empty .side-name { text-align: center; border-bottom-color: transparent; }
.side-card.is-empty .side-head svg { display: none; }
.side-empty-note { display: none; }
.side-card.is-empty .side-empty-note {
  display: block; font-weight: 700; font-size: 0.8125rem;
  color: var(--ink-dim); line-height: 1.4;
}
/* Refused rather than dead: the button keeps its click so tapping it can say
   why, and a screen reader is told it cannot be used rather than finding a
   control it cannot reach. */
.btn[aria-disabled="true"] { opacity: 0.45; }
.side-card.is-empty.shake { animation: side-shake 0.4s var(--ease); }
@keyframes side-shake {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-6px); }
  75% { transform: translateX(6px); }
}
.empty-side {
  background: var(--bg-raise); border-radius: var(--r-ctl); padding: 12px 14px;
  box-shadow: inset 0 0 0 2px var(--bad);
  display: flex; flex-direction: column; gap: 2px; text-align: left;
}
.empty-side[hidden] { display: none; }
.empty-side b { font-weight: 800; font-size: 0.875rem; }
.empty-sub { font-weight: 600; font-size: 0.75rem; color: var(--ink-dim); line-height: 1.35; }

/* The host walked off. */
.paused-scrim { position: fixed; inset: 0; background: oklch(0.19 0.025 40 / 0.78); z-index: 50; }
.paused-card {
  position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%); z-index: 51;
  width: min(340px, calc(100vw - 40px));
  background: var(--bg-raise); border-radius: var(--r-panel); padding: 20px;
  box-shadow: inset 0 0 0 2px var(--line);
  display: flex; flex-direction: column; gap: 12px; text-align: center;
}
.paused-scrim[hidden], .paused-card[hidden] { display: none; }
.paused-avatar { font-size: 1.875rem; filter: grayscale(1); opacity: 0.6; }
.paused-title {
  margin: 0; font-weight: 900; font-size: 1.375rem; text-transform: uppercase;
  letter-spacing: -0.02em; line-height: 1;
}
.paused-body { margin: 0; font-weight: 600; font-size: 0.8125rem; color: var(--ink-dim); line-height: 1.5; }
#paused-host { display: flex; flex-direction: column; gap: 8px; }
.paused-wait {
  margin: 0; display: flex; align-items: center; justify-content: center; gap: 10px;
  font-weight: 700; font-size: 0.875rem;
}
.paused-wait::before {
  content: ""; width: 9px; height: 9px; border-radius: 999px; background: var(--gold);
  animation: mine-pulse 1.6s var(--ease) infinite;
}
@media (prefers-reduced-motion: reduce) {
  .paused-wait::before, .side-card.is-empty.shake { animation: none; }
}

/* ═══════════ buzzer mode, from OneScreen.dc.html ═══════════
   A television in the room is showing the question, so the phone stops being a
   place to read and becomes a place to press. No new screen: the question
   screen loses its words and its four answers become quadrants. Everything
   downstream, locking and streaks and the reveal, is untouched. */
.buzzers #q-text,
.buzzers .q-category,
.buzzers #screen-question .a-text { display: none; }
/* The header keeps the timer and the count, because a glance down should still
   answer "how long have I got" without looking back up. */
.buzzers .q-header { justify-content: space-between; }
.buzzers .answers {
  grid-template-columns: 1fr 1fr; gap: 10px;
  flex: 1; align-content: stretch;
}
.buzzers #screen-question .answer {
  /* Roughly 170 by 300 on a 390 phone, which is the board's number and is
     larger than a thumb can miss. */
  min-height: 0; height: 100%; justify-content: center;
  font-size: 3.5rem; padding: 0;
}
.buzzers #screen-question .a-shape { width: auto; font-size: 3.5rem; opacity: 1; }
/* Dimmed until the question is live, so the four positions are learned before
   they are needed rather than at the moment they matter. */
.buzzers #screen-question .answer:disabled { opacity: 0.35; }
.buzzers #screen-question .answer.picked { opacity: 1; }
.buzzers #screen-question .answer.dim { opacity: 0.3; }
/* The wager is the one place buzzer mode prints words, because the numbers are
   this player's own and the television cannot show them. */
.buzzers #screen-question .answer .a-tier {
  display: block; font-size: 0.9375rem; font-weight: 800; margin-top: 6px;
}
.a-tier { display: none; }

/* The wager, with a television in the room. The three tiers and sitting out
   become the same four quadrants the answers use, carrying their shapes and
   their colours, and one tap locks. The phone breaks its own no-words rule
   exactly here, because the number on each button is this player's own and the
   television cannot show it to them. */
.wager-shape { display: none; }
.buzzers .wager-tiers { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; flex: 1; }
.buzzers .wager-tier {
  flex-direction: column; align-items: flex-start; justify-content: center;
  gap: 6px; height: 100%; padding: 16px;
}
.buzzers .wager-shape { display: block; font-size: 2rem; line-height: 1; }
.buzzers .wager-tier-note, .buzzers .tier-voters, .buzzers .tier-pill { display: none; }
.buzzers .wager-tier-name { font-size: 1.0625rem; }
.buzzers .wager-tier-points { font-size: 1.5rem; }
/* The confirm and the old sit out line both go: the fourth quadrant is the sit
   out, and a tap is the whole gesture. */
.buzzers #btn-wager, .buzzers #wager-out, .buzzers .wager-panel { display: none; }
