/* peer2peergames: one stylesheet, mobile first, no framework.
 *
 * Tokens on :root for the light palette, redefined for dark. The board is
 * walnut and the cards ivory in both, so those are not tokens that change.
 */
:root {
  --ground: #d9d5c9;
  --surface: #efebe2;
  --surface-2: #e4dfd3;
  --ink: #221d18;
  --muted: #6d655a;
  --line: #c4bdae;
  --accent: #7a4b22;
  --accent-ink: #fbf7ee;
  --danger: #b3261e;
  --walnut: #5a3a24;
  --walnut-deep: #3d2616;
  --hole: #241509;
  --brass: #cfa64f;
  --peg-red: #c23b2c;
  --peg-blue: #2f4c8a;
  /* Seats 3 and 4. Chosen to stay apart from red and blue under deuteranopia
     and protanopia, and never relied on alone: see .swatch below. */
  --peg-green: #1f7a4d;
  --peg-amber: #d59a00;
  --card: #fbf7ee;
  --card-ink: #1e1a17;
  --card-red: #b8322a;
  --card-edge: rgba(30, 20, 10, .22);
  --back: #2f4c8a;
  --back-line: rgba(251, 247, 238, .55);
  --shadow: rgba(30, 20, 10, .22);
  --display: "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif;
  --body: system-ui, -apple-system, "Segoe UI", sans-serif;
}
@media (prefers-color-scheme: dark) {
  :root {
    --ground: #1b1815;
    --surface: #26211c;
    --surface-2: #2f2923;
    --ink: #ece5d8;
    --muted: #a79d8f;
    --line: #3d362e;
    --accent: #d3aa55;
    --accent-ink: #1b1815;
    --shadow: rgba(0, 0, 0, .5);
  }
}

/* ---- the frame ------------------------------------------------------------- */
body { font: 16px/1.45 var(--body); background: var(--ground); color: var(--ink);
       max-width: 62rem; margin: 0 auto; padding: 0 1rem 3rem; }
h1, h2, h3 { font-family: var(--display); font-weight: 400; text-wrap: balance; }
h2 { font-size: 1.7rem; margin: 1.2rem 0 .4rem; }
h3 { font-size: 1.15rem; margin: 1.6rem 0 .5rem; }
.lede { max-width: 60ch; color: var(--muted); }
.quiet { color: var(--muted); }
a { color: var(--accent); }

header.site { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem 1rem;
              border-bottom: 1px solid var(--line); padding: .8rem 0; }
header.site .brand { font-family: var(--display); font-size: 1.25rem; text-decoration: none; color: var(--ink); }
header.site .brand-mark { color: var(--accent); }
header.site nav { display: flex; flex-wrap: wrap; align-items: center; gap: .3rem .9rem; margin-left: auto; }
header.site nav a { text-decoration: none; color: var(--ink); }
header.site nav a.cta { color: var(--accent); font-weight: 600; }
header.site nav form { margin: 0; }
button.link { border: 0; background: none; color: var(--accent); padding: 0; cursor: pointer; font: inherit; }

footer.site { display: flex; flex-wrap: wrap; gap: .4rem 1rem; margin-top: 3rem; padding-top: 1rem;
              border-top: 1px solid var(--line); font-size: .9rem; }

.button, button.button { border: 1px solid var(--line); background: var(--surface-2); color: var(--ink);
  padding: .5rem .9rem; border-radius: 8px; cursor: pointer; font: inherit; font-weight: 600; text-decoration: none;
  display: inline-block; }
.button.primary, button.primary { background: var(--accent); color: var(--accent-ink); border-color: transparent; }
.button.small, button.small { padding: .3rem .6rem; font-size: .9rem; }
.button.danger, button.danger { color: var(--danger); }
.button:disabled, button:disabled { opacity: .45; cursor: default; }
.button:focus-visible, button:focus-visible, .card:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
.notice { padding: .6rem .8rem; border-radius: 8px; background: var(--surface); border: 1px solid var(--line); }
.notice.bad { border-color: var(--danger); }
form.inline { display: inline; }
form.row { display: flex; flex-wrap: wrap; gap: .8rem; align-items: flex-end; }
form.row label { display: flex; flex-direction: column; gap: .2rem; }
select, input { font: inherit; padding: .4rem; border-radius: 6px; border: 1px solid var(--line); background: var(--surface); color: var(--ink); }
input:focus-visible, select:focus-visible { outline: 3px solid var(--accent); outline-offset: 1px; border-color: var(--accent); }

/* ---- forms: sign in, create an account, the account page ------------------------- */
form.stack { display: grid; gap: .9rem; max-width: 24rem; }
form.stack label, form.row label { display: flex; flex-direction: column; gap: .3rem; font-size: .85rem; font-weight: 600; color: var(--muted); }
form.stack input:not([type="checkbox"]), form.stack select { width: 100%; box-sizing: border-box; font-size: 1rem; padding: .55rem .7rem; color: var(--ink); }
form.stack .between { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; }
form.stack .between a { font-weight: 400; }
form.stack .hint { font-weight: 400; font-size: .85rem; color: var(--muted); margin: 0; }
form.stack label.check, label.check { flex-direction: row; align-items: center; gap: .6rem; font-weight: 400; font-size: 1rem; color: var(--ink); }
form.stack label.check input, label.check input { width: 1.15rem; height: 1.15rem; margin: 0; accent-color: var(--accent); flex: 0 0 auto; }
form.stack > button { justify-self: start; background: var(--accent); color: var(--accent-ink); border: 1px solid transparent;
                      padding: .6rem 1.1rem; border-radius: 8px; font-weight: 600; }
form.stack > button.bad { background: none; color: var(--danger); border-color: var(--danger); }
.cap { text-transform: capitalize; }

.auth { max-width: 26rem; margin: 2rem auto 0; padding: 1.6rem 1.5rem 1.4rem; background: var(--surface); border: 1px solid var(--line);
        border-radius: 12px; box-shadow: 0 6px 20px var(--shadow); }
.auth h2 { margin: 0 0 .3rem; font-size: 1.8rem; }
.auth .lede { margin: 0 0 1.2rem; }
.auth .notice { margin: 0 0 1rem; }
.auth form.stack { max-width: none; }
.auth form.stack > button { justify-self: stretch; width: 100%; }
.auth .divider { display: flex; align-items: center; gap: .8rem; margin: 1.2rem 0; color: var(--muted); font-size: .85rem; }
.auth .divider::before, .auth .divider::after { content: ""; flex: 1; border-top: 1px solid var(--line); }
.auth .oauth { display: grid; gap: .5rem; }
.auth .oauth .button { text-align: center; }
.auth .alt { margin: 1.2rem 0 0; text-align: center; color: var(--muted); }
.auth .aside { margin: .8rem 0 0; text-align: center; font-size: .85rem; color: var(--muted); }
.auth .aside a { word-break: break-all; }

/* ---- welcome, lists ------------------------------------------------------------ */
.hero { padding: 1.5rem 0 .5rem; }
.hero h2 { font-size: 2rem; max-width: 22ch; }
.actions { display: flex; flex-wrap: wrap; gap: .6rem; margin: 1rem 0; }
.steps { padding-left: 1.2rem; max-width: 60ch; display: grid; gap: .5rem; }
.columns { display: grid; gap: 0 2rem; grid-template-columns: 1fr; }
@media (min-width: 720px) { .columns { grid-template-columns: 1fr 1fr; } }
ul.games, ul.challenges { list-style: none; padding: 0; margin: 0; display: grid; gap: .4rem; }
ul.games li, ul.challenges li { padding: .5rem .7rem; background: var(--surface); border: 1px solid var(--line); border-radius: 8px; }
ul.challenges li { display: flex; flex-wrap: wrap; align-items: center; gap: .6rem; }
ul.challenges .who { font-weight: 600; }
ol.log { font-variant-numeric: tabular-nums; }
.invite-link a { word-break: break-all; }

/* ---- the roster, filters and tables (plan phase 12) ------------------------------ */
/* The game grid (plan_p2p_home_and_seo phase 01). It replaced .roster-list, a
   flex row per game, which was right for one game and unreadable at nine.
   Tiles are a fixed minimum width rather than a fixed count, so the same rule
   gives four across on a desktop and one on a phone with no breakpoint. */
