/* Play XO - "Across the table".
   The far side of the table (marigold) belongs to the other player and holds the
   invitation; the near side (paper) is yours and holds the board. Seats are the motif.
   The table is one centred column the width of the board on every screen: the far
   seat and the invitation over the board, your seat and the score under it. */

@font-face {
  font-family: Rubik;
  src: url(/rubik-latin-var.woff2) format('woff2');
  font-weight: 300 900;
  font-display: swap;
}
@font-face {
  font-family: 'Rubik Fallback';
  src: local('Arial'), local('Helvetica');
  size-adjust: 97.8%;
  ascent-override: 95.6%;
  descent-override: 25.6%;
  line-gap-override: 0%;
}

:root {
  color-scheme: light dark;
  /* surfaces */
  --paper: #ffffff;
  --tint: #f4f1ea;
  --tint-2: #e9e5dc;
  --line: #e3dfd6;
  /* the last move: one tint for every board (a tile, a square, a point) */
  --last-bg: var(--tint-2);
  /* text */
  --ink: #1f1d1b;
  --ink-2: #4a4640;
  --muted: #6b665f;
  /* the far side of the table: fixed in both schemes */
  --table: #ffc83d;
  --table-ink: #1f1d1b;
  --table-ink-2: #4a4640;
  --table-line: rgba(31, 29, 27, 0.62);
  --table-glass: rgba(255, 255, 255, 0.55);
  /* pieces */
  --x: #d81b60;
  --o: var(--ink);
  --bot: #8f8a83;
  --online: #1a7f4b;
  /* controls */
  --btn: var(--ink);
  --btn-fg: #ffffff;
  --btn-hover: #38352f;
  --cell: var(--paper);
  --hash: var(--ink);
  --tile-shadow: 0 1px 0 rgba(31, 29, 27, 0.06), 0 8px 18px -10px rgba(31, 29, 27, 0.35);
  --pop-shadow: 0 1px 0 rgba(31, 29, 27, 0.06), 0 16px 32px -12px rgba(31, 29, 27, 0.45);
  /* shape, rhythm, motion */
  --r-2xs: 3px;
  --r-xs: 6px;
  --r-s: 8px;
  --r: 12px;
  --r-l: 16px;
  --gap: 8px;
  /* line weights shared by every board: --lw is the big hash (6/7/8 by breakpoint),
     --lw-s the inner lattice and the hairline between small tiles */
  --lw: 6px;
  --lw-s: 2px;
  --overlap: 112px;
  --ease: cubic-bezier(0.2, 0.7, 0.2, 1);
  --fast: 150ms;
  --med: 240ms;
  --font: Rubik, 'Rubik Fallback', Arial, sans-serif;
}

@media (prefers-color-scheme: dark) {
  :root {
    --paper: #1b1a18;
    --tint: #262420;
    --tint-2: #3a362f;
    --line: #3d3a35;
    --ink: #f3efe8;
    --ink-2: #cfc9bf;
    --muted: #a8a39c;
    --x: #ff5c8f;
    --bot: #8f8a83;
    --online: #4cc47f;
    --btn: #f3efe8;
    --btn-fg: #1b1a18;
    --btn-hover: #ffffff;
    --cell: #2e2b26;
    /* the hash crosses the band edge: a warm mid grey that holds 3:1 on marigold and on the dark cell */
    --hash: #7a746b;
    --tile-shadow: 0 1px 0 rgba(0, 0, 0, 0.35), 0 8px 18px -10px rgba(0, 0, 0, 0.7);
    --pop-shadow: 0 1px 0 rgba(0, 0, 0, 0.35), 0 16px 32px -12px rgba(0, 0, 0, 0.8);
  }
}

/* ---------- base ---------- */
*,
*::before,
*::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font: 400 16px/1.5 var(--font);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}
main { flex: 1 0 auto; }
[hidden] { display: none !important; }
.sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
a { color: inherit; }
button { font: inherit; touch-action: manipulation; -webkit-tap-highlight-color: transparent; }
/* the ring follows the element's own radius; nothing changes shape on focus */
:focus-visible { outline: 3px solid var(--ink); outline-offset: 3px; }
.far :focus-visible { outline-color: var(--table-ink); }

.wrap { width: min(100% - 40px, 1080px); margin-inline: auto; }

h1 {
  margin: 0;
  font-size: 28px;
  line-height: 1.12;
  font-weight: 700;
  letter-spacing: -0.015em;
  text-wrap: balance;
}
p { margin: 0; }

