/*
 * Two surfaces, one sheet.
 *
 * .screen is read from a sofa: type scales with the viewport, contrast is high,
 * and there is margin to spare because televisions still overscan the edges.
 * .play is held in one hand: targets stay above 56px, the important controls sit
 * where a thumb reaches, and nothing depends on hovering.
 *
 * Fonts are self-hosted (public/fonts) so the pages render identically with no
 * outbound request -- which also means they work over an SSH tunnel with no
 * internet on the client.
 */

@font-face {
  font-family: 'Outfit';
  src: url('/fonts/outfit-latin.woff2') format('woff2-variations');
  font-weight: 100 900;
  font-display: swap;
}
@font-face {
  font-family: 'InterVar';
  src: url('/fonts/inter-latin.woff2') format('woff2-variations');
  font-weight: 100 900;
  font-display: swap;
}

:root {
  --bg: #08080f;
  --ink: #f2f5fa;
  --ink-dim: #a4adc0;
  --ink-mute: #6d7789;

  --surface: rgba(255, 255, 255, .045);
  --surface-2: rgba(255, 255, 255, .08);
  --line: rgba(255, 255, 255, .10);
  --line-2: rgba(255, 255, 255, .18);

  --brand-a: #6366f1;
  --brand-b: #c026d3;
  --accent: #818cf8;
  --good: #34d399;
  --bad: #fb7185;
  --warn: #fbbf24;
  --gold: #fcd34d;
  --silver: #cbd5e1;
  --bronze: #d8a25e;

  /* Quiz identity. Each is paired with a distinct glyph in the markup, so the
     answer is never carried by colour alone. */
  --opt-0: #3b82f6;
  --opt-1: #f59e0b;
  --opt-2: #e935d6;
  --opt-3: #10b981;

  --r-sm: .6rem;
  --r-md: 1rem;
  --r-lg: 1.4rem;
  --shadow: 0 18px 50px rgba(0, 0, 0, .55);
  --display: 'Outfit', system-ui, sans-serif;
  --text: 'InterVar', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

body {
  font-family: var(--text);
  color: var(--ink);
  background: var(--bg);
  min-height: 100dvh;
  -webkit-text-size-adjust: 100%;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* Ambient colour so the dark is not a flat void. Fixed and non-interactive:
   it must never intercept a tap. */
body::before {
  content: '';
  position: fixed;
  inset: -20%;
  pointer-events: none;
  z-index: 0;
  background:
    radial-gradient(38% 42% at 12% 8%, rgba(99, 102, 241, .30), transparent 70%),
    radial-gradient(36% 40% at 88% 12%, rgba(192, 38, 211, .24), transparent 70%),
    radial-gradient(50% 50% at 50% 108%, rgba(6, 182, 212, .16), transparent 70%);
  filter: blur(10px);
}
body > * { position: relative; z-index: 1; }

button { font: inherit; color: inherit; border: none; background: none; cursor: pointer; }
input { font: inherit; }

h1, h2, h3, .display { font-family: var(--display); letter-spacing: -.02em; font-weight: 700; }

@keyframes rise { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
@keyframes pop { from { opacity: 0; transform: scale(.94); } to { opacity: 1; transform: none; } }
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: .45; } }
@keyframes sheen { to { background-position: 200% center; } }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* ====================================================================== */
/* Landing                                                                 */
/* ====================================================================== */

.landing {
  min-height: 100dvh;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: 2.5rem; padding: 2rem; text-align: center;
}
.landing h1 {
  font-size: clamp(2.6rem, 9vw, 5.5rem);
  font-weight: 800;
  background: linear-gradient(100deg, var(--accent), var(--brand-b) 60%, var(--accent));
  background-size: 200% auto;
  -webkit-background-clip: text; background-clip: text;
  color: transparent;
  animation: sheen 7s linear infinite;
}
.landing p { color: var(--ink-dim); max-width: 34rem; line-height: 1.65; font-size: 1.05rem; }
.landing .choices { display: flex; gap: 1.25rem; flex-wrap: wrap; justify-content: center; }
.landing a {
  display: block; text-decoration: none; color: var(--ink);
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: 1.9rem 2.6rem; min-width: 15rem;
  box-shadow: var(--shadow);
  transition: border-color .18s, transform .18s, background .18s;
}
.landing a:hover { border-color: var(--line-2); background: var(--surface-2); transform: translateY(-3px); }
.landing a strong { display: block; font-family: var(--display); font-size: 1.45rem; margin-bottom: .35rem; }
.landing a span { color: var(--ink-dim); font-size: .95rem; }

/* ====================================================================== */
/* Screen (the television)                                                 */
/* ====================================================================== */

.screen {
  min-height: 100dvh;
  display: flex; flex-direction: column;
  padding: clamp(1rem, 2.6vmin, 2.6rem) clamp(1.2rem, 3.4vmin, 3.4rem);
  gap: clamp(.8rem, 2vmin, 1.8rem);
}
.screen #body { flex: 1; display: flex; flex-direction: column; min-height: 0; }

.screen-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 2rem; }
.screen-head .brand {
  font-family: var(--display); font-weight: 700;
  font-size: clamp(.85rem, 1.7vmin, 1.4rem);
  color: var(--ink-mute); letter-spacing: .3em; text-transform: uppercase;
}
.screen-head .join { text-align: right; line-height: 1.1; }
.screen-head .join .url { color: var(--ink-mute); font-size: clamp(.75rem, 1.4vmin, 1.15rem); letter-spacing: .04em; }
.screen-head .join .code {
  font-family: var(--display); font-weight: 800;
  font-size: clamp(2.4rem, 7vmin, 6rem); line-height: 1;
  letter-spacing: .1em;
  background: linear-gradient(120deg, #a5b4fc, #f0abfc);
  -webkit-background-clip: text; background-clip: text; color: transparent;
  filter: drop-shadow(0 0 26px rgba(168, 85, 247, .45));
}

.screen-body {
  flex: 1; display: flex; flex-direction: column;
  justify-content: center; gap: clamp(.8rem, 2.4vmin, 2rem);
  animation: rise .32s ease both;
  min-height: 0;
}
.screen h2 { font-size: clamp(1.6rem, 5vmin, 4rem); line-height: 1.1; }
.screen .sub { color: var(--ink-dim); font-size: clamp(.9rem, 1.9vmin, 1.5rem); line-height: 1.5; }

/* --- player chips ------------------------------------------------------ */

.roster { display: flex; flex-wrap: wrap; gap: clamp(.45rem, 1.2vmin, .9rem); }
.chip {
  display: flex; align-items: center; gap: .6em;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 999px; padding: .4em .95em .4em .4em;
  font-size: clamp(.85rem, 2vmin, 1.5rem);
  animation: pop .25s ease both;
}
.chip.host { border-color: rgba(129, 140, 248, .6); box-shadow: 0 0 0 1px rgba(129, 140, 248, .25); }
.chip.off { opacity: .38; }
.chip .ava {
  width: 1.9em; height: 1.9em; border-radius: 50%;
  display: grid; place-items: center;
  font-family: var(--display); font-weight: 700; font-size: .8em;
  color: #0b0b12; flex: none;
}
.chip .pts { color: var(--ink-mute); font-variant-numeric: tabular-nums; font-size: .85em; }
.chip .crown { font-size: .8em; }

/* --- game menu --------------------------------------------------------- */

.game-menu {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: clamp(.7rem, 1.8vmin, 1.4rem);
}
.game-card {
  position: relative; overflow: hidden;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-md); padding: clamp(.9rem, 2.2vmin, 1.8rem);
  transition: border-color .2s, background .2s;
}
.game-card::before {
  content: ''; position: absolute; inset: 0 auto 0 0; width: 4px;
  background: linear-gradient(180deg, var(--brand-a), var(--brand-b));
  opacity: .5;
}
.game-card.picked { border-color: rgba(129, 140, 248, .7); background: var(--surface-2); }
.game-card.picked::before { opacity: 1; }
.game-card.blocked { opacity: .4; }
.game-card h3 { font-size: clamp(1rem, 2.6vmin, 1.9rem); margin-bottom: .35em; }
.game-card p { color: var(--ink-dim); font-size: clamp(.75rem, 1.55vmin, 1.1rem); line-height: 1.5; }
.game-card .meta { margin-top: .6em; color: var(--ink-mute); font-size: clamp(.7rem, 1.35vmin, .95rem); }