.game-grid { list-style: none; padding: 0; margin: 0; display: grid; gap: 1rem;
             grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); }
/* Three rows: the name, the blurb, the buttons. The blurb's row is the elastic
   one, so the buttons sit on the floor of every tile and a row of tiles has its
   actions in a line however long the blurbs are. */
.game-tile { display: grid; grid-template-columns: auto 1fr; grid-template-rows: auto 1fr auto;
             gap: .2rem .8rem; padding: .9rem 1rem 1rem;
             background: var(--surface); border: 1px solid var(--line); border-radius: 10px; }
.game-tile .game-icon { grid-row: 1 / span 2; width: 3rem; height: 3rem; align-self: start; }
.game-tile h4 { margin: .1rem 0 0; font-size: 1.1rem; }
.game-tile .blurb { margin: .15rem 0 0; color: var(--muted); font-size: .88rem; }
.game-tile .tile-actions { grid-column: 1 / -1; margin: .8rem 0 0;
                           display: flex; flex-wrap: wrap; gap: .5rem .9rem; align-items: center; }
/* a game that is registered but has no page yet: no Play button to press */
.game-tile.soon { opacity: .82; }
.game-tile .tag { font-size: .8rem; padding: .25rem .6rem; border-radius: 999px;
                  background: var(--surface-2); border: 1px dashed var(--line); color: var(--muted); }

/* the same icons label the lobby's filter chips, so the roster reads alike wherever it is */
.chips .chip-icon { width: 1.15rem; height: 1.15rem; margin-right: .35rem; flex: none; }

.chips, .tabs { display: flex; flex-wrap: wrap; gap: .4rem; margin: .4rem 0 .8rem; }
.chips a, .tabs a { text-decoration: none; padding: .25rem .7rem; border-radius: 999px; border: 1px solid var(--line); color: var(--ink); background: var(--surface); font-size: .9rem; }
.chips a { display: inline-flex; align-items: center; }
.chips a[aria-current], .tabs a[aria-current] { background: var(--accent); color: var(--accent-ink); border-color: transparent; }
.board-table { border-collapse: collapse; width: 100%; font-variant-numeric: tabular-nums; }
.board-table th, .board-table td { text-align: left; padding: .4rem .6rem; border-bottom: 1px solid var(--line); }
.board-table th { font-size: .75rem; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.record { display: grid; gap: .3rem; margin: .4rem 0 1rem; }
.record div { display: flex; gap: .6rem; }
.record dt { color: var(--muted); min-width: 9rem; }
.record dd { margin: 0; }
.record-game h3 { margin-top: 1rem; }
.move-list { display: flex; flex-wrap: wrap; gap: .5rem; min-height: 2.4rem; margin-bottom: .6rem; }

/* ---- tic-tac-toe ------------------------------------------------------------------------ */
.ttt-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; padding: 6px; margin: 0 0 .8rem;
            background: var(--walnut); border-radius: 10px; width: min(100%, 354px); box-sizing: border-box;
            box-shadow: inset 0 2px 8px rgba(0,0,0,.35), 0 3px 10px var(--shadow); }
.ttt-grid .cell { aspect-ratio: 1; border: 0; border-radius: 6px; background: var(--card); color: var(--card-ink);
                  font-family: var(--display); font-size: clamp(2rem, 8vw, 3.6rem); line-height: 1; cursor: pointer;
                  transition: background .15s ease, transform .15s ease; }
.ttt-grid .cell:not(:disabled):hover { transform: translateY(-2px); }
.ttt-grid .cell:disabled { cursor: default; opacity: 1; }          /* a taken square is not a greyed control */
.ttt-grid .cell:disabled:empty { opacity: .7; }
.ttt-grid .cell.x { color: var(--peg-red); }
.ttt-grid .cell.o { color: var(--peg-blue); }
.ttt-grid .cell.win { background: var(--brass); }
.ttt-grid .cell.hinted { outline: 3px dashed var(--brass); outline-offset: -4px; }
.ttt-grid .cell:focus-visible { outline: 3px solid var(--accent); outline-offset: 1px; }
/* ---- checkers ---------------------------------------------------------------------------- */
/* The board is walnut and the discs are the peg colours, none of which move with the colour
   scheme, so the board looks the same in both. Squares are buttons: a square that cannot be
   picked up is disabled, and a disabled square is not a greyed control. */
.checkers { margin: 0 0 .8rem; }
/* Sized by the page, never by the squares: a board declared max-content wide makes the
   game grid's column that wide too (a grid takes an item's max-content as its minimum)
   and a phone scrolls sideways. So the board is as wide as it may be, up to a limit,
   and the squares divide it; a square's height follows its width. A landscape phone
   is short rather than narrow, so there the height sets the limit instead. */
.checkers-board { display: grid; grid-template-rows: repeat(8, auto); gap: 0; padding: 6px; margin: 0 auto .2rem;
                  background: var(--walnut); border-radius: 10px; width: min(100%, 460px); box-sizing: border-box;
                  box-shadow: inset 0 2px 8px rgba(0,0,0,.35), 0 3px 10px var(--shadow);
                  touch-action: none; }
.checkers-board .rank { display: grid; grid-template-columns: repeat(8, 1fr); }
.checkers-board .square { aspect-ratio: 1; border: 0; padding: 0; position: relative; display: block; }
.checkers-board .square.light { background: var(--card); }
.checkers-board .square.dark { background: var(--walnut-deep); cursor: default; }
.checkers-board button.square { cursor: default; }
.checkers-board button.square:not(:disabled) { cursor: pointer; }
.checkers-board button.square:disabled { opacity: 1; }             /* a square is not a greyed control */
.checkers-board .num { position: absolute; left: 3px; top: 2px; font-size: .6rem; line-height: 1;
                       color: var(--card); opacity: .32; font-family: var(--body); }
.checkers-board .disc { position: absolute; inset: 12%; border-radius: 50%; display: none;
                        box-shadow: inset 0 -2px 4px rgba(0,0,0,.35), 0 2px 3px var(--shadow);
                        transition: transform .18s ease; }
.checkers-board .man .disc, .checkers-board .king .disc { display: block; }
.checkers-board .black .disc { background: var(--peg-red); }
.checkers-board .white .disc { background: var(--peg-blue); }
.checkers-board .king .disc::after { content: ''; position: absolute; inset: 26%; border-radius: 50%;
                                     border: 2px solid var(--brass); }
.checkers-board .square.selected .disc { transform: scale(1.08); box-shadow: 0 0 0 3px var(--brass), 0 2px 3px var(--shadow); }
.checkers-board .square.dragging .disc { opacity: .35; }
.checkers-board .square.can-land::before { content: ''; position: absolute; inset: 32%; border-radius: 50%;
                                           background: var(--brass); opacity: .55; }
.checkers-board .square.would-take .disc { outline: 3px solid var(--danger); outline-offset: -3px; }
.checkers-board .square.hinted { outline: 3px dashed var(--brass); outline-offset: -4px; }
.checkers-board .square.last-move::after { content: ''; position: absolute; inset: 0; pointer-events: none;
                                           box-shadow: inset 0 0 0 3px var(--brass); opacity: .5; }
.checkers-board .square:focus-visible { outline: 3px solid var(--accent); outline-offset: -3px; z-index: 1; }
.checkers .files { display: grid; grid-template-columns: repeat(8, 1fr); gap: 0;
                   width: min(100%, 460px); box-sizing: border-box; margin: 0 auto .6rem; padding: 0 6px; text-align: center; }
.checkers .files span { font-size: .75rem; }
@media (max-width: 400px) { .checkers-board .num { font-size: .5rem; left: 2px; top: 1px; } }
@media (orientation: landscape) and (max-height: 520px) {
    .checkers-board, .checkers .files { width: min(100%, 460px, calc(100vh - 6rem)); }
}
/* the piece the drag carries: appended to the board, positioned by the client */
.checkers-drag { position: fixed; z-index: 20; pointer-events: none; border-radius: 50%;
                 box-shadow: inset 0 -2px 4px rgba(0,0,0,.35), 0 4px 8px var(--shadow); }