/* ---------- the far side (marigold) ---------- */
.top,
.far {
  /* the far side is always lit the same way, whatever the scheme */
  --paper: #ffffff;
  --tint: #f4f1ea;
  --tint-2: #e9e5dc;
  --line: #e3dfd6;
  --ink: #1f1d1b;
  --ink-2: #4a4640;
  --muted: #6b665f;
  --x: #d81b60;
  --o: #1f1d1b;
  --bot: #8f8a83;
  --btn: #1f1d1b;
  --btn-fg: #ffffff;
  --btn-hover: #38352f;
  background: var(--table);
  color: var(--table-ink);
}
.top { flex: none; }
.top .wrap { display: flex; align-items: center; justify-content: space-between; gap: 16px; height: 56px; }
.brand {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-weight: 700;
  font-size: 18px;
  letter-spacing: -0.01em;
  text-decoration: none;
  color: var(--table-ink);
  height: 44px;
}
.brand .tok:first-of-type { margin-left: 4px; }
.room-tag {
  font-size: 14px;
  font-weight: 500;
  color: var(--table-ink-2);
  background: var(--table-glass);
  padding: 4px 10px;
  border-radius: var(--r-s);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.room-tag strong { color: var(--table-ink); font-weight: 600; }

.far { padding: 8px 0 calc(var(--overlap) + 20px); }
.far-grid { display: grid; gap: 16px; }
.lead { margin-top: 6px; font-size: 16px; line-height: 1.45; color: var(--table-ink-2); max-width: 40ch; }

.invite { display: grid; gap: 10px; }
.hint { font-size: 14px; line-height: 1.4; color: var(--table-ink-2); text-wrap: pretty; max-width: 38ch; }
.hint.alert { color: var(--table-ink); font-weight: 600; }
.chip {
  display: inline-block;
  background: var(--table-glass);
  color: var(--table-ink);
  padding: 0 6px;
  border-radius: var(--r-xs);
  font-weight: 600;
  white-space: nowrap;
}
/* live room: the far side's note when the friend has dropped */
.far-aside { display: grid; gap: 8px; justify-items: start; }
.far-aside .btn { width: auto; height: 44px; font-size: 16px; padding: 0 18px; }

/* ---------- tokens: X and O drawn in CSS, reused at every size ---------- */
.tok { display: inline-block; width: 22px; height: 22px; position: relative; flex: none; }
.tok-x::before,
.tok-x::after {
  content: '';
  position: absolute;
  inset: 0;
  margin: auto;
  width: 100%;
  height: 22%;
  border-radius: 99px;
  background: var(--x);
  transform: rotate(45deg);
}
.tok-x::after { transform: rotate(-45deg); }
.tok-o::before {
  content: '';
  position: absolute;
  inset: 0;
  margin: auto;
  width: 86%;
  height: 86%;
  border: 5px solid var(--table-ink);
  border-radius: 50%;
}

/* ---------- seats: the motif ---------- */
.seat {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 52px;
  padding: 8px 12px;
  border: 2px solid transparent;
  border-radius: var(--r);
  background: var(--paper);
  color: var(--ink);
  transition: box-shadow var(--med) var(--ease), background-color var(--med) var(--ease);
}
.far .seat { background: var(--paper); }
.seat-near { background: var(--tint); }
.seat-mark { width: 28px; height: 28px; position: relative; flex: none; }
.seat-who { display: flex; flex-direction: column; min-width: 0; line-height: 1.25; }
.seat-name { font-weight: 600; }
.seat-note { font-size: 14px; color: var(--muted); }
.seat-note.is-lit { color: var(--ink); font-weight: 600; }
.seat-sub { font-weight: 400; color: var(--muted); }
/* X mark */
.seat[data-mark='X'] { --ring: var(--x); }
.seat[data-mark='X'] .seat-mark::before,
.seat[data-mark='X'] .seat-mark::after {
  content: '';
  position: absolute;
  inset: 0;
  margin: auto;
  width: 100%;
  height: 21%;
  border: 0;
  border-radius: 99px;
  background: var(--x);
  transform: rotate(45deg);
}
.seat[data-mark='X'] .seat-mark::after { transform: rotate(-45deg); }
/* O mark */
.seat[data-mark='O'] { --ring: var(--o); }
.seat[data-mark='O'] .seat-mark::before {
  content: '';
  position: absolute;
  inset: 0;
  margin: auto;
  width: 84%;
  height: 84%;
  border: 6px solid var(--o);
  border-radius: 50%;
  background: none;
  transform: none;
}
.seat[data-mark='O'] .seat-mark::after { content: none; }
/* grey marks: the bot, and a friend who dropped the connection */
.seat.is-bot[data-mark='O'] .seat-mark::before,
.seat.is-offline[data-mark='O'] .seat-mark::before { border-color: var(--bot); }
.seat.is-bot[data-mark='X'] .seat-mark::before,
.seat.is-bot[data-mark='X'] .seat-mark::after,
.seat.is-offline[data-mark='X'] .seat-mark::before,
.seat.is-offline[data-mark='X'] .seat-mark::after { background: var(--bot); }
/* empty or abandoned seat: dashed outline on the table */
.seat.is-empty,
.seat.is-offline {
  background: transparent;
  border-style: dashed;
  border-color: var(--table-line);
  color: var(--table-ink);
}
.seat.is-empty .seat-note,
.seat.is-offline .seat-note { color: var(--table-ink-2); }
.seat.is-empty[data-mark='O'] .seat-mark::before { border-color: var(--table-line); }
.seat.is-empty[data-mark='X'] .seat-mark::before,
.seat.is-empty[data-mark='X'] .seat-mark::after { background: var(--table-line); }
.seat-row { display: grid; gap: 8px; }

/* whose move: the seat to move is ringed in its own colour and its plate darkens a step;
   the note under the name says "Your move" / "Their move" (app.ts). Focus stays a 3px
   outline with an offset, so the two never look alike. */
#live[data-turn='you'] .seat-near,
#live[data-turn='friend'] .seat-far { box-shadow: inset 0 0 0 2px var(--ring); background: var(--tint-2); }

/* waiting pulse */
.is-waiting::before {
  content: '';
  display: inline-block;
  width: 8px;
  height: 8px;
  margin-right: 6px;
  border-radius: 50%;
  background: currentColor;
  vertical-align: 1px;
  animation: pulse 1.6s ease-in-out infinite;
}
@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.25; }
}