/* --- timer ------------------------------------------------------------- */

.timer {
  height: clamp(.4rem, .9vmin, .8rem);
  background: rgba(255, 255, 255, .07);
  border-radius: 999px; overflow: hidden; flex: none;
}
.timer > i {
  display: block; height: 100%; border-radius: 999px;
  background: linear-gradient(90deg, var(--brand-a), var(--accent));
  transition: background .4s;
}
.timer.low > i { background: linear-gradient(90deg, #f43f5e, var(--bad)); animation: pulse 1s ease-in-out infinite; }

/* --- tris -------------------------------------------------------------- */

.tris-wrap {
  display: flex; gap: clamp(1rem, 4vmin, 4rem);
  align-items: center; justify-content: center; flex-wrap: wrap; flex: 1; min-height: 0;
}
.tris-board {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: clamp(.35rem, .9vmin, .8rem);
  background: rgba(255, 255, 255, .07);
  padding: clamp(.35rem, .9vmin, .8rem);
  border-radius: var(--r-md);
  height: min(56vmin, 62vh); aspect-ratio: 1;
  box-shadow: var(--shadow);
}
.tris-cell {
  background: #10101a; border-radius: var(--r-sm);
  display: grid; place-items: center;
  font-family: var(--display); font-weight: 800; line-height: 1;
  font-size: min(13vmin, 15vh);
}
.tris-cell.x { color: var(--opt-0); text-shadow: 0 0 28px rgba(59, 130, 246, .5); }
.tris-cell.o { color: var(--opt-1); text-shadow: 0 0 28px rgba(245, 158, 11, .5); }
.tris-cell.win { background: rgba(52, 211, 153, .16); box-shadow: inset 0 0 0 2px var(--good); }
.tris-side { min-width: 15rem; display: flex; flex-direction: column; gap: clamp(.6rem, 1.6vmin, 1.2rem); }
.tris-vs {
  display: flex; align-items: center; gap: .7em;
  font-size: clamp(.95rem, 2.3vmin, 1.8rem);
  padding: .45em .8em; border-radius: var(--r-sm);
  border: 1px solid transparent;
}
.tris-vs.active { background: var(--surface); border-color: var(--line-2); }
.tris-vs .mark { font-family: var(--display); font-weight: 800; }
.tris-vs .mark.x { color: var(--opt-0); }
.tris-vs .mark.o { color: var(--opt-1); }

/* --- quiz -------------------------------------------------------------- */

.quiz-cat {
  text-align: center; color: var(--ink-mute);
  letter-spacing: .26em; text-transform: uppercase;
  font-size: clamp(.7rem, 1.4vmin, 1rem); font-weight: 600;
}
.quiz-q {
  font-family: var(--display); font-weight: 700;
  font-size: clamp(1.5rem, 4.6vmin, 3.6rem); line-height: 1.15;
  text-align: center; text-wrap: balance;
}
.quiz-opts { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(.5rem, 1.4vmin, 1.1rem); }
.quiz-opt {
  display: flex; align-items: center; gap: .75em;
  border-radius: var(--r-md); padding: clamp(.7rem, 1.9vmin, 1.5rem) clamp(.9rem, 2.2vmin, 1.7rem);
  font-size: clamp(.95rem, 2.5vmin, 2rem);
  background: var(--surface); border: 1px solid var(--line);
  border-left: 5px solid var(--c);
  transition: opacity .25s, background .25s;
  animation: pop .28s ease both;
}
.quiz-opt.o0 { --c: var(--opt-0); } .quiz-opt.o1 { --c: var(--opt-1); }
.quiz-opt.o2 { --c: var(--opt-2); } .quiz-opt.o3 { --c: var(--opt-3); }
.quiz-opt .glyph { color: var(--c); font-size: 1.15em; line-height: 1; flex: none; }
.quiz-opt.right { background: rgba(52, 211, 153, .16); border-color: var(--good); }
.quiz-opt.dim { opacity: .3; }
.quiz-opt .count {
  margin-left: auto; color: var(--ink-mute);
  font-variant-numeric: tabular-nums; font-weight: 700;
}

/* --- bugiardi ---------------------------------------------------------- */

.prompt {
  font-family: var(--display); font-weight: 600;
  font-size: clamp(1.3rem, 3.9vmin, 3rem); line-height: 1.3;
  text-align: center; text-wrap: balance;
}
.prompt .blank {
  color: var(--accent); letter-spacing: .04em;
  border-bottom: 3px solid var(--accent); padding: 0 .12em; margin-right: -.06em;
}
.answers { display: flex; flex-direction: column; gap: clamp(.35rem, 1vmin, .7rem); }
.answer {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-sm);
  padding: clamp(.5rem, 1.4vmin, 1rem) clamp(.8rem, 1.9vmin, 1.3rem);
  font-size: clamp(.9rem, 2.2vmin, 1.7rem);
  display: flex; align-items: baseline; gap: .8em; flex-wrap: wrap;
  animation: pop .25s ease both;
}
.answer.truth { border-color: var(--good); background: rgba(52, 211, 153, .14); }
.answer .by { color: var(--ink-mute); font-size: .76em; }
.answer .took { color: var(--warn); font-size: .76em; margin-left: auto; }

/* --- leaderboard ------------------------------------------------------- */

.board { display: flex; flex-direction: column; gap: .35rem; }
.board-row {
  display: flex; align-items: center; gap: .9em;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-sm);
  padding: clamp(.4rem, 1.1vmin, .8rem) clamp(.7rem, 1.6vmin, 1.1rem);
  font-size: clamp(.9rem, 2.2vmin, 1.7rem);
  animation: rise .3s ease both;
}
.board-row .pos {
  font-family: var(--display); font-weight: 800;
  color: var(--ink-mute); min-width: 1.6em; font-variant-numeric: tabular-nums;
}
.board-row .pts { margin-left: auto; font-weight: 700; font-variant-numeric: tabular-nums; }
.board-row .gain { color: var(--good); font-size: .78em; font-weight: 600; }
.board-row.p1 { border-color: var(--gold); background: rgba(252, 211, 77, .12); }
.board-row.p1 .pos { color: var(--gold); }
.board-row.p2 { border-color: rgba(203, 213, 225, .45); }
.board-row.p2 .pos { color: var(--silver); }
.board-row.p3 { border-color: rgba(216, 162, 94, .45); }
.board-row.p3 .pos { color: var(--bronze); }