.checkers-choice, .board-choice { display: flex; flex-wrap: wrap; gap: .4rem; margin: .3rem 0; align-items: center; }

/* ---- chess ------------------------------------------------------------------------------- */
/* The same walnut and the same tokens as checkers, so the game looks like the site and not
   like a chess program. Every square is a button; the pieces are the inline SVG symbols in
   the template, filled and outlined by the colour class on the square. */
/* The squares are tan and brown, not the cream and near-black the PIECES are: a board
   whose light square is the white piece's own colour turns half the set into outlines. */
.chess { margin: 0 0 .8rem; --sq-light: #d7bd97; --sq-dark: #7a5232; --piece-light: #fbf7ee; --piece-dark: #241a12; }
.chess-symbols { position: absolute; width: 0; height: 0; overflow: hidden; }
.chess-frame { width: min(100%, 500px); margin: 0 auto .6rem; }
@media (orientation: landscape) and (max-height: 520px) { .chess-frame { width: min(100%, 500px, calc(100vh - 6rem)); } }
.chess-board { display: grid; grid-template-rows: repeat(8, auto); gap: 0; padding: 6px 6px 6px 0;
               background: var(--walnut); border-radius: 10px; box-sizing: border-box;
               box-shadow: inset 0 2px 8px rgba(0,0,0,.35), 0 3px 10px var(--shadow); touch-action: none; }
.chess-board .rank { display: grid; grid-template-columns: 1.1rem repeat(8, 1fr); align-items: center; }
.chess-board .rank-label, .chess .files .rank-label { font-size: .7rem; color: var(--brass); text-align: center; font-family: var(--body); }
.chess .files { display: grid; grid-template-columns: 1.1rem repeat(8, 1fr); gap: 0; margin: .2rem 0 0; padding: 0 6px 0 0; text-align: center; }
.chess .files span { font-size: .75rem; }
.chess-board .square { aspect-ratio: 1; border: 0; padding: 0; position: relative; display: block; min-width: 0; }
.chess-board .square.light { background: var(--sq-light); }
.chess-board .square.dark { background: var(--sq-dark); }
.chess-board button.square { cursor: default; }
.chess-board button.square:not(:disabled) { cursor: pointer; }
.chess-board button.square:disabled { opacity: 1; }                /* a square is not a greyed control */
.chess-board .piece { position: absolute; inset: 6%; display: block; pointer-events: none; }
.chess-board .piece svg, .chess-drag svg { display: block; width: 100%; height: 100%; stroke-width: 1.6; stroke-linejoin: round; }
.chess-board .white .piece svg, .chess-drag.white svg { fill: var(--piece-light); stroke: var(--piece-dark); }
.chess-board .black .piece svg, .chess-drag.black svg { fill: var(--piece-dark); stroke: var(--piece-light); }
.chess-drag { --piece-light: #fbf7ee; --piece-dark: #241a12; }
.chess-board .square.selected .piece { transform: scale(1.1); filter: drop-shadow(0 0 3px var(--brass)); }
.chess-board .square.dragging .piece { opacity: .35; }
.chess-board .square.can-land::before { content: ''; position: absolute; inset: 36%; border-radius: 50%;
                                        background: rgba(30, 20, 10, .45); }
.chess-board .square.can-land.pawn::before, .chess-board .square.can-land.knight::before, .chess-board .square.can-land.bishop::before,
.chess-board .square.can-land.rook::before, .chess-board .square.can-land.queen::before, .chess-board .square.can-land.king::before {
    inset: 0; border-radius: 0; background: none; box-shadow: inset 0 0 0 4px var(--brass); }
.chess-board .square.would-take { box-shadow: inset 0 0 0 3px var(--danger); }
.chess-board .square.in-check { background: radial-gradient(circle, var(--danger) 0, var(--danger) 35%, transparent 75%); }
.chess-board .square.hinted { outline: 3px dashed var(--brass); outline-offset: -4px; }
.chess-board .square.last-move::after { content: ''; position: absolute; inset: 0; pointer-events: none;
                                        box-shadow: inset 0 0 0 3px var(--brass); opacity: .5; }
.chess-board .square:focus-visible { outline: 3px solid var(--accent); outline-offset: -3px; z-index: 1; }
@media (max-width: 400px) { .chess-board .rank { grid-template-columns: .8rem repeat(8, 1fr); } .chess .files { grid-template-columns: .8rem repeat(8, 1fr); } }
/* the piece the drag carries: appended to the body, positioned by the client */
.chess-drag { position: fixed; z-index: 20; pointer-events: none; }
.draw-controls { display: flex; flex-wrap: wrap; gap: .4rem; margin: .3rem 0; }

/* ---- connect four ------------------------------------------------------------------------ */
/* Sized the same way as the checkers board: the page's width up to a limit, seven equal
   columns, a cell as tall as it is wide. */
.c4-board { display: grid; grid-template-columns: repeat(7, 1fr); gap: 0; padding: 1%; margin: 0 0 .8rem;
            background: var(--peg-blue); border-radius: 12px; width: min(100%, 488px); box-sizing: border-box;
            box-shadow: inset 0 2px 8px rgba(0,0,0,.35), 0 3px 10px var(--shadow); }
@media (orientation: landscape) and (max-height: 520px) { .c4-board { width: min(100%, 488px, calc((100vh - 6rem) * 7 / 6)); } }
/* The space between cells is a margin on the cell, as a share of the column's WIDTH
   (a percentage margin always resolves against the width, top and bottom included).
   A percentage row gap would resolve against the column's height, which is not known
   until the cells are placed, so the gap was added after the board was sized and the
   bottom row hung below the blue. */
.c4-col { display: grid; gap: 0; padding: 0; border: 0; background: none; cursor: pointer; border-radius: 6px; min-width: 0; }
.c4-col:disabled { cursor: default; }
.c4-col:not(:disabled):hover .c4-cell:not(.r):not(.y) { background: rgba(255,255,255,.35); }
.c4-col:focus-visible { outline: 3px solid var(--brass); outline-offset: 2px; }
.c4-col.hinted { outline: 3px dashed var(--brass); outline-offset: 2px; }
.c4-cell { display: block; aspect-ratio: 1; margin: 6%; border-radius: 50%; background: var(--ground);
           box-shadow: inset 0 2px 4px rgba(0,0,0,.35); transition: background .15s ease; }
.c4-cell.r { background: radial-gradient(circle at 35% 35%, #e0584a, var(--peg-red) 60%, #8f2419); }
.c4-cell.y { background: radial-gradient(circle at 35% 35%, #ffe680, #e6b422 60%, #a67c00); }
.c4-cell.win { box-shadow: inset 0 0 0 4px var(--card), inset 0 2px 4px rgba(0,0,0,.35); }

/* ---- rock, paper, scissors -------------------------------------------------------------- */
.rps-choices { display: flex; flex-wrap: wrap; gap: .6rem; margin: 0 0 .8rem; }
.rps-choice { font-family: var(--display); font-size: 1.3rem; padding: .9rem 1.4rem; min-width: 7.5rem; }
.rps-choice.chosen { background: var(--accent); color: var(--accent-ink); border-color: transparent; }
.rounds { padding-left: 1.2rem; display: grid; gap: .25rem; }

.badge { font-family: var(--display); font-size: 1.1rem; padding: 0 .35rem; border-radius: 4px; background: var(--surface-2); }

/* ---- the game page ---------------------------------------------------------------- */
.game { display: grid; gap: .9rem; }
.game-head { display: grid; gap: .3rem; padding-top: 1em; }
.scores { display: flex; flex-wrap: wrap; gap: .5rem; }
.score { display: inline-flex; align-items: center; gap: .5rem; padding: .35rem .8rem .35rem .5rem; background: var(--surface);
         border: 1px solid var(--line); border-radius: 999px; font-variant-numeric: tabular-nums; }
.score b { font-family: var(--display); font-weight: 400; font-size: 1.3rem; min-width: 2ch; text-align: right; }
.score .name { color: var(--muted); }
.score .dealer { font-size: .7rem; letter-spacing: .08em; text-transform: uppercase; color: var(--accent); font-weight: 600; }
/* A seat's swatch. The COLOUR IS NEVER THE ONLY DIFFERENCE: each seat has its
 * own shape and carries its own number, because four colours that a
 * colour-blind player can reliably separate do not exist. At three or four
 * seats the marker is how somebody finds their own score on a crowded page.
 *
 * Red and blue keep their shapes, so every two-seat game looks exactly as it
 * did. */
.swatch {
  width: 16px; height: 16px; display: inline-block;
  font-size: 10px; line-height: 16px; text-align: center;
  color: #fff; font-weight: 700;
}
.swatch.red { background: var(--peg-red); border-radius: 50%; }
.swatch.blue { background: var(--peg-blue); border-radius: 2px; }
.swatch.green { background: var(--peg-green); border-radius: 50% 2px 50% 2px; }
.swatch.amber { background: var(--peg-amber); border-radius: 2px 50% 2px 50%; color: #3a2a00; }
.meta { margin: 0; font-size: .9rem; }

.board { background: linear-gradient(170deg, #6a4529, var(--walnut) 40%, var(--walnut-deep)); border-radius: 10px;
         padding: .6rem .8rem; box-shadow: inset 0 2px 8px rgba(0,0,0,.35), 0 3px 10px var(--shadow); overflow-x: auto; }
.board svg { display: block; width: 100%; min-width: 480px; height: auto; }
.board .holes circle { fill: var(--hole); }
.board .holes .finish { stroke: var(--brass); stroke-width: 1.2; }
.board .labels text { font-family: var(--display); font-size: 6px; fill: var(--brass); }
.board .peg { transition: transform .55s cubic-bezier(.4, 0, .2, 1); }
.board .peg circle, .board .peg rect { stroke: rgba(0,0,0,.45); stroke-width: .6; }
.board .peg.p1 circle { fill: var(--peg-red); }
.board .peg.p2 rect { fill: var(--peg-blue); }
.board .peg .shine { fill: rgba(255,255,255,.55); stroke: none; }
@media (prefers-reduced-motion: reduce) { .board .peg, .card, .checkers-board .disc, .chess-board .piece { transition: none !important; } }

.status { font-size: 1.1rem; min-height: 1.5em; margin: 0; }

.table { display: grid; gap: .8rem; padding: .8rem; border-radius: 10px; background: var(--surface-2); border: 1px dashed var(--line); }
@media (min-width: 640px) { .table { grid-template-columns: 1fr auto; align-items: start; } }
.seq { display: flex; flex-wrap: wrap; gap: .4rem; align-items: flex-start; min-height: 72px; }
.seq .who { font-size: .7rem; color: var(--muted); text-align: center; display: grid; gap: 2px; justify-items: center; }
.side { display: flex; flex-wrap: wrap; gap: .8rem; align-items: flex-start; }
.count { font-family: var(--display); font-size: 2rem; line-height: 1; min-width: 3ch; text-align: center; font-variant-numeric: tabular-nums; }
.count small { display: block; font-family: var(--body); font-size: .65rem; letter-spacing: .1em; text-transform: uppercase; color: var(--muted); }
.starterbox, .cribbox, .oppbox { display: grid; gap: .2rem; justify-items: center; }
.label { font-size: .65rem; letter-spacing: .1em; text-transform: uppercase; color: var(--muted); }
.pile { display: inline-grid; place-items: center; width: 46px; aspect-ratio: 5/7; border-radius: 5px; font-family: var(--display); font-size: 1.2rem;
         background: repeating-linear-gradient(45deg, transparent 0 4px, var(--back-line) 4px 5px), repeating-linear-gradient(-45deg, transparent 0 4px, var(--back-line) 4px 5px), var(--back);
         color: var(--card); box-shadow: inset 0 0 0 3px var(--card); }

/* ---- cards ----------------------------------------------------------------------------- */
.hand .cards { display: flex; flex-wrap: wrap; gap: .5rem; padding-top: 16px; min-height: 108px; }
.card { --w: 66px; display: inline-block; width: var(--w); aspect-ratio: 5 / 7; font-size: calc(var(--w) * .21); position: relative; padding: 0;
        border-radius: calc(var(--w) * .09); background: var(--card); color: var(--card-ink); border: 1px solid var(--card-edge);
        box-shadow: 0 1px 2px var(--shadow); font-family: var(--display); cursor: pointer; flex: 0 0 auto;
        transition: transform .18s ease, box-shadow .18s ease; }
.card.red { color: var(--card-red); }
.card.sm { --w: 46px; }
.card .idx { position: absolute; top: .3em; left: .38em; line-height: 1; text-align: center; }
.card .idx small { display: block; font-size: .8em; font-family: var(--body); }
.card .idx.b { top: auto; left: auto; bottom: .3em; right: .38em; transform: rotate(180deg); }
.card .pip { position: absolute; inset: 0; display: grid; place-items: center; font-size: 1.8em; }
.card:not(:disabled):hover { transform: translateY(-4px); }
.card[aria-pressed="true"] { transform: translateY(-14px); box-shadow: 0 8px 16px var(--shadow); outline: 2px solid var(--accent); outline-offset: 2px; }
.card:disabled { cursor: default; }
.card:disabled:not(.back):not(.static) { opacity: .42; }
.card.back { background: repeating-linear-gradient(45deg, transparent 0 4px, var(--back-line) 4px 5px), repeating-linear-gradient(-45deg, transparent 0 4px, var(--back-line) 4px 5px), var(--back);
             border-color: rgba(0,0,0,.3); box-shadow: inset 0 0 0 3px var(--card), 0 1px 2px var(--shadow); }
.card.hi { outline: 2px solid var(--brass); outline-offset: 1px; }
.card.new { animation: deal .35s ease-out; }
@keyframes deal { from { transform: translateY(8px); opacity: 0; } to { transform: none; opacity: 1; } }

.controls { display: flex; flex-wrap: wrap; align-items: center; gap: .6rem; min-height: 2.4rem; padding-top:1em;}
.emotes { display: flex; flex-wrap: wrap; gap: .4rem; align-items: center; }
.toast { margin: 0; padding: .3rem .7rem; border-radius: 999px; background: var(--surface); border: 1px solid var(--line); }
.hand-ends details { background: var(--surface); border: 1px solid var(--line); border-radius: 8px; padding: .4rem .7rem; margin: .3rem 0; }
.hand-ends summary { cursor: pointer; font-family: var(--display); }
.hand-ends ul { margin: .3rem 0 .2rem; padding-left: 1.1rem; font-size: .92rem; }
/* a card in a line of text: the count says what scored, these say from what */
.pip-cards { display: inline-flex; flex-wrap: wrap; gap: .2rem; vertical-align: -.15em; }
.pip-card { display: inline-flex; align-items: baseline; gap: .05em; padding: .05em .3em;
            border: 1px solid var(--line); border-radius: 4px; background: var(--card);
            font-family: var(--display); font-size: .88em; line-height: 1.35; white-space: nowrap; color: black; }
.pip-card.red { color: var(--card-red); }
.pip-card small { font-size: 1.05em; }
.game-actions { display: flex; flex-wrap: wrap; gap: .8rem; align-items: center; }
.game-actions p { margin: 0; }
/* ---- the referral banner, above the footer on every page --------------------------------- */
.promo { display: flex; flex-wrap: wrap; align-items: center; gap: .6rem 1.2rem; margin: 2.5rem 0 0; padding: .9rem 1.1rem;
         background: var(--surface); border: 1px solid var(--line); border-radius: 10px; }
.promo-text { margin: 0; flex: 1 1 24ch; }
.promo-go { margin: 0; display: flex; flex-wrap: wrap; align-items: center; gap: .4rem .8rem; }
.promo-mark { font-size: .7rem; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }

/* ---- the modal: somebody joined your game ---------------------------------------------- */
dialog.modal { border: 1px solid var(--line); border-radius: 14px; background: var(--surface); color: var(--ink);
               padding: 2rem 2.2rem; max-width: min(34rem, 92vw); box-shadow: 0 16px 48px var(--shadow); }
dialog.modal::backdrop { background: rgba(20, 14, 8, .6); backdrop-filter: blur(2px); }
dialog.modal h2 { margin: 0 0 .5rem; font-size: 2rem; }
dialog.modal .lede { font-size: 1.15rem; margin: 0 0 1.4rem; }
dialog.modal .actions { margin: 0; }
.button.big { font-size: 1.15rem; padding: .8rem 1.4rem; }
.rematch-prompt { flex-basis: 100%; display: flex; flex-wrap: wrap; gap: .6rem; align-items: center; padding: .6rem .8rem;
                  background: var(--surface); border: 1px solid var(--line); border-radius: 8px; }
.push-prompt { display: flex; flex-wrap: wrap; gap: .6rem; align-items: center; padding: .6rem .8rem; background: var(--surface); border: 1px solid var(--line); border-radius: 8px; }
.push-prompt p { margin: 0; }

/* ---- consent and advertising (plan phase 08) ---------------------------------------- */
.consent { position: sticky; bottom: 0; margin: 1rem -1rem 0; padding: .8rem 1rem; background: var(--surface); border-top: 1px solid var(--line);
           display: flex; flex-wrap: wrap; gap: .6rem 1.2rem; align-items: center; box-shadow: 0 -3px 12px var(--shadow); }
.consent p { margin: 0; max-width: 60ch; }
.consent-choice { display: flex; gap: .5rem; }
/* The ins must FILL the slot. `place-items: center` sets justify-items too,
   which sizes a grid item to its own content: an empty <ins> is then zero
   wide, and the network refuses it with "No slot size for availableWidth=0".
   Centre the box, stretch what is in it. */
.ad-slot { margin: 1rem 0; min-height: 90px; overflow:hidden; align-items: center; }
.ad-slot > ins.adsbygoogle { display: block; width: 100%; }
.ad-slot-header { max-width: 728px; margin-inline: auto; }
.with-sidebar { display: grid; gap: 1.5rem; grid-template-columns: 1fr; }
@media (min-width: 1100px) { .with-sidebar:has(.sidebar) { grid-template-columns: minmax(0, 1fr) 300px; } .sidebar { position: sticky; top: 1rem; align-self: start; } }
.card.hinted { outline: 2px dashed var(--brass); outline-offset: 2px; }
.theme-crimson .card.back, .theme-crimson .pile { background: repeating-linear-gradient(45deg, transparent 0 4px, var(--back-line) 4px 5px), repeating-linear-gradient(-45deg, transparent 0 4px, var(--back-line) 4px 5px), #8a2f2a; }
.theme-sage .card.back, .theme-sage .pile { background: repeating-linear-gradient(45deg, transparent 0 4px, var(--back-line) 4px 5px), repeating-linear-gradient(-45deg, transparent 0 4px, var(--back-line) 4px 5px), #4f6b4a; }
aside.sidebar {
    overflow: hidden;
}
/* ---- ludo ---------------------------------------------------------------------------- */
/* The cross board: fifteen by fifteen, so the arms, the yards and the middle
   all fall out of the grid rather than being positioned by hand. */
.ludo { display: grid; gap: .8rem; justify-items: center; }
.ludo-board { display: grid; grid-template-rows: repeat(15, 1fr);
              background: var(--surface-2); border: 1px solid var(--line); border-radius: 8px;
              padding: 4px; width: min(90vw, 30rem); }
.ludo-row { display: grid; grid-template-columns: repeat(15, 1fr); }
.ludo-board .cell { aspect-ratio: 1; position: relative; display: grid; place-items: center;
                    border: 1px solid transparent; }
.ludo-board .cell.track { background: var(--card); border-color: var(--line); }
.ludo-board .cell.blank { background: transparent; }
.ludo-board .cell.finish { background: var(--brass); border-radius: 4px; }
.ludo-board .cell.home.red, .ludo-board .cell.yard.red, .ludo-board .cell.entry.red { background: var(--peg-red); }
.ludo-board .cell.home.blue, .ludo-board .cell.yard.blue, .ludo-board .cell.entry.blue { background: var(--peg-blue); }
.ludo-board .cell.home.green, .ludo-board .cell.yard.green, .ludo-board .cell.entry.green { background: #3f7d4f; }
.ludo-board .cell.home.yellow, .ludo-board .cell.yard.yellow, .ludo-board .cell.entry.yellow { background: #c8992f; }
.ludo-board .cell.yard { border-radius: 50%; opacity: .35; }
.ludo-board .cell.can-land::before { content: ''; position: absolute; inset: 18%; border-radius: 50%;
                                     border: 2px dashed var(--brass); }
/* A token carries its NUMBER as well as its colour: four seats need four
   colours, and colour alone is not a distinction everybody can see. */
.ludo-board .token { position: absolute; inset: 6%; border-radius: 50%; border: 1px solid var(--card-edge);
                     font: 600 clamp(7px, 1.4vw, 11px)/1 var(--body); color: var(--accent-ink);
                     display: grid; place-items: center; padding: 0; cursor: default; }
.ludo-board .token.red { background: var(--peg-red); }
.ludo-board .token.blue { background: var(--peg-blue); }
.ludo-board .token.green { background: #3f7d4f; }
.ludo-board .token.yellow { background: #c8992f; color: var(--card-ink); }
.ludo-board .token.playable { cursor: pointer; box-shadow: 0 0 0 2px var(--brass); }
.ludo-board .token.playable:hover { transform: scale(1.12); }
.ludo-board .token.hinted { outline: 2px dashed var(--brass); outline-offset: 2px; }
.ludo-board .token:disabled { opacity: 1; }
.ludo-board .token:focus-visible { outline: 3px solid var(--accent); outline-offset: 1px; z-index: 2; }

.ludo-seats { list-style: none; display: flex; flex-wrap: wrap; gap: .4rem .9rem; padding: 0; margin: 0; }
.ludo-seats li { display: flex; align-items: center; gap: .4rem; padding: .2rem .5rem; border-radius: 999px;
                 border: 1px solid transparent; font-size: .9rem; }
.ludo-seats li.on-turn { border-color: var(--brass); background: var(--surface); }
.ludo-seats .dot { width: .7rem; height: .7rem; border-radius: 50%; }
.ludo-seats .dot.red { background: var(--peg-red); } .ludo-seats .dot.blue { background: var(--peg-blue); }
.ludo-seats .dot.green { background: #3f7d4f; }     .ludo-seats .dot.yellow { background: #c8992f; }
.ludo-seats .tally { color: var(--muted); }

/* The die is shown, not thrown: the roll came from the seed with the state. */
.ludo-side { text-align: center; }
.die-wrap { display: flex; align-items: center; gap: .6rem; justify-content: center; margin: 0 0 .3rem; }
.die { display: grid; grid-template-columns: repeat(3, 1fr); gap: 2px; place-items: center;
       width: 2.4rem; height: 2.4rem; padding: .3rem; border-radius: 8px;
       background: var(--card); border: 1px solid var(--line); color: var(--muted); }
.die i { width: .38rem; height: .38rem; border-radius: 50%; background: var(--card-ink); }
.die.idle { color: var(--muted); font-size: 1.4rem; }
.die.rolled { animation: die-in .25s ease-out; }
@keyframes die-in { from { transform: rotate(-12deg) scale(.85); } to { transform: none; } }
.ludo .small { font-size: .8rem; max-width: 42ch; margin: 0 auto; }
@media (prefers-reduced-motion: reduce) { .die.rolled { animation: none; } .ludo-board .token { transition: none; } }

/* ---- backgammon ---------------------------------------------------------------------- */
/* The real board: four quadrants split by the bar, trays outside, points as
   triangles. The viewer's home board is always the bottom right, whichever
   seat they hold, so neither player has to do arithmetic to read it.
   The checkers are WHITE and BLACK, which is what the badges say and what a
   backgammon set looks like. */
.bg { display: grid; gap: .6rem; justify-items: center; }
.bg-board { width: min(96vw, 44rem); background: var(--walnut-deep);
            border: 3px solid var(--walnut); border-radius: 8px; padding: 4px;
            display: grid; gap: 0; }
.bg-half { display: grid; grid-template-columns: 6fr auto 6fr auto; gap: 3px; }
.bg-quad { display: grid; grid-template-columns: repeat(6, 1fr); gap: 1px;
           background: var(--walnut); border-radius: 2px; }
.bg-quad.home { box-shadow: inset 0 0 0 2px var(--brass); }

/* A point is a triangle with the checkers stacked from its base: down from
   the top row, up from the bottom, which is how they sit on a board. The
   number sits on the OUTER edge, away from the checkers and away from the
   bar, which is where a real board prints it. */
.bg-board .pt { position: relative; height: 8.5rem; cursor: default;
                display: flex; justify-content: center; }
.bg-half.top .pt    { align-items: flex-start; padding-top: .85rem; }
.bg-half.bottom .pt { align-items: flex-end;  padding-bottom: .85rem; }
.bg-board .tri { position: absolute; left: 0; right: 0; }
.bg-half.top .tri    { top: .85rem; bottom: 0; clip-path: polygon(0 0, 100% 0, 50% 100%); }
.bg-half.bottom .tri { top: 0; bottom: .85rem; clip-path: polygon(50% 0, 100% 100%, 0 100%); }
.bg-board .tri { background: #efe6d2; }
.bg-board .pt.dark .tri { background: #6b4a2f; }
.bg-board .pn { position: absolute; left: 0; right: 0; text-align: center;
                font: 600 .6rem/.85rem var(--body); color: var(--muted); }
.bg-half.top .pn    { top: 0; }
.bg-half.bottom .pn { bottom: 0; }

/* Checkers overlap slightly, as a real stack does, so five fit in a point. */
.bg-board .men { position: relative; display: flex; flex-direction: column;
                 align-items: center; z-index: 1; }
.bg-half.bottom .men { flex-direction: column-reverse; }
.bg-board .man { width: 1.3rem; height: 1.3rem; border-radius: 50%; display: block;
                 box-shadow: inset 0 0 0 1px rgba(0,0,0,.35), 0 1px 1px var(--shadow); }
.bg-board .man + .man { margin-top: -.12rem; }
.bg-half.bottom .man + .man { margin-top: 0; margin-bottom: -.12rem; }
.bg-board .man.white { background: #f4efe2; }
.bg-board .man.black { background: #2b2622; }
.bg-board .more { font: 700 .62rem/1 var(--body); color: var(--ink);
                  background: var(--brass); border-radius: 999px; padding: 1px 5px; margin-top: 1px; }

/* what may be picked, and where it may go: the server decided both */
.bg-board .pt.can-from, .bg-board .pt.can-to { cursor: pointer; }
.bg-board .pt.can-from .tri { filter: brightness(1.12); }
.bg-board .pt.can-from::after, .bg-board .pt.can-to::after {
    content: ''; position: absolute; left: 50%; transform: translateX(-50%);
    width: .5rem; height: .5rem; border-radius: 50%; background: var(--brass); }
.bg-half.top .pt.can-from::after, .bg-half.top .pt.can-to::after { bottom: .3rem; }
.bg-half.bottom .pt.can-from::after, .bg-half.bottom .pt.can-to::after { top: .3rem; }
.bg-board .pt.can-to .tri { filter: brightness(1.25); box-shadow: inset 0 0 0 2px var(--accent); }
.bg-board .pt.picked .tri { box-shadow: inset 0 0 0 3px var(--accent); filter: brightness(1.3); }
.bg-board .pt:focus-visible { outline: 3px solid var(--accent); outline-offset: -3px; z-index: 2; }

.bg-bar { width: 2rem; background: var(--walnut-deep); border-radius: 2px;
          display: flex; align-items: center; justify-content: center; }
.bg-tray { width: 1.9rem; background: var(--walnut-deep); border-radius: 2px;
           display: grid; place-items: center; box-shadow: inset 0 0 0 1px var(--walnut); }
.bg-tray.mine { box-shadow: inset 0 0 0 2px var(--brass); }
/* bearing off is a move to the tray, so the tray lights up like a point does */
.bg-tray.can-to { cursor: pointer; background: var(--walnut);
                  box-shadow: inset 0 0 0 3px var(--accent); filter: brightness(1.15); }
.bg-tray:focus-visible { outline: 3px solid var(--accent); outline-offset: -3px; }
.tray-count { font: 700 .85rem/1 var(--display); color: var(--accent-ink); }

.bg-under { display: flex; flex-wrap: wrap; gap: .6rem 1.2rem; align-items: center; justify-content: center; }
.bg-pips { margin: 0; font-size: .9rem; }
.bg-dice { display: flex; gap: .4rem; align-items: center; }
.bg-dice .die { display: grid; grid-template: repeat(3, 1fr) / repeat(3, 1fr);
                width: 2.1rem; height: 2.1rem; padding: .22rem; gap: 1px;
                border-radius: 7px; background: #f4efe2;
                border: 1px solid var(--line); box-shadow: 0 1px 3px var(--shadow); }
.bg-dice .pip { width: .34rem; height: .34rem; border-radius: 50%; background: #2b2622;
                align-self: center; justify-self: center; }
.bg-dice .pip.r1 { grid-row: 1 } .bg-dice .pip.r2 { grid-row: 2 } .bg-dice .pip.r3 { grid-row: 3 }
.bg-dice .pip.c1 { grid-column: 1 } .bg-dice .pip.c2 { grid-column: 2 } .bg-dice .pip.c3 { grid-column: 3 }
/* a double is worth seeing at a glance: four dice, all the same */
.bg-dice.doubles .die { box-shadow: 0 0 0 2px var(--brass), 0 1px 3px var(--shadow); }
.bg-building { display: flex; flex-wrap: wrap; gap: .5rem; align-items: center;
               padding: .4rem .7rem; background: var(--surface); border: 1px solid var(--brass);
               border-radius: 8px; }
.bg-building b { font-family: var(--display); }
@media (max-width: 34rem) {
  .bg-board .pt { height: 6rem; }
  .bg-board .man { width: .95rem; height: .95rem; }
  .bg-bar, .bg-tray { width: 1.4rem; }
}

/* ---- hangman ------------------------------------------------------------------------- */
/* Two gallows, one word. Yours is large and theirs is smaller beside it: their
   figure is public because the miss count is, and their word is a row of blocks
   saying HOW MANY letters they have found and never which. That asymmetry is the
   whole tension of the game and it has to read at a glance. */

/* a general utility, introduced here because nothing needed it before: text for
   a screen reader that the drawing carries for everybody else */
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
           overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

.hm { display: grid; gap: 1rem; justify-items: center; }
.hm-bar { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem 1rem; justify-content: center; }
.hm-category { margin: 0; color: var(--muted); font-size: .95rem; }
.hm-category b { color: var(--ink); }

.hm-pips { list-style: none; display: flex; gap: .35rem; padding: 0; margin: 0; }
.hm-pips .pip { width: .8rem; height: .8rem; border-radius: 50%;
                border: 1px solid var(--line); background: transparent; }
.hm-pips .pip.current { border-color: var(--accent); box-shadow: 0 0 0 2px var(--surface-2); }
.hm-pips .pip.won { background: var(--accent); border-color: var(--accent); }
.hm-pips .pip.lost { background: var(--muted); border-color: var(--muted); }
/* a drawn round is a half, and it looks like one */
.hm-pips .pip.drawn { background: linear-gradient(90deg, var(--accent) 50%, transparent 50%); }

.hm-boards { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem 1.5rem;
             align-items: start; width: min(96vw, 34rem); }
.hm-board { display: grid; justify-items: center; gap: .4rem; }
.hm-who { margin: 0; font: 600 .95rem/1 var(--body); color: var(--muted); }
.hm-board.mine .hm-who { color: var(--ink); }

.hm-figure { width: 100%; max-width: 11rem; height: auto; }
.hm-figure.small { max-width: 7.5rem; opacity: .85; }
.hm-figure .frame { stroke: var(--line); stroke-width: 5; }
.hm-figure .limbs { stroke: var(--ink); stroke-width: 4; }
/* every limb is normalised to pathLength 100, so one dash rule draws all six
   however long each really is */
.hm-figure .limb { stroke-dasharray: 100; stroke-dashoffset: 100; }
.hm-figure .limb.on { stroke-dashoffset: 0; transition: stroke-dashoffset .35s ease-out; }

.hm-lives { margin: 0; font-size: .85rem; color: var(--muted); }
.hm-lives.danger { color: var(--danger); font-weight: 600; }

.hm-slots { list-style: none; display: flex; flex-wrap: wrap; gap: .3rem;
            padding: 0; margin: .2rem 0 0; justify-content: center; }
.hm-slots .slot { width: 1.5rem; height: 1.9rem; display: grid; place-items: center;
                  border-bottom: 2px solid var(--line);
                  font: 600 1.1rem/1 var(--display); color: var(--ink); }
.hm-slots .slot.shown { border-bottom-color: var(--accent); }
.hm-slots .slot.just { animation: hm-flip .3s ease-out; }
@keyframes hm-flip { from { transform: rotateX(-90deg); opacity: 0; } to { transform: none; opacity: 1; } }
/* theirs is a count, so it is blocks and never letters */
.hm-slots.blocks .slot { width: .9rem; height: .9rem; border: 1px solid var(--line);
                         border-radius: 2px; background: transparent; }
.hm-slots.blocks .slot.shown { background: var(--accent); border-color: var(--accent); }

.hm-keyboard { display: grid; gap: .3rem; justify-items: center; width: min(96vw, 32rem); }
.hm-keyrow { display: flex; gap: .3rem; justify-content: center; flex-wrap: wrap; }
.hm-key { min-width: 2.1rem; min-height: 2.6rem; padding: 0 .3rem; border-radius: 6px;
          border: 1px solid var(--line); background: var(--card); color: var(--card-ink);
          font: 600 1rem/1 var(--body); text-transform: uppercase; cursor: pointer; }
.hm-key:hover:not(:disabled) { border-color: var(--accent); }
.hm-key:focus-visible { outline: 3px solid var(--accent); outline-offset: 1px; }
.hm-key.hit { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
/* A MISS IS STRUCK THROUGH as well as dimmed: a colour is not a state. */
.hm-key.miss { background: transparent; color: var(--muted); text-decoration: line-through;
               text-decoration-thickness: 2px; opacity: .7; }
.hm-key:disabled { cursor: default; }
.hm-key.hinted { outline: 2px dashed var(--brass); outline-offset: 2px; }
/* you have guessed and they have not: the board says so without a sentence */
.hm.waiting .hm-keyboard { opacity: .55; }

.hm-solve { display: grid; gap: .4rem; justify-items: center; }
.hm-solve-box { display: flex; flex-wrap: wrap; gap: .4rem; align-items: center;
                justify-content: center; max-width: 34rem; }
.hm-solve-box label { flex: 1 0 100%; text-align: center; font-size: .85rem; color: var(--muted); }
.hm-solve-box input { font: 600 1rem/1 var(--body); text-transform: uppercase; letter-spacing: .1em;
                      padding: .45rem .6rem; border-radius: 6px; border: 1px solid var(--line);
                      background: var(--card); color: var(--card-ink); }
.hm .small { font-size: .8rem; max-width: 46ch; margin: 0 auto; text-align: center; }

@media (max-width: 30rem) {
    .hm-boards { grid-template-columns: 1fr; }
    .hm-board.theirs { border-top: 1px solid var(--line); padding-top: .8rem; }
    .hm-key { min-width: 1.9rem; min-height: 2.9rem; }
}
@media (prefers-reduced-motion: reduce) {
    .hm-figure .limb.on { transition: none; }
    .hm-slots .slot.just { animation: none; }
}

/* ---- dominoes ------------------------------------------------------------------ */
/* Real tiles, drawn in CSS from two numbers, so the board renders with
   JavaScript off and the client only has to rebuild the same markup.
   The pips are background gradients rather than elements: a 6-6 is 12 dots and
   a table is thirty tiles, and that is 360 spans nobody needs. */

.dominoes .dom-arms { overflow: auto; padding: .5rem 0; max-height: 28rem; }

/* The main line runs across, and the SPINNER sits in it like any other tile so
   the line stays straight and unbroken.
   
   Its two arms are positioned OUT of the flow, away from it. They were flex
   children of a centred column before, which meant an arm growing on one side
   shoved the spinner off the line: with five tiles below and none above, the
   line ran through the middle of the lower arm instead of through the spinner.
   Out of the flow, the spinner cannot move however long either arm gets. */
.dominoes .dom-line { display: flex; gap: .25rem; align-items: center; justify-content: center;
  white-space: nowrap; min-height: 26rem; }
.dom-spinner { position: relative; display: inline-flex; flex: 0 0 auto; }
.dom-arm { position: absolute; left: 50%; transform: translateX(-50%);
  display: flex; flex-direction: column; gap: .25rem; align-items: center; }
.dom-arm.up { bottom: calc(100% + .25rem); }
.dom-arm.down { top: calc(100% + .25rem); }
.dom-arm:empty { display: none; }

/* A tile lies LENGTHWAYS along its run: wide on the main line, tall on an arm.
   A double lies CROSSWISE, which is the whole reason a spinner has arms, so it
   is the other way round in both places. */
.dom-tile {
  --pip: currentColor;
  display: inline-flex; flex: 0 0 auto;
  background: var(--card); color: var(--card-ink);
  border: 1px solid var(--card-edge); border-radius: 6px;
  box-shadow: 0 1px 2px var(--shadow);
  overflow: hidden;
}
.dom-half { width: 1.7rem; height: 1.7rem; position: relative; }
.dom-half + .dom-half { border-left: 1px solid var(--card-edge); }

/* On the main line: lengthways along it, doubles across it. */
.dom-line > .dom-tile { flex-direction: row; }
.dom-line > .dom-tile.double { flex-direction: column; }
.dom-line > .dom-tile.double .dom-half + .dom-half { border-left: 0; border-top: 1px solid var(--card-edge); }

/* The spinner is always crosswise: that is what makes it a spinner. It is also
   marked, because it is the only double whose two ends can be played on and a
   player needs to see which one it is. */
.dom-tile.spinner { flex-direction: column; box-shadow: 0 0 0 2px var(--brass), 0 1px 2px var(--shadow); }
.dom-tile.spinner .dom-half + .dom-half { border-left: 0; border-top: 1px solid var(--card-edge); }

/* On an arm: down the arm, doubles across it. */
.dom-arm .dom-tile { flex-direction: column; }
.dom-arm .dom-tile .dom-half + .dom-half { border-left: 0; border-top: 1px solid var(--card-edge); }
.dom-arm .dom-tile.double { flex-direction: row; }
.dom-arm .dom-tile.double .dom-half + .dom-half { border-left: 1px solid var(--card-edge); border-top: 0; }

/* In the hand: held upright. */
.dom-hand .dom-tile { flex-direction: column; }
.dom-hand .dom-tile .dom-half + .dom-half { border-left: 0; border-top: 1px solid var(--card-edge); }

/* The pips. Three columns and three rows at 25/50/75, which is every layout a
   double six set needs. */
.dom-half::before {
  content: ""; position: absolute; inset: 0;
  background-repeat: no-repeat;
  background-size: 100% 100%;
}
.dom-half[data-pips="0"]::before { background-image: none; }
.dom-half[data-pips="1"]::before {
  background-image: radial-gradient(circle at 50% 50%, var(--pip) 1.6px, transparent 1.7px); }
.dom-half[data-pips="2"]::before {
  background-image:
    radial-gradient(circle at 27% 27%, var(--pip) 1.6px, transparent 1.7px),
    radial-gradient(circle at 73% 73%, var(--pip) 1.6px, transparent 1.7px); }
.dom-half[data-pips="3"]::before {
  background-image:
    radial-gradient(circle at 27% 27%, var(--pip) 1.6px, transparent 1.7px),
    radial-gradient(circle at 50% 50%, var(--pip) 1.6px, transparent 1.7px),
    radial-gradient(circle at 73% 73%, var(--pip) 1.6px, transparent 1.7px); }
.dom-half[data-pips="4"]::before {
  background-image:
    radial-gradient(circle at 27% 27%, var(--pip) 1.6px, transparent 1.7px),
    radial-gradient(circle at 73% 27%, var(--pip) 1.6px, transparent 1.7px),
    radial-gradient(circle at 27% 73%, var(--pip) 1.6px, transparent 1.7px),
    radial-gradient(circle at 73% 73%, var(--pip) 1.6px, transparent 1.7px); }
.dom-half[data-pips="5"]::before {
  background-image:
    radial-gradient(circle at 27% 27%, var(--pip) 1.6px, transparent 1.7px),
    radial-gradient(circle at 73% 27%, var(--pip) 1.6px, transparent 1.7px),
    radial-gradient(circle at 50% 50%, var(--pip) 1.6px, transparent 1.7px),
    radial-gradient(circle at 27% 73%, var(--pip) 1.6px, transparent 1.7px),
    radial-gradient(circle at 73% 73%, var(--pip) 1.6px, transparent 1.7px); }
.dom-half[data-pips="6"]::before {
  background-image:
    radial-gradient(circle at 27% 25%, var(--pip) 1.6px, transparent 1.7px),
    radial-gradient(circle at 73% 25%, var(--pip) 1.6px, transparent 1.7px),
    radial-gradient(circle at 27% 50%, var(--pip) 1.6px, transparent 1.7px),
    radial-gradient(circle at 73% 50%, var(--pip) 1.6px, transparent 1.7px),
    radial-gradient(circle at 27% 75%, var(--pip) 1.6px, transparent 1.7px),
    radial-gradient(circle at 73% 75%, var(--pip) 1.6px, transparent 1.7px); }

/* The hand. A tile you cannot play is dimmed rather than hidden: knowing what
   you are holding and cannot use is most of the game. */
.dominoes .dom-hand { display: flex; flex-wrap: wrap; gap: .4rem; margin: 1rem 0; padding: 0; }
.dom-hand button.dom-tile { cursor: default; padding: 0; }
.dom-hand button.dom-tile.playable { cursor: pointer; border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent); }
.dom-hand button.dom-tile:disabled { opacity: .5; }
.dominoes .dom-ends { margin: .6rem 0; }
.dominoes .dom-empty { color: var(--muted); }

/* ---- goofspiel ------------------------------------------------------------------ */
/* Real cards, so this reuses the .card markup cribbage uses rather than a
   second card look. Only the layout and the "already spent" state are new. */
.goof { padding: 1rem; }
.goof-prize { text-align: center; margin-bottom: 1rem; }
.goof-prize .card { cursor: default; }
.goof-label { margin: 1.2rem 0 .4rem; font-size: .85rem; }
.goof-row { display: flex; flex-wrap: wrap; gap: .4rem; }
.goof-row.hand { padding-top: 16px; }

/* The prize is a span in a plain block rather than a button in a flex row, and
   a span is inline: width and aspect-ratio do not apply to it, so the card
   collapsed to the size of its text. .card now sets display: inline-block for
   that reason. The row of theirs never showed the fault because a flex
   container blockifies its children. */

/* A rank they have spent is struck through and faded, NOT removed. The gap is
   the information: the whole game is knowing what is left in the other hand,
   and a row that reflows every round is much harder to read at a glance. */
.card.spent { opacity: .3; }
.card.spent .pip { text-decoration: line-through; }
.card.static { cursor: default; }

.goof-history { width: 100%; border-collapse: collapse; margin-top: 1.4rem; font-size: .9rem; }
.goof-history th, .goof-history td { text-align: left; padding: .25rem .5rem; border-bottom: 1px solid var(--line); }
.goof-history caption { text-align: left; padding-bottom: .3rem; }
.goof-history tr.won td { color: var(--accent); font-weight: 600; }
.goof-history tr.tied td { color: var(--muted); font-style: italic; }

/* ---- battleship ----------------------------------------------------------------------- */
/* Two grids, the same size, told apart by more than position: yours shows your
   ships, theirs shows only the squares you have fired at. A square you have not
   fired at is water because the state does not mention it, not because the page
   is hiding something. */

.bs { display: grid; gap: 1rem; justify-items: center; }
.bs-grids { display: grid; gap: 1.2rem; grid-template-columns: 1fr; width: min(96vw, 46rem); }
@media (min-width: 46rem) { .bs-grids { grid-template-columns: 1fr 1fr; } }

.bs-side { display: grid; gap: .4rem; justify-items: center; }
.bs-who { margin: 0; font: 600 .95rem/1 var(--body); color: var(--muted); }
.bs-side.mine .bs-who { color: var(--ink); }

.bs-grid { display: grid; gap: 1px; background: var(--line); border: 1px solid var(--line);
           border-radius: 6px; padding: 1px; width: 100%; }
.bs-labels, .bs-row { display: grid; grid-template-columns: 1.3rem repeat(10, 1fr); gap: 1px; }
.bs-labels span, .bs-rownum { display: grid; place-items: center; font: 600 .7rem/1 var(--body);
                              color: var(--muted); background: var(--surface); }

.bs-cell { aspect-ratio: 1; border: 0; padding: 0; background: var(--surface-2); cursor: default;
           position: relative; }
.bs-grid:not(.own) .bs-cell:not(:disabled) { cursor: crosshair; }
.bs-grid:not(.own) .bs-cell:not(:disabled):hover { background: var(--line); }
.bs-cell:focus-visible { outline: 3px solid var(--accent); outline-offset: -2px; z-index: 2; }

/* your own ships, and the shots that have landed on them */
.bs-cell.ship { background: var(--muted); }
.bs-cell.sunk { background: var(--walnut-deep); }

/* A HIT IS A SHAPE AS WELL AS A COLOUR: a cross for a hit, a dot for a miss, so
   the board reads without relying on either. */
.bs-cell.hit::after, .bs-cell.miss::after, .bs-cell.sunk::after {
    content: ''; position: absolute; inset: 22%; }
.bs-cell.hit { background: var(--danger); }
.bs-cell.hit::after, .bs-cell.sunk::after {
    background: linear-gradient(45deg, transparent 43%, var(--accent-ink) 43% 57%, transparent 57%),
                linear-gradient(-45deg, transparent 43%, var(--accent-ink) 43% 57%, transparent 57%); }
.bs-cell.miss::after { border-radius: 50%; background: var(--muted); inset: 36%; }
.bs-cell.hinted { box-shadow: inset 0 0 0 2px var(--brass); }

/* placing */
.bs-cell.preview { background: var(--accent); }
.bs-cell.refused { background: var(--danger); opacity: .55; }

.bs-fleet { list-style: none; display: flex; flex-wrap: wrap; gap: .3rem .6rem; padding: 0; margin: 0;
            font-size: .78rem; color: var(--muted); }
.bs-tally.sunk { text-decoration: line-through; text-decoration-thickness: 2px; opacity: .6; }

.bs-setup { display: grid; gap: .6rem; justify-items: center; width: min(96vw, 40rem); }
.bs-tray { list-style: none; display: flex; flex-wrap: wrap; gap: .4rem; padding: 0; margin: 0;
           justify-content: center; }
.bs-ship-button { display: grid; gap: .2rem; justify-items: center; padding: .35rem .5rem;
                  border: 1px solid var(--line); border-radius: 6px; background: var(--card);
                  color: var(--card-ink); font: 600 .75rem/1 var(--body); cursor: pointer; }
.bs-ship.picked .bs-ship-button { border-color: var(--accent); box-shadow: 0 0 0 2px var(--surface-2); }
.bs-ship.done .bs-ship-button { opacity: .45; text-decoration: line-through; }
.bs-ship-pips { display: flex; gap: 2px; }
.bs-ship-pips i { width: .5rem; height: .5rem; background: var(--muted); border-radius: 1px; }
.bs-setup-actions { display: flex; flex-wrap: wrap; gap: .4rem; justify-content: center; align-items: center; }
.bs .small { font-size: .8rem; max-width: 48ch; margin: 0 auto; text-align: center; }

@media (prefers-reduced-motion: reduce) {
    .bs-cell { transition: none; }
}

svg.game-icon.big {
    max-width: 14em;
}