/* presence dot on the friend's seat */
.presence { font-weight: 600; display: flex; align-items: center; gap: 8px; }
.presence::before {
  content: '';
  width: 10px;
  height: 10px;
  border-radius: 50%;
  border: 2px solid var(--muted);
  flex: none;
}
.presence.is-online::before { background: var(--online); border-color: var(--online); }

/* ---------- the near side (paper) and the board ---------- */
.near { margin-top: calc(-1 * var(--overlap)); padding-bottom: 32px; }
.near-grid { display: grid; gap: 16px; }
.play { display: grid; gap: 8px; }
.status {
  min-height: 1.4em;
  font-size: 17px;
  line-height: 1.35;
  font-weight: 600;
  color: var(--table-ink);
}
.near-side { display: grid; gap: 12px; align-content: start; }
.score {
  font-size: 15px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  padding: 0 4px;
}

.board {
  position: relative;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--gap);
  width: min(100%, 340px);
  /* space reserved before the script builds the tiles: no layout shift */
  aspect-ratio: 1;
  container-type: inline-size;
}
/* the hash: four inner lines, no outer frame */
.board::before,
.board::after {
  content: '';
  position: absolute;
  inset: 2% 0;
  pointer-events: none;
  --c: calc((100cqw - 2 * var(--gap)) / 3);
  background-image: linear-gradient(var(--hash), var(--hash)), linear-gradient(var(--hash), var(--hash));
  background-repeat: no-repeat;
}
.board::before {
  background-size: var(--lw) 100%;
  background-position:
    calc(var(--c) + var(--gap) / 2 - var(--lw) / 2) 0,
    calc(2 * var(--c) + 1.5 * var(--gap) - var(--lw) / 2) 0;
}
.board::after {
  inset: 0 2%;
  background-size: 100% var(--lw);
  background-position:
    0 calc(var(--c) + var(--gap) / 2 - var(--lw) / 2),
    0 calc(2 * var(--c) + 1.5 * var(--gap) - var(--lw) / 2);
}
.cell {
  position: relative;
  aspect-ratio: 1;
  padding: 0;
  border: 0;
  border-radius: var(--r);
  background: var(--cell);
  color: var(--ink);
  box-shadow: var(--tile-shadow);
  cursor: pointer;
  transition: background-color var(--med) var(--ease), box-shadow var(--med) var(--ease), transform var(--fast) var(--ease), opacity var(--med) var(--ease);
}
.cell:disabled { cursor: default; }
.cell:enabled:hover { background: var(--tint); }
.cell:enabled:active { transform: scale(0.96); }
/* not your move: the tiles sit flat on the table */
.board.is-locked .cell { background: var(--tint); box-shadow: none; }
.cell::before,
.cell::after { content: ''; position: absolute; inset: 0; margin: auto; opacity: 0; }
.cell[data-mark='X']::before,
.cell[data-mark='X']::after {
  opacity: 1;
  width: 19cqw;
  height: 4.6cqw;
  border-radius: 99px;
  background: var(--x);
  transform: rotate(45deg);
  animation: pop-x var(--med) var(--ease) both;
}
.cell[data-mark='X']::after { transform: rotate(-45deg); animation-name: pop-x2; }
.cell[data-mark='O']::before {
  opacity: 1;
  width: 17.5cqw;
  height: 17.5cqw;
  border: 4.6cqw solid var(--o);
  border-radius: 50%;
  animation: pop-o var(--med) var(--ease) both;
}
/* the bot's marks are grey: colour is for people. Every game repeats this for its
   own second mark under .board.vs-bot (the bot always takes seat 1). */