.split { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(1rem, 3vmin, 2.5rem); align-items: start; }
@media (max-width: 900px) { .split { grid-template-columns: 1fr; } }

/* ====================================================================== */
/* Controller (the phone)                                                  */
/* ====================================================================== */

.play {
  min-height: 100dvh; display: flex; flex-direction: column;
  gap: .9rem; max-width: 34rem; margin: 0 auto;
  padding: max(.9rem, env(safe-area-inset-top)) .9rem max(.9rem, env(safe-area-inset-bottom));
}
.play #body { flex: 1; display: flex; flex-direction: column; min-height: 0; }

.play-head {
  /* Name on the left, then score and exit pushed together on the right. */
  display: flex; align-items: center; gap: .5rem;
  padding: .55rem .9rem; border-radius: 999px;
  background: var(--surface); border: 1px solid var(--line);
  flex: none;
}
.play-head .who { display: flex; align-items: center; gap: .5em; font-weight: 700; }
.play-head .ava {
  width: 1.7em; height: 1.7em; border-radius: 50%; display: grid; place-items: center;
  font-family: var(--display); font-weight: 700; font-size: .85em; color: #0b0b12;
}
.play-head .score { margin-left: auto; color: var(--ink-dim); font-variant-numeric: tabular-nums; font-size: .9rem; }

.play-body {
  flex: 1; display: flex; flex-direction: column; justify-content: center;
  gap: .9rem; min-height: 0;
  animation: rise .28s ease both;
}
.play h2 { font-size: 1.6rem; line-height: 1.2; }
.play .hint { color: var(--ink-dim); line-height: 1.55; font-size: .95rem; }
.play .status { text-align: center; font-size: 1.15rem; color: var(--ink-dim); line-height: 1.5; }

.field { display: flex; flex-direction: column; gap: .45rem; }
.field label { color: var(--ink-dim); font-size: .85rem; font-weight: 600; }
.field input {
  background: rgba(255, 255, 255, .06); border: 1px solid var(--line);
  border-radius: var(--r-md); padding: 1rem; color: var(--ink); width: 100%;
  transition: border-color .15s, background .15s;
}
.field input::placeholder { color: var(--ink-mute); }
.field input:focus { outline: none; border-color: var(--accent); background: rgba(255, 255, 255, .09); }
.field input.code {
  font-family: var(--display); text-transform: uppercase;
  letter-spacing: .45em; text-indent: .45em;
  font-size: 2rem; text-align: center; font-weight: 800;
}