.board.vs-bot .cell[data-mark='O']::before { border-color: var(--bot); }
/* ghost of your mark on hover (pointer devices only) */
@media (hover: hover) and (pointer: fine) {
  .cell:enabled:not([data-mark='X']):not([data-mark='O']):hover::before,
  .cell:enabled:not([data-mark='X']):not([data-mark='O']):hover::after {
    opacity: 0.22;
    width: 19cqw;
    height: 4.6cqw;
    border-radius: 99px;
    background: var(--x);
    transform: rotate(45deg);
  }
  .cell:enabled:not([data-mark='X']):not([data-mark='O']):hover::after { transform: rotate(-45deg); }
  [data-you='O'] .cell:enabled:not([data-mark='X']):not([data-mark='O']):hover::before {
    width: 17.5cqw;
    height: 17.5cqw;
    background: none;
    border: 4.6cqw solid var(--o);
    border-radius: 50%;
    transform: none;
  }
  [data-you='O'] .cell:enabled:not([data-mark='X']):not([data-mark='O']):hover::after { opacity: 0; }
}
.cell.is-last,
.board.is-locked .cell.is-last { background: var(--last-bg); }
/* the winning line becomes solid tiles in the winner's colour; the rest fades */
.cell.is-win[data-mark='X'] { background: var(--x); }
.cell.is-win[data-mark='X']::before,
.cell.is-win[data-mark='X']::after { background: #ffffff; }
.cell.is-win[data-mark='O'] { background: var(--o); }
.cell.is-win[data-mark='O']::before { border-color: var(--paper); }
.board.vs-bot .cell.is-win[data-mark='O'] { background: var(--bot); }
.board.vs-bot .cell.is-win[data-mark='O']::before { border-color: #ffffff; }
.board.is-over .cell:not(.is-win)::before,
.board.is-over .cell:not(.is-win)::after { opacity: 0.4; }
.board.is-over .cell.is-win { transform: scale(1.04); }
@keyframes pop-x {
  from { opacity: 0; transform: rotate(45deg) scale(0.4); }
}
@keyframes pop-x2 {
  from { opacity: 0; transform: rotate(-45deg) scale(0.4); }
}
@keyframes pop-o {
  from { opacity: 0; transform: scale(0.4); }
}

/* ---------- buttons and inputs ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 56px;
  padding: 0 24px;
  border: 0;
  border-radius: var(--r);
  font-weight: 600;
  font-size: 18px;
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
  width: 100%;
  transition: background-color var(--fast) var(--ease), transform var(--fast) var(--ease);
}
.btn:active { transform: translateY(1px); }
.btn:disabled { cursor: default; opacity: 0.6; transform: none; }
.btn-primary { background: var(--btn); color: var(--btn-fg); }
.btn-primary:hover:enabled { background: var(--btn-hover); }
.btn-secondary { background: transparent; color: var(--ink); border: 2px solid var(--muted); height: 48px; font-size: 16px; }
.btn-secondary:hover:enabled { background: var(--tint); }
.far .btn-secondary { color: var(--table-ink); border-color: var(--table-line); }
.far .btn-secondary:hover:enabled { background: var(--table-glass); }
/* the small button: turn controls under a board, account actions, the consent plate */
.btn-small { height: 44px; padding: 0 16px; font-size: 14px; }
/* the friend asked for a rematch: the button asks back */
.btn.is-nudge { animation: nudge 1.4s var(--ease) infinite; }
@keyframes nudge {
  0%, 100% { transform: none; }
  50% { transform: scale(1.03); }
}

.linkbox { display: grid; gap: 8px; grid-template-columns: 1fr; }
.linkbox input {
  width: 100%;
  min-width: 0;
  height: 56px;
  padding: 0 16px;
  border: 0;
  border-radius: var(--r);
  background: var(--paper);
  color: var(--ink);
  font: 600 17px/1 var(--font);
  letter-spacing: 0.005em;
  text-overflow: ellipsis;
}
.linkbox input::selection { background: var(--table); color: var(--table-ink); }
.linkbox-actions { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 8px; }
.linkbox .btn { margin: 0; }
.linkbox .btn-secondary { height: 56px; font-size: 18px; }

/* ---------- notices (full room, gone room, 404) ---------- */
.notice .far { padding-bottom: 40px; }
.notice .near { margin-top: 0; padding-top: 28px; display: grid; gap: 28px; }
.notice-text { display: grid; gap: 20px; justify-items: start; }
.notice p { max-width: 44ch; }
.notice .btn { width: auto; }
.board.lonely {
  width: min(100%, 220px);
  --gap: 6px;
  --lw: 4px;
}
.lonely .cell { box-shadow: none; background: var(--tint); cursor: default; }
.lonely .cell[data-mark='X']::before,
.lonely .cell[data-mark='X']::after { animation: none; background: var(--bot); }
.lonely .cell[data-mark='O']::before { animation: none; border-color: var(--bot); }

/* ---------- footer ---------- */
.foot { color: var(--muted); font-size: 14px; padding: 24px 0 calc(24px + env(safe-area-inset-bottom)); }
.foot a { text-decoration: none; font-weight: 500; }
.foot a:hover { text-decoration: underline; }

/* ---------- wider screens: the same table, larger, with air ----------
   One centred column the width of the board carries the whole table: head, the far
   seat and the invitation stand over the board on the marigold side, your seat, the
   score and the rematch sit under it on the paper side. The board stays centred on
   every screen; only the list of games below spreads to the full width. */
@media (min-width: 640px) {
  h1 { font-size: 32px; }
  .status { font-size: 18px; }
  .far { padding-top: 16px; }
  .far-grid,
  .near-grid,
  .notice .near { width: min(100% - 40px, 480px); }
  .far-grid { row-gap: 20px; }
  .near-grid { row-gap: 20px; }
  /* the column is wide enough for the hint to run on one line */
  .invite .hint { max-width: none; }
  /* the two empty or taken seats of a notice sit side by side across the table */
  .notice .far-grid > .seat-row { grid-template-columns: 1fr 1fr; }
  /* boards narrower than the column (Connect Four, Dots) stay on the table's axis */
  .board { width: 100%; margin-inline: auto; --gap: 10px; --lw: 7px; }
  .btn { width: auto; min-width: 200px; }
  .invite .btn,
  .near-side .btn { width: 100%; }
  .linkbox { grid-template-columns: 1fr auto; }
  .linkbox-actions { grid-auto-columns: auto; }
  .linkbox .btn { min-width: 0; padding: 0 20px; }
  .notice .near { grid-template-columns: 200px minmax(0, 1fr); column-gap: 32px; align-items: center; }
  .notice .near .lonely { grid-column: 1; grid-row: 1; width: 100%; }
  .notice .near .notice-text { grid-column: 2; grid-row: 1; }
}
@media (min-width: 960px) {
  :root { --overlap: 160px; }
  /* 36px keeps most titles on one line in the board-wide column */
  h1 { font-size: 36px; letter-spacing: -0.02em; }
  .lead { font-size: 17px; margin-top: 10px; }
  .far { padding-top: 24px; }
  .far-grid { row-gap: 24px; }
  .board { --gap: 10px; --lw: 8px; }
  .status { font-size: 20px; }
  .cell { border-radius: var(--r-l); }
}

/* ---------- motion ---------- */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after { animation: none !important; transition: none !important; }
  .is-waiting::before { opacity: 1; }
}

.near .hint { color: var(--muted); }
.note { min-height: 1.4em; }

/* ---------- account widget in the header (every page) ---------- */
.nav-user { margin-left: auto; display: flex; align-items: center; min-width: 0; }
.nav-link {
  display: inline-flex;
  align-items: center;
  height: 44px;
  padding: 0 14px;
  border-radius: var(--r-s);
  background: var(--table-glass);
  color: var(--table-ink);
  font-size: 14px;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
  max-width: 40vw;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: background-color var(--fast) var(--ease);
}
.nav-link:hover { background: #ffffff; }
.nav-user + .room-tag { margin-left: -8px; }

/* ---------- badge toasts: the reward lands on the table ---------- */
.toasts {
  position: fixed;
  left: 16px;
  right: 16px;
  bottom: calc(16px + env(safe-area-inset-bottom));
  z-index: 50;
  display: grid;
  gap: 8px;
  pointer-events: none;
}
.toast {
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px 12px 12px;
  border-radius: var(--r);
  background: var(--cell);
  color: var(--ink);
  box-shadow: var(--pop-shadow);
  animation: toast-in var(--med) var(--ease) both;
  transition: opacity var(--med) var(--ease), transform var(--med) var(--ease);
}
.toast-emoji {
  flex: none;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--table);
  font-size: 22px;
  line-height: 1;
}
.toast-emoji:empty { display: none; }
.toast-body { display: grid; gap: 2px; min-width: 0; }
.toast strong { font-size: 15px; line-height: 1.3; font-weight: 600; }
.toast-text { font-size: 14px; line-height: 1.35; color: var(--muted); }
.toast.is-out { opacity: 0; transform: translateY(8px); }
@keyframes toast-in {
  from { opacity: 0; transform: translateY(12px); }
}
@media (min-width: 640px) {
  .toasts { left: auto; right: 24px; bottom: 24px; width: 360px; }
}

/* after a game without an account: one line, the far side's invitation visiting your side */
.nudge { margin: 4px 0 0; padding: 6px 12px; border-left: 3px solid var(--table); font-size: 14px; line-height: 1.4; }
.nudge a { color: var(--ink); font-weight: 600; text-underline-offset: 3px; }

/* Плашка согласия на аналитику (только ЕЭЗ/UK/CH) */
.consent { position: fixed; left: 12px; right: 12px; bottom: 12px; z-index: 60; margin: 0 auto; max-width: 560px; background: var(--ink); color: var(--paper); border-radius: var(--r); padding: 14px 16px; box-shadow: var(--pop-shadow); display: grid; gap: 10px; }
.consent p { margin: 0; font-size: 14px; line-height: 1.4; }
.consent-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.consent-actions a { color: inherit; font-size: 13px; margin-left: auto; }
.consent .btn-primary { background: var(--table); color: var(--table-ink); }
.consent .btn-secondary { background: transparent; color: inherit; border-color: color-mix(in srgb, currentColor 50%, transparent); }

/* ---------- tokens for games without X and O ----------
   app.ts sets --seat-color from meta.colors and --seat-ring (the colour, or ink when the
   colour is too light to ring a plate: White, Yellow). Every disc wears a rim mixed from
   its own colour and ink, so a white disc reads on a white plate and a black one on dark paper. */
.seat:not([data-mark='X']):not([data-mark='O']) { --ring: var(--seat-ring, var(--seat-color, var(--ink))); }
.seat:not([data-mark='X']):not([data-mark='O']) .seat-mark::before {
  content: '';
  position: absolute;
  inset: 3px;
  border-radius: 50%;
  background: var(--seat-color, var(--ink));
  box-shadow: inset 0 -3px 0 rgba(0, 0, 0, 0.18), 0 0 0 1.5px color-mix(in srgb, var(--seat-color, var(--ink)) 60%, var(--ink));
}
.seat.is-bot:not([data-mark='X']):not([data-mark='O']) .seat-mark::before,
.seat.is-offline:not([data-mark='X']):not([data-mark='O']) .seat-mark::before { background: var(--bot); box-shadow: inset 0 -3px 0 rgba(0, 0, 0, 0.18); }
.seat.is-empty:not([data-mark='X']):not([data-mark='O']) .seat-mark::before { background: transparent; box-shadow: inset 0 0 0 3px var(--table-line); }

/* ---------- shared board furniture ---------- */
/* the count strip under Reversi and Dots: a disc per seat, tabular figures */
.tally {
  display: flex;
  gap: 18px;
  padding: 0 4px;
  font-size: 14px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.tally-count { display: inline-flex; align-items: center; gap: 7px; }
.tally-count::before {
  content: '';
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--c, var(--ink));
  box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.18), 0 0 0 1px color-mix(in srgb, var(--c, var(--ink)) 60%, var(--ink));
}
.board.vs-bot .tally-count:nth-child(2)::before { background: var(--bot); box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.18); }
.tally-count.is-winner { color: var(--ink); font-weight: 600; }
/* the line under a board that needs two taps on a phone ("Tap again to place") */
.board-hint { min-height: 1.4em; font-size: 14px; line-height: 1.4; color: var(--muted); padding: 0 4px; }
.board-hint.is-lit { color: var(--ink); font-weight: 600; }

/* ---------- the list of games ---------- */
.games-section { padding: 28px 0 40px; }
.games-section h2 { margin: 0 0 12px; font-size: 18px; }
.games { display: grid; grid-template-columns: 1fr; gap: 10px; }
.game-link {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 2px 12px;
  align-items: start;
  padding: 12px 14px;
  border-radius: var(--r);
  background: var(--tint);
  color: var(--ink);
  text-decoration: none;
  transition: background-color var(--fast) var(--ease);
}
.game-link:hover { background: var(--tint-2); }
.game-link.is-current { background: var(--table); color: var(--table-ink); }
.game-link.is-current .game-tag { color: var(--table-ink-2); }
/* the two pieces of the game, drawn like the seat tokens */
.game-mark { grid-row: span 2; display: flex; align-items: center; height: 24px; margin-top: 0; }
.game-mark .tok { width: 14px; height: 14px; }
.game-mark .tok + .tok { margin-left: 3px; }
.game-mark .tok-o::before { border-width: 3px; border-color: var(--o); }
.game-link.is-current .tok-o::before { border-color: var(--table-ink); }
.game-tok {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--c);
  box-shadow: inset 0 -2px 0 rgba(0, 0, 0, 0.18), 0 0 0 1.5px color-mix(in srgb, var(--c) 60%, var(--ink));
}
.game-tok + .game-tok { margin-left: -4px; }
.game-link.is-current .game-tok { box-shadow: inset 0 -2px 0 rgba(0, 0, 0, 0.18), 0 0 0 1.5px color-mix(in srgb, var(--c) 60%, var(--table-ink)); }
.game-name { font-weight: 700; line-height: 1.3; }
.game-tag { font-size: 13px; line-height: 1.4; color: var(--muted); }
@media (min-width: 480px) { .games { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 960px) { .games { grid-template-columns: repeat(3, 1fr); } }

/* Шапка комнаты на узких экранах: название игры прячется, остаётся код комнаты;
   имя пользователя не должно выдавливать код за край */
@media (max-width: 480px) {
  #room-game { display: none; }
  .room-tag { white-space: nowrap; }
  [data-page='room'] .nav-link { max-width: 28vw; }
}

/* Открытые столы, стол для всех, сдача */
.lobby-section { padding: 24px 0 8px; }
.lobby-section h2 { margin: 0 0 4px; font-size: 18px; }
.lobby { display: grid; gap: 8px; margin-top: 10px; }
.lobby-row { display: grid; grid-template-columns: auto 1fr auto; gap: 12px; align-items: center; padding: 10px 14px; border-radius: var(--r, 12px); background: var(--tint, #f4f1ea); color: var(--ink); text-decoration: none; }
.lobby-game { font-weight: 700; }
.lobby-host { color: var(--muted, #6b665f); font-size: 14px; }
.linkish { font: inherit; background: none; border: 0; padding: 0; color: inherit; text-decoration: underline; cursor: pointer; }
.public-row { margin-top: 10px; font-size: 14px; }
.name-row { margin-top: 10px; }
.resign { margin-top: 8px; justify-self: start; }
.resign[data-armed='1'] { color: var(--x, #d81b60); border-color: var(--x, #d81b60); }
.name-row { display: grid; gap: 4px; font-size: 14px; font-weight: 600; }
.name-row input { font: inherit; font-weight: 400; padding: 10px 12px; border: 2px solid var(--edge, #8f8a83); border-radius: var(--r-s, 8px); background: var(--paper, #fff); color: inherit; max-width: 260px; }
.top .nav-user { order: 3; } .top .room-tag { order: 2; }