.btn {
  border-radius: var(--r-md); padding: 1.05rem; min-height: 56px; width: 100%;
  font-size: 1.05rem; font-weight: 700; font-family: var(--display);
  color: #fff; background: linear-gradient(135deg, var(--brand-a), var(--brand-b));
  box-shadow: 0 8px 24px rgba(99, 102, 241, .32);
  transition: transform .08s, filter .15s, box-shadow .15s;
}
.btn:active { transform: translateY(1px) scale(.99); }
.btn:disabled { opacity: .35; box-shadow: none; cursor: default; }
.btn.ghost {
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--line); box-shadow: none;
}
.btn.ghost:disabled { opacity: .5; }

.err { color: var(--bad); text-align: center; min-height: 1.3em; font-size: .9rem; flex: none; }

/* Quiz pad: fills whatever height is left, so the buttons are as big as the
   phone allows instead of floating in a sea of background. */
.pad { display: grid; grid-template-columns: 1fr 1fr; gap: .7rem; flex: 1; min-height: 14rem; }
.pad button {
  border-radius: var(--r-md); padding: .8rem;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .45rem;
  font-size: 1rem; font-weight: 700; text-align: center; color: #08080f;
  background: linear-gradient(160deg, var(--c), color-mix(in srgb, var(--c) 72%, #000));
  box-shadow: 0 10px 26px rgba(0, 0, 0, .4);
  transition: transform .08s, opacity .18s, box-shadow .15s;
}
.pad button.b0 { --c: var(--opt-0); } .pad button.b1 { --c: var(--opt-1); }
.pad button.b2 { --c: var(--opt-2); } .pad button.b3 { --c: var(--opt-3); }
.pad button .glyph { font-size: 2rem; line-height: 1; }
.pad button:active { transform: scale(.97); }
.pad button.faded { opacity: .22; box-shadow: none; }
.pad button.chosen { box-shadow: 0 0 0 4px var(--ink), 0 10px 26px rgba(0, 0, 0, .4); }

/* Tris grid: square, centred, and never taller than the space available. */
.grid3 {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: .5rem;
  width: min(100%, 22rem); aspect-ratio: 1; margin: 0 auto;
  background: rgba(255, 255, 255, .06); padding: .5rem; border-radius: var(--r-md);
}
.grid3 button {
  border-radius: var(--r-sm); background: #10101a;
  font-family: var(--display); font-size: 2.4rem; font-weight: 800;
  display: grid; place-items: center;
  transition: background .15s, transform .08s;
}
.grid3 button.x { color: var(--opt-0); }
.grid3 button.o { color: var(--opt-1); }
.grid3 button:disabled { opacity: .5; }
.grid3.armed button:not(:disabled) { background: rgba(129, 140, 248, .16); box-shadow: inset 0 0 0 1px rgba(129, 140, 248, .5); }
.grid3.armed button:not(:disabled):active { transform: scale(.95); }

.votes { display: flex; flex-direction: column; gap: .55rem; }
.votes button {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-md); padding: 1rem; min-height: 56px;
  text-align: left; font-size: 1rem; line-height: 1.35;
  transition: border-color .15s, background .15s, transform .08s;
}
.votes button:active { transform: scale(.99); }
.votes button.mine { opacity: .35; }
.votes button.chosen { border-color: var(--accent); background: var(--surface-2); }

.verdict {
  text-align: center; padding: 2rem 1rem; border-radius: var(--r-lg);
  background: var(--surface); border: 1px solid var(--line);
  animation: pop .3s ease both;
}
.verdict .big { font-family: var(--display); font-size: 2.4rem; font-weight: 800; margin-bottom: .3rem; }
.verdict.ok { border-color: var(--good); background: rgba(52, 211, 153, .12); }
.verdict.ok .big { color: var(--good); }
.verdict.no { border-color: var(--bad); background: rgba(251, 113, 133, .10); }
.verdict.no .big { color: var(--bad); }
.verdict .gain { color: var(--ink-dim); font-size: 1rem; }

.offline {
  position: fixed; inset: auto 0 0 0; z-index: 9;
  background: var(--warn); color: #1a1200;
  text-align: center; padding: .6rem; font-weight: 700; font-size: .9rem;
  padding-bottom: max(.6rem, env(safe-area-inset-bottom));
}

/* ====================================================================== */
/* Playing cards (Briscola)                                                */
/* ====================================================================== */

/*
 * Cards are drawn, not images: a face is a label plus a pip, which CSS renders
 * crisply at any size and keeps the app free of binary assets and their
 * licensing. Red and black follow the French convention every Italian deck is
 * also printed in, so the suit reads instantly.
 */
.card {
  --face: #f6f5f1;
  position: relative; flex: none;
  background: linear-gradient(165deg, var(--face), #ddd9cf);
  color: #17171d; border-radius: .55em;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: .05em; line-height: 1;
  font-family: var(--display); font-weight: 800;
  box-shadow: 0 6px 18px rgba(0, 0, 0, .45), inset 0 1px 0 rgba(255, 255, 255, .7);
  aspect-ratio: 5 / 7.4;
  animation: pop .22s ease both;
}
.card .rank { font-size: 1.5em; }
.card .pip { font-size: 1.25em; }
.card.red { color: #c02644; }
.card.trump { box-shadow: 0 0 0 3px var(--gold), 0 6px 18px rgba(0, 0, 0, .45); }
.card.back {
  background: repeating-linear-gradient(45deg, #2b2b52, #2b2b52 6px, #232343 6px, #232343 12px);
  box-shadow: 0 6px 18px rgba(0, 0, 0, .45);
}
.card .corner { position: absolute; top: .25em; left: .35em; font-size: .7em; opacity: .75; }
.card .pts {
  position: absolute; bottom: .25em; right: .35em;
  font-size: .55em; font-family: var(--text); font-weight: 700;
  color: #7a6a2a;
}

/* --- screen table ------------------------------------------------------ */

.bris {
  flex: 1; display: grid; gap: clamp(.8rem, 2.2vmin, 2rem);
  grid-template-columns: minmax(12rem, 18rem) 1fr;
  align-items: center; min-height: 0;
}
.bris-aside { display: flex; flex-direction: column; gap: clamp(.6rem, 1.6vmin, 1.2rem); }
.bris-trump { display: flex; align-items: center; gap: .9rem; }
.bris-trump .card { height: clamp(5rem, 13vmin, 9rem); font-size: clamp(.7rem, 1.6vmin, 1.2rem); }
.bris-trump .meta { color: var(--ink-dim); font-size: clamp(.75rem, 1.5vmin, 1.1rem); line-height: 1.5; }
.bris-trump .meta b { color: var(--ink); display: block; font-family: var(--display); font-size: 1.25em; }

.bris-seats { display: flex; flex-direction: column; gap: .4rem; }
.bris-seat {
  display: flex; align-items: center; gap: .6em;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-sm); padding: .45em .8em;
  font-size: clamp(.8rem, 1.8vmin, 1.3rem);
}
.bris-seat.turn { border-color: var(--accent); background: var(--surface-2); }
.bris-seat .t1 { color: #7dd3fc; } .bris-seat .t2 { color: #fda4af; }
.bris-seat .n { margin-left: auto; color: var(--ink-mute); font-variant-numeric: tabular-nums; font-size: .85em; }
.bris-seat .sc { font-weight: 700; font-variant-numeric: tabular-nums; }

.bris-table {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: clamp(.7rem, 2vmin, 1.6rem); min-height: 0;
}
.bris-played { display: flex; gap: clamp(.5rem, 1.6vmin, 1.4rem); align-items: flex-end; }
.bris-play { display: flex; flex-direction: column; align-items: center; gap: .5em; }
.bris-play .who { color: var(--ink-dim); font-size: clamp(.7rem, 1.5vmin, 1.1rem); }
.bris-play .card { height: clamp(7rem, 22vmin, 15rem); font-size: clamp(.9rem, 2.4vmin, 2rem); }
.bris-play.winner .card { box-shadow: 0 0 0 3px var(--good), 0 6px 18px rgba(0, 0, 0, .45); }
.bris-play.winner .who { color: var(--good); font-weight: 700; }

/* --- phone hand -------------------------------------------------------- */

.hand { display: flex; gap: .5rem; justify-content: center; align-items: stretch; }
.hand button {
  flex: 1 1 0; max-width: 8rem; padding: 0;
  transition: transform .12s, filter .12s;
}
.hand button .card { height: 100%; width: 100%; font-size: 1.5rem; }
.hand button:disabled { filter: grayscale(.5) brightness(.75); }
.hand button:not(:disabled):active { transform: translateY(-6px) scale(1.03); }
.hand.armed button:not(:disabled) .card { box-shadow: 0 0 0 2px var(--accent), 0 8px 22px rgba(0, 0, 0, .5); }

.trump-mini { display: flex; align-items: center; justify-content: center; gap: .6rem; color: var(--ink-dim); font-size: .9rem; }
.trump-mini .card { height: 3.4rem; font-size: .75rem; }

/* ====================================================================== */
/* Gioco dell'Oca                                                          */
/* ====================================================================== */

/*
 * The real board spirals; a boustrophedon grid keeps the same "snake" reading
 * order while staying legible on a 16:9 screen, which matters more here than
 * imitating the shape.
 */
/*
 * The board is nine columns by seven rows of square cells, so its height is
 * fixed by its width. Sizing it in vh instead of letting it fill the row is what
 * keeps all 63 squares on screen: at 9 columns a full-width board on a 16:9
 * display would run about a third of a screen too tall and silently cut off the
 * last rows -- along with the dice underneath them.
 */
.oca {
  display: grid; grid-template-columns: repeat(9, 1fr);
  gap: clamp(.15rem, .5vmin, .4rem);
  width: min(100%, 68vh);
  margin: 0 auto;
  flex: none; align-content: center;
}
.oca-cell {
  position: relative; aspect-ratio: 1;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: .35em;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  font-size: clamp(.5rem, 1.1vmin, .85rem);
  color: var(--ink-mute);
  overflow: hidden;
}
.oca-cell .num { font-family: var(--display); font-weight: 700; }
.oca-cell.goose { background: rgba(52, 211, 153, .16); border-color: rgba(52, 211, 153, .4); color: var(--good); }
.oca-cell.ponte { background: rgba(56, 189, 248, .16); border-color: rgba(56, 189, 248, .45); }
.oca-cell.osteria, .oca-cell.prigione { background: rgba(251, 191, 36, .16); border-color: rgba(251, 191, 36, .45); }
.oca-cell.pozzo, .oca-cell.labirinto { background: rgba(129, 140, 248, .18); border-color: rgba(129, 140, 248, .45); }
.oca-cell.morte { background: rgba(251, 113, 133, .2); border-color: rgba(251, 113, 133, .5); }
.oca-cell.finish { background: linear-gradient(140deg, rgba(252, 211, 77, .3), rgba(252, 211, 77, .1)); border-color: var(--gold); }
.oca-cell .icon { font-size: 1.5em; line-height: 1; }
.oca-cell .here {
  position: absolute; inset: auto .1em .1em .1em;
  display: flex; gap: .1em; justify-content: center; flex-wrap: wrap;
}
.oca-cell .here .ava {
  width: 1.5em; height: 1.5em; border-radius: 50%;
  display: grid; place-items: center;
  font-family: var(--display); font-weight: 700; font-size: .85em; color: #0b0b12;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, .5);
}

.dice { display: flex; gap: .5rem; justify-content: center; }
.die {
  width: clamp(2.2rem, 6vmin, 4.2rem); aspect-ratio: 1;
  background: linear-gradient(160deg, #f6f5f1, #ddd9cf); color: #17171d;
  border-radius: .22em; display: grid; place-items: center;
  font-family: var(--display); font-weight: 800;
  font-size: clamp(1.2rem, 3.4vmin, 2.4rem);
  box-shadow: 0 6px 18px rgba(0, 0, 0, .45);
  animation: pop .25s ease both;
}
.oca-story { text-align: center; display: flex; flex-direction: column; gap: .5rem; align-items: center; }
.oca-story .ev { color: var(--warn); font-size: clamp(.85rem, 2vmin, 1.5rem); }

.big-roll {
  font-size: 1.3rem; padding: 1.6rem; min-height: 8rem;
  display: flex; flex-direction: column; gap: .4rem; align-items: center; justify-content: center;
}
.big-roll .sub2 { font-size: .85rem; font-weight: 400; opacity: .85; }

/* ====================================================================== */
/* UNO                                                                     */
/* ====================================================================== */

.uno-c0 { --uc: #ef4444; } .uno-c1 { --uc: #eab308; }
.uno-c2 { --uc: #22c55e; } .uno-c3 { --uc: #3b82f6; }
.uno-cw { --uc: #4b5563; }

/* No `--uc` default here on purpose. The colour classes are plain classes too,
   so setting a default on .ucard would win by source order and paint every card
   grey regardless of its suit. The fallback belongs in the var() instead. */
.ucard {
  position: relative; flex: none;
  background: linear-gradient(160deg, var(--uc, #4b5563),
    color-mix(in srgb, var(--uc, #4b5563) 62%, #000));
  border-radius: .5em; aspect-ratio: 5 / 7.4;
  display: grid; place-items: center;
  font-family: var(--display); font-weight: 800; color: #fff;
  border: .18em solid #fbfbfd;
  box-shadow: 0 6px 18px rgba(0, 0, 0, .5);
  animation: pop .22s ease both;
}
.ucard .v { font-size: 1.55em; line-height: 1; text-shadow: 0 2px 0 rgba(0, 0, 0, .35); }
.ucard.wild {
  background:
    conic-gradient(from 45deg, #ef4444 0 25%, #eab308 0 50%, #22c55e 0 75%, #3b82f6 0);
}
.ucard.wild .v { font-size: 1.1em; }
.ucard.dim { filter: grayscale(.75) brightness(.55); }

.uno-table {
  flex: 1; display: flex; align-items: center; justify-content: center;
  gap: clamp(1rem, 4vmin, 3.5rem); flex-wrap: wrap; min-height: 0;
}
.uno-pile { display: flex; flex-direction: column; align-items: center; gap: .7rem; }
.uno-pile .ucard { height: clamp(8rem, 26vmin, 17rem); font-size: clamp(1rem, 3vmin, 2.4rem); }
.uno-colour {
  display: flex; align-items: center; gap: .5em;
  font-size: clamp(.85rem, 2vmin, 1.4rem); color: var(--ink-dim);
}
.uno-colour .dot {
  width: 1.1em; height: 1.1em; border-radius: 50%;
  background: var(--uc); box-shadow: 0 0 14px var(--uc);
}
.uno-seats { display: flex; flex-direction: column; gap: .4rem; min-width: 14rem; }
.uno-seat {
  display: flex; align-items: center; gap: .6em;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-sm); padding: .45em .8em;
  font-size: clamp(.8rem, 1.8vmin, 1.3rem);
}
.uno-seat.turn { border-color: var(--accent); background: var(--surface-2); }
.uno-seat .n { margin-left: auto; color: var(--ink-mute); font-variant-numeric: tabular-nums; }
.uno-seat .uno-badge {
  background: var(--bad); color: #2a0710; font-weight: 800; font-family: var(--display);
  border-radius: 999px; padding: .1em .6em; font-size: .75em; letter-spacing: .1em;
  animation: pulse 1.1s ease-in-out infinite;
}
.uno-dir { text-align: center; color: var(--ink-mute); font-size: clamp(.8rem, 1.7vmin, 1.2rem); }

/* Phone hand: scrolls sideways so seven-plus cards stay tappable. */
.uhand {
  display: flex; gap: .4rem; overflow-x: auto; padding: .3rem .1rem .6rem;
  scrollbar-width: thin;
}
.uhand button { flex: none; width: 4.6rem; padding: 0; transition: transform .12s; }
.uhand button .ucard { width: 100%; height: 6.8rem; font-size: 1.35rem; }
.uhand button:disabled { cursor: default; }
.uhand button:not(:disabled):active { transform: translateY(-6px); }

.uno-actions { display: grid; grid-template-columns: 1fr 1fr; gap: .6rem; }
.colour-pick { display: grid; grid-template-columns: 1fr 1fr; gap: .7rem; }
.colour-pick button {
  min-height: 5.5rem; border-radius: var(--r-md);
  background: var(--uc); color: #08080f;
  font-family: var(--display); font-weight: 800; font-size: 1.15rem;
  box-shadow: 0 8px 22px rgba(0, 0, 0, .4);
}
.colour-pick button:active { transform: scale(.97); }

/* ====================================================================== */
/* Television: scale, measure and motion                                   */
/* ====================================================================== */

/*
 * Everything below is about the big screen being read from a sofa rather than
 * from a desk. Three things were wrong and they are fixed here rather than by
 * editing the rules above, so the base layout stays readable on its own:
 *
 *   1. type was sized for a monitor, leaving a third of a 16:9 screen empty;
 *   2. rows spanned the full width, so a name and its score sat 1500px apart
 *      and the eye had to cross the whole screen to connect them;
 *   3. nothing moved, which is most of what makes a party game feel alive.
 */

.screen h2 { font-size: clamp(1.8rem, 6vmin, 5rem); }
.screen .sub { font-size: clamp(1rem, 2.4vmin, 2rem); }
.screen .quiz-cat { font-size: clamp(.8rem, 1.8vmin, 1.4rem); }
.screen .quiz-q { font-size: clamp(1.7rem, 5.4vmin, 4.4rem); }
.screen .quiz-opt { font-size: clamp(1.1rem, 3vmin, 2.5rem); padding: clamp(.9rem, 2.4vmin, 2rem); }
.screen .prompt { font-size: clamp(1.5rem, 4.6vmin, 3.6rem); }
.screen .answer { font-size: clamp(1rem, 2.6vmin, 2.1rem); }
.screen .chip { font-size: clamp(1rem, 2.4vmin, 1.9rem); }
.screen .game-card h3 { font-size: clamp(1.2rem, 3.2vmin, 2.4rem); }
.screen .game-card p { font-size: clamp(.85rem, 1.9vmin, 1.35rem); }

/* A measure, not a canvas. Long rows of two short values read badly across two
   metres of television; a centred column keeps name and score in one glance. */
.board { max-width: min(100%, 62rem); width: 100%; margin-inline: auto; gap: .5rem; }
.board-row {
  font-size: clamp(1.05rem, 2.8vmin, 2.2rem);
  padding: clamp(.55rem, 1.6vmin, 1.15rem) clamp(.9rem, 2.2vmin, 1.6rem);
}
.board-row .pts { font-size: 1.05em; }
.screen .answers { max-width: min(100%, 74rem); width: 100%; margin-inline: auto; }

.podium-wrap {
  display: flex; flex-direction: column; gap: clamp(.6rem, 1.8vmin, 1.4rem);
  align-items: center; text-align: center;
}

/* The room code is the most important thing on screen right up until somebody
   presses start, and clutter afterwards. It steps aside on its own. */
.screen-head, .screen-head .join .code, .screen-head .join .url {
  transition: font-size .35s ease, opacity .35s ease;
}
body.playing .screen-head { opacity: .45; }
body.playing .screen-head .join .code { font-size: clamp(1.1rem, 2.4vmin, 2rem); }
body.playing .screen-head .join .url { opacity: 0; }

/* --- motion ------------------------------------------------------------ */

@keyframes dealIn {
  from { opacity: 0; transform: translateY(-38px) rotate(-7deg) scale(.9); }
  to   { opacity: 1; transform: none; }
}
@keyframes flipUp {
  from { opacity: 0; transform: translateY(16px) scale(.86); }
  to   { opacity: 1; transform: none; }
}
@keyframes trail {
  0%   { background: rgba(129, 140, 248, .55); transform: scale(1.08); }
  100% { background: var(--surface); transform: none; }
}
@keyframes land {
  0%   { transform: scale(1); }
  45%  { transform: scale(1.22); }
  100% { transform: scale(1); }
}
@keyframes turnGlow {
  0%, 100% { box-shadow: 0 0 0 1px rgba(129, 140, 248, .35); }
  50%      { box-shadow: 0 0 22px 2px rgba(129, 140, 248, .55); }
}

/* Cards arrive one after another instead of appearing all at once. */
.bris-play { animation: dealIn .34s cubic-bezier(.2, .9, .3, 1.2) both; }
.bris-play:nth-child(2) { animation-delay: .08s; }
.bris-play:nth-child(3) { animation-delay: .16s; }
.bris-play:nth-child(4) { animation-delay: .24s; }

.hand button { animation: flipUp .3s ease both; }
.hand button:nth-child(2) { animation-delay: .06s; }
.hand button:nth-child(3) { animation-delay: .12s; }
.uhand button { animation: flipUp .26s ease both; }

.bris-seat.turn, .uno-seat.turn { animation: turnGlow 2s ease-in-out infinite; }

.oca-cell.trail { animation: trail .5s ease both; }
.oca-cell.landed { animation: land .5s cubic-bezier(.2, .9, .3, 1.4) both; }
.oca-cell .here .ava { transition: transform .25s; }

.die { animation: dealIn .3s cubic-bezier(.2, .9, .3, 1.3) both; }
.die:nth-child(2) { animation-delay: .07s; }

/* Numbers that climb rather than snap. The value is written by JS; this only
   keeps the digits from jittering as the width changes. */
.count-up { font-variant-numeric: tabular-nums; }

/* The avatar was only styled inside .chip, so the same node came out as a
   rounded square anywhere else it was reused. Base rule, overridden where a
   different size is wanted. */
.ava {
  width: 1.9em; height: 1.9em; border-radius: 50%;
  display: grid; place-items: center;
  font-family: var(--display); font-weight: 700; font-size: .8em;
  color: #0b0b12; flex: none; line-height: 1;
}
.board-row .ava { font-size: .78em; }

/* ====================================================================== */
/* Login (screen side only)                                                */
/* ====================================================================== */

.login {
  display: flex; flex-direction: column; gap: 1rem;
  width: min(100%, 24rem); text-align: left;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: 1.8rem;
  box-shadow: var(--shadow);
}
.login .hint { color: var(--ink-dim); font-size: .92rem; line-height: 1.55; }
.landing .quiet { color: var(--ink-mute); text-decoration: none; font-size: .9rem; background: none; border: none; box-shadow: none; padding: 0; min-width: 0; }
.landing .quiet:hover { color: var(--ink-dim); transform: none; background: none; border: none; }

/* ====================================================================== */
/* Join panel: the QR the players scan                                     */
/* ====================================================================== */

.join-panel {
  display: grid; grid-template-columns: auto 1fr; gap: clamp(1.2rem, 3.5vmin, 3rem);
  align-items: center; justify-content: center;
}
@media (max-width: 900px) { .join-panel { grid-template-columns: 1fr; } }

/* The quiet zone is padding on a white card: scanners need the light margin,
   and drawing it here means the matrix itself stays exactly the modules. */
.qr {
  background: #fff; padding: clamp(.6rem, 1.6vmin, 1.1rem);
  border-radius: .5rem; line-height: 0;
  box-shadow: 0 12px 40px rgba(0, 0, 0, .5);
  animation: pop .3s ease both;
}
.qr svg { display: block; width: clamp(12rem, 36vmin, 26rem); height: auto; }

.join-info { display: flex; flex-direction: column; gap: clamp(.5rem, 1.6vmin, 1.2rem); }
.join-info .label { color: var(--ink-mute); letter-spacing: .22em; text-transform: uppercase; font-size: clamp(.7rem, 1.5vmin, 1.05rem); font-weight: 600; }
.join-info .bigcode {
  font-family: var(--display); font-weight: 800; line-height: 1;
  font-size: clamp(3rem, 11vmin, 9rem); letter-spacing: .1em;
  background: linear-gradient(120deg, #a5b4fc, #f0abfc);
  -webkit-background-clip: text; background-clip: text; color: transparent;
  filter: drop-shadow(0 0 30px rgba(168, 85, 247, .4));
}
.join-info .where { color: var(--ink-dim); font-size: clamp(.9rem, 2.1vmin, 1.6rem); }
.join-info .where b { color: var(--ink); font-weight: 600; }

/* The screen is driven with a mouse or a remote, so its buttons need hover and
   focus states the television-only views never needed. */
.screen-actions { display: flex; gap: .8rem; flex-wrap: wrap; align-items: center; }
.sbtn {
  font-family: var(--display); font-weight: 700;
  font-size: clamp(.95rem, 2.1vmin, 1.5rem);
  padding: .7em 1.4em; border-radius: var(--r-md);
  background: linear-gradient(135deg, var(--brand-a), var(--brand-b)); color: #fff;
  box-shadow: 0 8px 24px rgba(99, 102, 241, .3);
  transition: transform .1s, filter .15s, opacity .15s;
}
.sbtn:hover:not(:disabled) { filter: brightness(1.12); transform: translateY(-2px); }
.sbtn:active:not(:disabled) { transform: translateY(0); }
.sbtn:disabled { opacity: .35; box-shadow: none; cursor: default; }
.sbtn.ghost { background: var(--surface); border: 1px solid var(--line); box-shadow: none; color: var(--ink); }
.sbtn.ghost:hover { background: var(--surface-2); }

.game-card.pickable { cursor: pointer; text-align: left; width: 100%; }
.game-card.pickable:hover:not(:disabled) { border-color: var(--line-2); background: var(--surface-2); transform: translateY(-3px); }
.game-card.pickable:disabled { cursor: default; }
.game-card { transition: border-color .2s, background .2s, transform .18s; }

.who-bar {
  display: flex; align-items: center; gap: .6em;
  color: var(--ink-mute); font-size: clamp(.75rem, 1.5vmin, 1.1rem);
}
.who-bar a { color: var(--ink-mute); text-decoration: none; border-bottom: 1px solid currentColor; }
.who-bar a:hover { color: var(--ink-dim); }

/* The join screen is the one moment when the whole television says one thing.
   Centre it, and drop the duplicate code out of the corner. */
body.joining .screen-head .join { opacity: 0; }
.screen-body.joining { align-items: center; text-align: center; }
.screen-body.joining .join-panel { text-align: left; }
.screen-body.joining .roster { justify-content: center; }

/* ====================================================================== */
/* Camera scanner                                                          */
/* ====================================================================== */

.scanner {
  position: fixed; inset: 0; z-index: 50;
  background: #000;
  display: grid; place-items: center;
}
.scanner video {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}
/* Only the middle of the frame is decoded, so the reticle is a promise the
   code keeps rather than decoration. */
.scanner .reticle {
  position: relative;
  width: min(72vw, 72vh); aspect-ratio: 1;
  border-radius: 1.5rem;
  box-shadow: 0 0 0 100vmax rgba(0, 0, 0, .55);
  outline: 2px solid rgba(255, 255, 255, .9);
  outline-offset: -2px;
}
.scanner .scan-hint {
  position: absolute; left: 0; right: 0; top: max(1.5rem, env(safe-area-inset-top));
  text-align: center; color: #fff; font-weight: 600;
  text-shadow: 0 2px 8px rgba(0, 0, 0, .8);
}
.scanner .scan-cancel {
  position: absolute; left: 50%; transform: translateX(-50%);
  bottom: max(2rem, env(safe-area-inset-bottom));
  background: rgba(255, 255, 255, .16); color: #fff;
  border: 1px solid rgba(255, 255, 255, .3);
  padding: .8em 2.2em; border-radius: 999px; font-weight: 600;
  backdrop-filter: blur(8px);
}

.hint.or {
  text-align: center; color: var(--ink-mute);
  text-transform: uppercase; letter-spacing: .2em; font-size: .72rem;
  margin: .2rem 0;
}

/* Small and out of the way: leaving is rare, and a mis-tap costs the seat. */
.leave {
  color: var(--ink-mute); font-size: .8rem;
  border: 1px solid var(--line); border-radius: 999px;
  padding: .35em 1em; margin-left: .5rem;
}
.leave.armed { color: #fca5a5; border-color: #7f1d1d; background: rgba(127, 29, 29, .25); }

/* renderJoin leaves the header empty; without this the empty pill still draws. */
.play-head:empty { display: none; }
