/* Go of Go: shared styles for the overview, board and how-to-play pages.
   Plain CSS, no build. Colors are tokens; dark mode follows the system unless
   the viewer picked one with the theme button (data-theme on <html>).

   One meaning per color (DESIGN principle 5): black and white are the two
   sides, gold (--gold, --gold-hi) marks what is truly won, amber (--amber)
   means the engine is judging, red (--bad) means captured, blue (--live)
   means a move just landed, frost (--frozen) means the cooldown. */

:root {
  --bg: #f4efe4;
  --card: #fffaf1;
  --ink: #1f1b16;
  --muted: #6d6458;
  --line: #e2d8c6;
  --accent: #2f6fdb;
  --accent-ink: #fff;
  --amber: #e8960c;
  --good: #1f8a4c;
  --bad: #c0392b;
  --frozen: #6ea8cf;
  --wood: #e0b872;
  --wood-2: #d4a85c;
  --wood-line: rgba(70, 45, 12, 0.55);
  --wood-ink: #4a3210;
  --ring-bg: rgba(70, 45, 12, 0.14);
  --mini: #e8c486;
  --mini-edge: rgba(70, 45, 12, 0.45);
  --live: #2f6fdb;
  --gold: #a8812a;
  --gold-hi: #d9b45a;
  --cord-1: #c49a5c;
  --cord-2: #9a7036;
  --shadow: 0 1px 2px rgba(40, 25, 5, 0.12), 0 4px 14px rgba(40, 25, 5, 0.08);
  --radius: 12px;
  color-scheme: light;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #14120f;
    --card: #1d1a16;
    --ink: #efe8dc;
    --muted: #a69c8c;
    --line: #34302a;
    --accent: #6c9cf0;
    --accent-ink: #0d1220;
    --amber: #f5ab2e;
    --good: #45c07a;
    --bad: #ef6b5b;
    --frozen: #7fb6dc;
    --wood: #9b7741;
    --wood-2: #8a6836;
    --wood-line: rgba(25, 14, 2, 0.6);
    --wood-ink: #f3e2c2;
    --ring-bg: rgba(20, 10, 0, 0.25);
    --mini: #c7a065;
    --mini-edge: rgba(10, 5, 0, 0.75);
    --live: #7fb0ff;
    --gold: #d8b45a;
    --gold-hi: #f3d68a;
    --cord-1: #b48a4f;
    --cord-2: #7d5a2a;
    --shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 6px 18px rgba(0, 0, 0, 0.3);
    color-scheme: dark;
  }
}
:root[data-theme="dark"] {
  --bg: #14120f;
  --card: #1d1a16;
  --ink: #efe8dc;
  --muted: #a69c8c;
  --line: #34302a;
  --accent: #6c9cf0;
  --accent-ink: #0d1220;
  --amber: #f5ab2e;
  --good: #45c07a;
  --bad: #ef6b5b;
  --frozen: #7fb6dc;
  --wood: #9b7741;
  --wood-2: #8a6836;
  --wood-line: rgba(25, 14, 2, 0.6);
  --wood-ink: #f3e2c2;
  --ring-bg: rgba(20, 10, 0, 0.25);
  --mini: #c7a065;
  --mini-edge: rgba(10, 5, 0, 0.75);
  --live: #7fb0ff;
  --gold: #d8b45a;
  --gold-hi: #f3d68a;
  --cord-1: #b48a4f;
  --cord-2: #7d5a2a;
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 6px 18px rgba(0, 0, 0, 0.3);
  color-scheme: dark;
}

* { box-sizing: border-box; }
html, body { margin: 0; }
body {
  background: var(--bg);
  color: var(--ink);
  font: 15px/1.45 ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  overflow-x: hidden;
  -webkit-tap-highlight-color: transparent;
}
a { color: var(--accent); }
.num { font-variant-numeric: tabular-nums; }
.muted { color: var(--muted); }
kbd { font: inherit; font-size: 11.5px; border: 1px solid var(--line); border-bottom-width: 2px; border-radius: 5px; padding: 0 5px; background: var(--card); }

/* ---------- top bar (48 px, the same on every page) ---------- */
.top {
  display: flex; align-items: center; gap: 12px;
  height: 48px; padding: 0 16px; max-width: 1400px; margin: 0 auto;
}
body.shell > .top { max-width: none; }
.brand {
  display: flex; align-items: center; gap: 8px;
  font-weight: 750; font-size: 18px; letter-spacing: -0.01em;
  color: var(--ink); text-decoration: none; white-space: nowrap;
}
.brand .logo {
  width: 22px; height: 22px; border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #777 0, #222 40%, #000 80%);
  box-shadow: 9px 3px 0 -3px #f4f1ea, 9px 3px 0 -2px #bbb;
}
.top nav { margin-left: auto; display: flex; gap: 14px; align-items: center; font-size: 14px; }
.top nav a { color: var(--muted); text-decoration: none; white-space: nowrap; }
.top nav a:hover { color: var(--ink); }
@media (max-width: 560px) {
  .top { gap: 8px; }
  .top nav { gap: 10px; font-size: 13px; }
  .top nav .opt { display: none; }
}
.icon-btn {
  border: 1px solid var(--line); background: var(--card); color: var(--ink);
  border-radius: 999px; width: 30px; height: 30px; cursor: pointer; font-size: 14px;
}

.wrap { max-width: 1400px; margin: 0 auto; padding: 0 16px 32px; overflow-x: clip; }
.card {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow); padding: 12px 14px;
}
.card h2 { font-size: 12px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--muted); margin: 0 0 8px; font-weight: 650; }

.chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 10px; border-radius: 999px; font-size: 13px; font-weight: 600;
  background: var(--card); border: 1px solid var(--line); white-space: nowrap;
}
.dot { width: 9px; height: 9px; border-radius: 50%; display: inline-block; flex: none; }
.dot.live { background: var(--live); box-shadow: 0 0 0 3px color-mix(in srgb, var(--live) 30%, transparent); }
.dot.down { background: var(--muted); }

/* ---------- stones (the same sprites everywhere, the Key included) ---------- */
.stone-b, [data-state="black"] > .stone, .st.black, .ghost.black {
  background: radial-gradient(circle at 34% 30%, #7a7a7a 0, #2b2b2b 28%, #0b0b0b 62%, #000 100%);
  box-shadow: 0.06em 0.1em 0.18em rgba(0, 0, 0, 0.45);
}
.stone-w, [data-state="white"] > .stone, .st.white, .ghost.white {
  background: radial-gradient(circle at 34% 30%, #ffffff 0, #f4f2ec 35%, #d9d5cb 75%, #b8b3a7 100%);
  box-shadow: 0.06em 0.1em 0.18em rgba(0, 0, 0, 0.4);
}

/* =====================================================================
   The shell (DESIGN.md): one grid for / and /board/{i}.
   Desktop: | left 280 | stage | right 320 |; the stage is the 64 px flag
   strip over the board square, the same box in both views. The board's
   side is the smaller of the stage width and the height under the top bar
   and the strip. Phone: stage, then the left column, then the right.
   ===================================================================== */
.shell-grid {
  --col-l: 280px; --col-r: 320px; --gap: 20px; --strip: 64px;
  display: flex; flex-direction: column; gap: 14px; padding: 4px 16px 24px;
  overflow-x: clip; /* a shake or a gold burst may reach into the gutter, never past the page */
}
.stage { position: relative; container-type: inline-size; --side: 100cqw; width: 100%; min-width: 0; display: flex; flex-direction: column; align-items: center; }
.flagstrip { position: relative; width: var(--side); height: var(--strip); flex: none; display: grid; grid-template-rows: 44px 20px; }
.flagstrip[hidden] { display: grid; visibility: hidden; } /* the box stays put without a flag */
.board-sq { position: relative; width: var(--side); height: var(--side); flex: none; container-type: size; }
.col { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.stage-tools { display: none; }

@media (min-width: 1000px) {
  .shell-grid {
    display: grid; grid-template-columns: var(--col-l) minmax(0, 1fr) var(--col-r); grid-template-rows: minmax(0, 1fr);
    column-gap: var(--gap); padding: 8px 16px 16px;
  }
  .col-l { grid-column: 1; grid-row: 1; }
  .stage { grid-column: 2; grid-row: 1; --side: min(100cqw, calc(100dvh - 48px - var(--strip) - 24px)); }
  .col-r { grid-column: 3; grid-row: 1; }
  .col { align-self: start; max-height: 100%; overflow-y: auto; overscroll-behavior: contain; padding: 0 2px 2px; }
  .intro { display: none !important; } /* DESIGN: no intro on desktop; the top bar's How to play is enough */
}
@media (min-width: 1000px) and (max-width: 1279px) {
  .shell-grid { --col-l: 236px; --col-r: 268px; --gap: 14px; }
}
/* a laptop: the page is exactly the window, nothing scrolls but the side columns */
@media (min-width: 1000px) and (min-height: 560px) {
  html:has(body.shell), body.shell { height: 100%; overflow: hidden; }
  body.shell .shell-grid { height: calc(100dvh - 48px); }
}
/* phones and narrow windows: stacked, the page scrolls */
@media (max-width: 999px) {
  .stage-tools { display: flex; align-items: center; justify-content: space-between; gap: 10px; width: var(--side); margin-top: 8px; font-size: 13px; }
}

.btn {
  border: 1px solid var(--line); background: var(--card); color: var(--ink);
  font: inherit; font-weight: 650; padding: 9px 18px; border-radius: 10px; cursor: pointer;
  box-shadow: var(--shadow);
}
.btn:hover { border-color: var(--accent); }
.btn:active { transform: translateY(1px); }
.btn[disabled] { opacity: 0.5; cursor: default; }
.btn-sm { padding: 5px 12px; font-size: 13px; border-radius: 999px; box-shadow: none; white-space: nowrap; flex: none; display: inline-flex; align-items: center; gap: 5px; }
.btn-sm svg { width: 14px; height: 14px; }
.hint-touch { display: none; }
@media (hover: none) { .hint-touch { display: inline; } .hint-mouse { display: none; } }
#zoom[aria-pressed="true"] { border-color: var(--accent); color: var(--accent); }

/* ---------- the flag strip: the rope row (44 px) and one line of words (20 px) ---------- */
.strip-rope { position: relative; height: 44px; }
.strip-cap {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  height: 20px; line-height: 20px; font-size: 13px; white-space: nowrap; min-width: 0;
}
.strip-say { min-width: 0; overflow: hidden; text-overflow: ellipsis; font-weight: 650; }
.strip-say b { font-weight: 650; }
.strip-side { flex: none; display: inline-flex; align-items: center; gap: 8px; color: var(--muted); }
.strip-side b { color: var(--ink); }
.strip-cd { font-weight: 750; color: var(--ink); }
.needle-cd { font-weight: 800; color: var(--ink); }
.needle-p { display: inline-flex; align-items: center; gap: 5px; }
.needle-p .pip { width: 10px; height: 10px; margin: 0; }
/* the epoch's last ten seconds: the countdown, big, on the middle of the rope */
.needle-big {
  position: absolute; left: 50%; top: 50%; z-index: 4; transform: translate(-50%, -50%);
  font-size: 28px; line-height: 34px; font-weight: 800; letter-spacing: -0.01em; color: var(--ink);
  padding: 0 14px; border-radius: 999px; background: var(--bg); box-shadow: 0 0 0 1px var(--line), 0 4px 14px rgba(30, 18, 2, 0.15);
  display: none;
}
.needle-card[data-final="1"] .needle-big { display: block; animation: bigin 0.35s cubic-bezier(.3, 1.4, .5, 1); }
.needle-card[data-final="1"] .needle-cd { display: none; }
@keyframes bigin { from { transform: translate(-50%, -50%) scale(0.5); opacity: 0; } }
.why {
  font: inherit; font-size: 11.5px; line-height: 16px; height: 18px; padding: 0 8px; cursor: pointer;
  border: 1px solid var(--line); background: var(--card); color: var(--muted); border-radius: 999px;
}
.why:hover, .why[aria-expanded="true"] { color: var(--ink); border-color: var(--muted); }
.why-pop {
  position: absolute; right: 0; top: calc(var(--strip) + 2px); z-index: 30; width: min(360px, 100%);
  padding: 10px 14px; border-radius: 10px; font-size: 13px; line-height: 1.45;
  background: var(--card); border: 1px solid var(--line); box-shadow: 0 10px 30px rgba(30, 18, 2, 0.22);
}
.why-pop[hidden] { display: none; }
.why-pop p { margin: 0 0 6px; }
.why-pop p:last-child { margin: 0; }

/* =====================================================================
   The rope: a board's flag and the epoch needle (FLAGS §3). Markup from
   G.ropeBuild; G.ropeSet tweens the flag (JS, so the cord's sag and the
   pulled part follow the same curve). --f is the flag in [-1, 1] (+1 is
   Black's end, on the right); --ry the flag's drop on the sagging cord.
   ===================================================================== */
.rope { position: relative; height: 44px; --pad: 52px; --stone: 30px; } /* the lane stops 22 px short of each end stone: the flag never sits on its halo */
.rope-end {
  position: absolute; top: 50%; width: var(--stone); height: var(--stone); margin-top: calc(var(--stone) / -2);
  border-radius: 50%; z-index: 2; transition: transform 0.25s;
}
.rope-end.w { left: 0; background: radial-gradient(circle at 34% 30%, #fff 0, #f4f2ec 35%, #d9d5cb 75%, #b8b3a7 100%); box-shadow: 0 1px 2px rgba(0,0,0,.35); }
.rope-end.b { right: 0; background: radial-gradient(circle at 34% 30%, #7a7a7a 0, #2b2b2b 28%, #0b0b0b 62%, #000 100%); box-shadow: 0 1px 2px rgba(0,0,0,.45); }
.rope-end::after { content: ""; position: absolute; inset: -4px; border-radius: 50%; border: 2px solid var(--gold-hi); opacity: 0; }
.rope-jerk { position: absolute; inset: 0; }
.rope-svg { position: absolute; left: calc(var(--stone) / 2); right: calc(var(--stone) / 2); top: 0; height: 44px; width: calc(100% - var(--stone)); overflow: visible; pointer-events: none; }
.rope-svg path { fill: none; vector-effect: non-scaling-stroke; stroke-linecap: round; }
.rope-svg .cord { stroke: var(--cord-1); stroke-width: 7px; }
.rope-svg .twist { stroke: var(--cord-2); stroke-width: 7px; stroke-dasharray: 2.5 3.5; opacity: 0.85; }
.rope-svg .pull { stroke-width: 7px; opacity: 0.92; }
.rope[data-side="black"] .rope-svg .pull { stroke: #14110d; }
.rope[data-side="white"] .rope-svg .pull { stroke: #fbf8f1; opacity: 1; }
.rope[data-side="white"] .rope-svg .pull-edge { stroke: #8c7f6a; stroke-width: 10px; }
.rope-svg .pull-edge { stroke: transparent; stroke-width: 9px; }
/* a highlight along the top of Black's pulled cord, so it reads as solid black on a dark page */
.rope-svg .gloss { stroke: transparent; stroke-width: 1.6px; transform: translateY(-1.8px); }
.rope[data-side="black"] .rope-svg .gloss { stroke: rgba(255, 255, 255, 0.2); }
/* dark: the black side's pull and notches get a light rim, or they vanish */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .rope[data-side="black"] .rope-svg .pull-edge { stroke: rgba(255, 245, 225, 0.22); }
  :root:not([data-theme="light"]) .rope[data-side="black"] .rope-svg .pull { stroke: #2a2623; opacity: 1; }
  :root:not([data-theme="light"]) .rope[data-side="black"] .rope-svg .gloss { stroke: rgba(255, 255, 255, 0.28); }
  :root:not([data-theme="light"]) .rope[data-side="black"] .rope-tick.won { background: radial-gradient(circle at 35% 30%, #9a9a9a, #222 62%); box-shadow: 0 0 0 1px rgba(255, 250, 238, 0.3); }
}
:root[data-theme="dark"] .rope[data-side="black"] .rope-svg .pull-edge { stroke: rgba(255, 245, 225, 0.22); }
:root[data-theme="dark"] .rope[data-side="black"] .rope-svg .pull { stroke: #2a2623; opacity: 1; }
:root[data-theme="dark"] .rope[data-side="black"] .rope-svg .gloss { stroke: rgba(255, 255, 255, 0.28); }
:root[data-theme="dark"] .rope[data-side="black"] .rope-tick.won { background: radial-gradient(circle at 35% 30%, #9a9a9a, #222 62%); box-shadow: 0 0 0 1px rgba(255, 250, 238, 0.3); }
.rope-lane { position: absolute; left: var(--pad); right: var(--pad); top: 0; bottom: 0; container-type: inline-size; }
.rope-tick { position: absolute; top: 50%; width: 1px; height: 7px; margin: 9px 0 0 -0.5px; background: var(--muted); opacity: 0.6; }
.rope-tick.mid { height: 24px; margin-top: -12px; width: 2px; background: var(--ink); opacity: 0.45; }
.rope-tick.end { height: 20px; margin-top: -10px; opacity: 0.6; }
/* notches already won: a 6 px bead of the side, ringed in the other colour */
.rope-tick.won { width: 6px; height: 6px; margin: 9px 0 0 -3px; border-radius: 50%; opacity: 1; }
.rope[data-side="black"] .rope-tick.won { background: radial-gradient(circle at 35% 30%, #777, #121110 62%); box-shadow: 0 0 0 1px rgba(255, 250, 238, 0.75); }
.rope[data-side="white"] .rope-tick.won { background: #fbf8f1; box-shadow: 0 0 0 1px #6f6450; }
/* the gap before the last notch on each side: it pulses amber while judged */
.rope-gap { position: absolute; top: 50%; height: 16px; margin-top: -8px; border-radius: 4px; background: var(--amber); opacity: 0; }
.rope-ride { position: absolute; left: 50%; top: 0; bottom: 0; width: 0; transform: translate(calc(var(--fx, 0) * 50cqw), var(--ry, 0px)); will-change: transform; }
.rope-flag { position: absolute; left: 0; top: 0; bottom: 0; width: 0; }
.rope-pole { position: absolute; left: -1px; width: 2px; top: 2px; height: 20px; background: var(--ink); border-radius: 1px; }
.rope-pennant { position: absolute; left: 1px; top: 2px; width: 22px; height: 16px; overflow: visible; transform-origin: 0 50%; }
.rope-pennant path { fill: var(--gold-hi); stroke: var(--ink); stroke-width: 1px; stroke-linejoin: round; }
.rope[data-side="white"] .rope-pennant { transform: scaleX(-1); }
.rope-knot { position: absolute; left: -5px; top: 50%; width: 10px; height: 10px; margin-top: -5px; border-radius: 50%; background: var(--gold-hi); box-shadow: 0 0 0 1px var(--ink), 0 1px 2px rgba(0, 0, 0, 0.3); }
/* tied down: slack, pegged to the middle, no colour */
.rope[data-tied="1"] .rope-svg .cord, .rope[data-tied="1"] .rope-svg .twist { opacity: 0.45; }
.rope[data-tied="1"] .rope-knot { border-radius: 2px; background: var(--muted); transform: rotate(45deg); box-shadow: none; }
.rope[data-tied="1"] .rope-pennant path { fill: var(--muted); stroke: none; }
/* tension: from notch 7 the pennant flutters, at the last notch the flag trembles */
.rope[data-near="1"] .rope-pennant { animation: flutter 2.4s ease-in-out infinite; }
.rope[data-side="white"][data-near="1"] .rope-pennant { animation-name: flutter-w; }
@keyframes flutter { 0%, 100% { transform: rotate(-6deg); } 50% { transform: rotate(6deg); } }
@keyframes flutter-w { 0%, 100% { transform: scaleX(-1) rotate(-6deg); } 50% { transform: scaleX(-1) rotate(6deg); } }
.rope[data-last="1"] .rope-flag { animation: tremble 0.24s steps(1) infinite; }
@keyframes tremble { 0% { transform: translateX(-1.5px); } 50% { transform: translateX(1.5px); } }
.rope[data-heavy="1"][data-side="black"] .rope-end.b::after, .rope[data-heavy="1"][data-side="white"] .rope-end.w::after { opacity: 0.5; animation: heavy 1.3s ease-in-out infinite alternate; }
@keyframes heavy { from { opacity: 0.15; } to { opacity: 0.8; } }
/* judging: the flag holds still, the last gap pulses amber, the end stone waits */
.rope[data-status="judging"] .rope-pennant { animation: none; }
.rope[data-status="judging"] .rope-flag { animation: tremble 0.24s steps(1) infinite; }
.rope[data-status="judging"][data-side="black"] .rope-gap.b, .rope[data-status="judging"][data-side="white"] .rope-gap.w { animation: gap 1.2s ease-in-out infinite; }
@keyframes gap { 0%, 100% { opacity: 0.12; } 50% { opacity: 0.75; } }
.rope[data-status="judging"][data-side="black"] .rope-end.b, .rope[data-status="judging"][data-side="white"] .rope-end.w { transform: scale(1.15); }
.rope[data-status="judging"][data-side="black"] .rope-end.b::after, .rope[data-status="judging"][data-side="white"] .rope-end.w::after { opacity: 1; border-color: var(--amber); animation: none; }
/* won: the end stone keeps a gold ring */
.rope[data-status^="locked"] .rope-end::after { opacity: 0; animation: none; }
.rope[data-status="locked_black"] .rope-end.b::after, .rope[data-status="locked_white"] .rope-end.w::after { opacity: 1; border-color: var(--gold-hi); }
.rope[data-status^="locked"] .rope-pennant, .rope[data-status^="locked"] .rope-flag { animation: none; }
/* won: the flag stays planted at the end, its pole tipped in gold */
.rope[data-status^="locked"] .rope-pole::before { content: ""; position: absolute; left: -2px; top: -4px; width: 6px; height: 6px; border-radius: 50%; background: var(--gold-hi); box-shadow: 0 0 0 1px var(--ink); }
.rope[data-status^="locked"] .rope-pennant path { fill: var(--gold-hi); }
/* a pull: a 90 ms jerk that overshoots 6 px, then settles */
.rope.jerk-b .rope-jerk { animation: jerk-b 0.42s ease-out; }
.rope.jerk-w .rope-jerk { animation: jerk-w 0.42s ease-out; }
@keyframes jerk-b { 21% { transform: translateX(6px); } 48% { transform: translateX(-1.5px); } 72% { transform: translateX(0.5px); } }
@keyframes jerk-w { 21% { transform: translateX(-6px); } 48% { transform: translateX(1.5px); } 72% { transform: translateX(-0.5px); } }
.rope.twitch .rope-jerk { animation: twitch 0.35s ease-out; }
@keyframes twitch { 30% { transform: translateY(1.5px); } 65% { transform: translateY(-1px); } }
/* held: a pull that would take the last notch from an old reading strains
   against the end and springs back; the end stone flashes amber */
.rope.held-b .rope-flag { animation: held-b 0.85s ease-out; }
.rope.held-w .rope-flag { animation: held-w 0.85s ease-out; }
@keyframes held-b { 18% { transform: translateX(14px); } 32% { transform: translateX(8px); } 46% { transform: translateX(13px); } 62% { transform: translateX(4px); } }
@keyframes held-w { 18% { transform: translateX(-14px); } 32% { transform: translateX(-8px); } 46% { transform: translateX(-13px); } 62% { transform: translateX(-4px); } }
.rope.held-b .rope-end.b::after, .rope.held-w .rope-end.w::after { border-color: var(--amber); animation: flash 0.85s ease-out; }
@keyframes flash { 0%, 40% { opacity: 1; transform: scale(1.25); } 100% { opacity: 0; transform: scale(1); } }
/* the last notch: the flag slams into the end stone, the stone pops, its gold ring flares to 3x */
.rope.end[data-side="black"] .rope-flag { animation: slam-b 0.38s cubic-bezier(.2, .9, .3, 1); }
.rope.end[data-side="white"] .rope-flag { animation: slam-w 0.38s cubic-bezier(.2, .9, .3, 1); }
@keyframes slam-b { 0% { transform: translateX(-6px); } 30% { transform: translateX(14px); } 60% { transform: translateX(-2px); } }
@keyframes slam-w { 0% { transform: translateX(6px); } 30% { transform: translateX(-14px); } 60% { transform: translateX(2px); } }
.rope.end[data-side="black"] .rope-end.b, .rope.end[data-side="white"] .rope-end.w { animation: pop 0.45s cubic-bezier(.3, 1.4, .5, 1); }
@keyframes pop { 45% { transform: scale(1.35); } }
.rope.end[data-side="black"] .rope-end.b::after, .rope.end[data-side="white"] .rope-end.w::after { border-color: var(--gold-hi); animation: burst 0.6s ease-out; }
@keyframes burst { 0% { opacity: 1; transform: scale(1); border-width: 3px; } 100% { opacity: 0; transform: scale(3); border-width: 1px; } }
/* the epoch's last ten seconds: the leading end stone swells, the cord's tension pulses each second */
.rope[data-final="1"][data-side="black"] .rope-end.b, .rope[data-final="1"][data-side="white"] .rope-end.w { transform: scale(1.15); }
.rope[data-final="1"][data-side="black"] .rope-end.b::after, .rope[data-final="1"][data-side="white"] .rope-end.w::after { opacity: 1; border-color: var(--gold-hi); animation: heavy 0.5s ease-in-out infinite alternate; }
.rope[data-final="1"] .rope-svg .pull { animation: tension 1s ease-out infinite; }
@keyframes tension { 0% { stroke-width: 11px; } 45%, 100% { stroke-width: 7px; } }
.needle-rope.tick .rope-knot { animation: knot 0.4s ease-out; }
@keyframes knot { 30% { transform: scale(1.3); } }
@media (prefers-reduced-motion: reduce) {
  .rope *, .rope *::after { animation: none !important; transition: none !important; }
}

/* ---------- overview: the epoch card and the key (left column) ---------- */
.epoch { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.epoch .big { font-size: 22px; font-weight: 750; letter-spacing: -0.01em; }
.phase.playing { color: var(--good); }
.phase.cooldown { color: var(--frozen); }
.counts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 4px 10px; margin-top: 10px; font-size: 13.5px; color: var(--muted); }
.counts .cnt { display: flex; align-items: center; gap: 7px; white-space: nowrap; }
.counts .cnt[hidden] { display: none; }
.counts b { color: var(--ink); min-width: 2.2em; text-align: right; }
.late-btn { margin-top: 10px; }
.late-btn[hidden] { display: none; } /* .btn-sm sets display, which would beat [hidden] */
.sw { width: 12px; height: 12px; border-radius: 50%; display: inline-block; flex: none; }
.sw.open { border-radius: 3px; background: var(--mini); box-shadow: inset 0 0 0 1px var(--mini-edge); }
.sw.lean { border-radius: 3px; background: var(--mini); border: 3px solid #111; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .sw.lean { box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.3); } }
:root[data-theme="dark"] .sw.lean { box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.3); }
.sw.live { background: transparent; border: 1px solid #4a8bf5; border-radius: 3px; }
.sw.judging { border: 2px solid var(--amber); border-radius: 3px; background: color-mix(in srgb, var(--amber) 25%, transparent); }
.sw.stone-b, .sw.stone-w { font-size: 12px; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .sw.stone-b, :root:not([data-theme="light"]) .ticker .ic.stone-b { box-shadow: 0 0 0 1px rgba(255, 245, 225, 0.28); } }
:root[data-theme="dark"] .sw.stone-b, :root[data-theme="dark"] .ticker .ic.stone-b { box-shadow: 0 0 0 1px rgba(255, 245, 225, 0.28); }
.sw.frozen { background: repeating-linear-gradient(45deg, var(--frozen) 0 2px, transparent 2px 4px); border: 1px solid var(--frozen); border-radius: 2px; }
.sw.mini { border-radius: 3px; background: var(--mini); box-shadow: 0 0 0 1px var(--mini-edge); position: relative; }
.sw.mini::after { content: ""; position: absolute; left: 50%; top: 50%; width: 4px; height: 4px; margin: -2px; border-radius: 50%; background: var(--wood-ink); opacity: 0.45; }
.sw.cap { background: var(--bad); border-radius: 50%; }
.legend { display: grid; grid-template-columns: 1fr; gap: 6px 10px; font-size: 13px; }
.legend span { display: flex; align-items: center; gap: 8px; }
.key-note { font-size: 12.5px; color: var(--muted); margin: 10px 0 0; line-height: 1.4; }

.gauge {
  position: relative; height: 12px; border-radius: 999px; overflow: hidden;
  background: linear-gradient(90deg, #f3f0e8, #ddd8cc); border: 1px solid var(--line);
}
.gauge .fill {
  position: absolute; inset: 0 auto 0 0; width: 50%;
  background: linear-gradient(90deg, #000, #333);
  transition: width 0.8s cubic-bezier(.2,.8,.2,1);
}
.gauge .mark { position: absolute; top: -2px; bottom: -2px; width: 1px; background: var(--muted); opacity: 0.5; }
.gauge.none .fill { opacity: 0.15; }

/* ---------- overview: the macro board ---------- */
/* Each point is a mini board painted on canvas.thumbs (overview.js); the
   cells (a.pt, the contract hooks) sit on top and carry the macro stone,
   the judging frame and the frozen haze. The frame's margin is the goban's
   label margin (0.75 of 20.5 units), so the big board's 19x19 grid sits
   exactly where a game's 19x19 grid sits on its own page. */
.macro-scroll { width: 100%; height: 100%; }
.macro-frame {
  position: relative; width: 100%; aspect-ratio: 1; padding: 3.6585%;
  background: linear-gradient(135deg, var(--wood) 0%, var(--wood-2) 100%);
  border-radius: 8px; box-shadow: var(--shadow); transition: box-shadow 0.6s;
}
.macro-scroll.zoomed {
  overflow: auto; border-radius: 10px;
  overscroll-behavior: contain; -webkit-overflow-scrolling: touch; box-shadow: var(--shadow);
}
.macro-scroll:not(.zoomed) .macro-frame { height: 100%; }
.macro-scroll.zoomed .macro-frame { width: 240%; max-width: none; }
.macro {
  position: relative;
  display: grid; grid-template-columns: repeat(19, 1fr); aspect-ratio: 1;
  width: 100%; touch-action: manipulation; container-type: inline-size;
}
.macro canvas.thumbs { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 0; }
.macro canvas.thumbs.fx { z-index: 2; }
.pt {
  position: relative; display: block; aspect-ratio: 1; min-width: 0; z-index: 1;
  text-decoration: none; color: inherit; outline: none; font-size: 4.6cqw;
  -webkit-touch-callout: none; -webkit-user-select: none; user-select: none;
}
.pt .ring, .pt .stone, .pt .ghost, .pt .ripple { position: absolute; pointer-events: none; }
.pt .stone, .pt .ghost, .pt .ripple { border-radius: 50%; }

/* locked: the macro stone covers the mini board; hover shows the final position */
.pt .stone { inset: 4%; opacity: 0; transform: scale(0.6); transition: opacity 0.25s, transform 0.25s; }
.pt[data-state="black"] .stone { opacity: 0.95; transform: none; }
.pt[data-state="white"] .stone { opacity: 0.96; transform: none; }
@media (hover: hover) {
  .pt[data-state="black"]:hover .stone, .pt[data-state="white"]:hover .stone { opacity: 0.16; transform: scale(1.06); }
}

/* judging: an amber frame that breathes (opacity only: cheap) */
.pt .ring { inset: 3%; border-radius: 4px; opacity: 0; }
.pt[data-state="judging"] .ring {
  opacity: 1;
  border: max(2px, 0.09em) solid var(--amber);
  background: color-mix(in srgb, var(--amber) 24%, transparent);
}
.pt[data-state="judging"] .ring::after {
  content: ""; position: absolute; inset: -2px; border-radius: 5px;
  box-shadow: 0 0 0.45em 0.12em var(--amber);
  animation: judgeblink 0.9s ease-in-out infinite alternate;
}
@keyframes judgeblink { from { opacity: 1; } to { opacity: 0.15; } }
@keyframes judgeglow { 50% { box-shadow: inset 0 0 0 4px var(--amber), 0 0 0.9em 0.1em var(--amber); } }

/* undecided boards: the outline is the board's flag (FLAGS §3). Neutral at
   0; then a line in the side's colour, 1 px + 0.35 px a notch (4.5 px at
   most) at 25% + 7.5% a notch (--n = notches pulled, set by overview.js).
   It sits inside the cell (1 px in) so neighbours never overlap, with a
   1 px halo where the side's colour would vanish (black on dark wood, white
   on light). At 8-9 notches it breathes: a heavy outline reads "about to fall". */
.pt[data-state="open"]::before, .pt[data-state="judging"]::before {
  content: ""; position: absolute; inset: 1px; border-radius: 3px; pointer-events: none;
  border: 1px solid transparent; /* a flag at 0: no outline */
  --a: calc(0.25 + 0.075 * var(--n, 0));
  transition: border-color 0.4s, border-width 0.4s;
}
.pt[data-lean][data-state="open"]::before, .pt[data-lean][data-state="judging"]::before { border-width: min(4.5px, calc(1px + var(--n, 0) * 0.35px)); }
.pt[data-lean="black"][data-state="open"]::before, .pt[data-lean="black"][data-state="judging"]::before { border-color: rgb(17 17 17 / var(--a)); }
.pt[data-lean="white"][data-state="open"]::before, .pt[data-lean="white"][data-state="judging"]::before {
  border-color: rgb(255 255 255 / var(--a)); box-shadow: 0 0 0 1px rgb(0 0 0 / calc(0.35 * var(--a)));
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .pt[data-lean="black"]:is([data-state="open"], [data-state="judging"])::before { box-shadow: 0 0 0 1px rgb(255 255 255 / calc(0.25 * var(--a) + 0.06)); }
  :root:not([data-theme="light"]) .pt[data-lean="white"]:is([data-state="open"], [data-state="judging"])::before { box-shadow: none; }
}
:root[data-theme="dark"] .pt[data-lean="black"]:is([data-state="open"], [data-state="judging"])::before { box-shadow: 0 0 0 1px rgb(255 255 255 / calc(0.25 * var(--a) + 0.06)); }
:root[data-theme="dark"] .pt[data-lean="white"]:is([data-state="open"], [data-state="judging"])::before { box-shadow: none; }
.pt[data-hot][data-state="open"]::before { animation: hot 1.2s ease-in-out infinite alternate; }
@keyframes hot { from { opacity: 0.55; } to { opacity: 1; } }

/* frozen: a cold haze over the mini board (never under a finale) */
.pt[data-state="frozen"]::before {
  content: ""; position: absolute; inset: 6%; border-radius: 2px; pointer-events: none;
  background: repeating-linear-gradient(45deg, color-mix(in srgb, var(--frozen) 70%, transparent) 0 2px, transparent 2px 5px);
}

.pt:hover::after, .pt:focus-visible::after {
  content: ""; position: absolute; inset: 0; border-radius: 4px;
  outline: 2px solid var(--accent); outline-offset: -1px; z-index: 3;
}

/* a lock drops a stone with a gold ripple (gold: truly won) */
.pt.drop .stone { animation: drop 0.55s cubic-bezier(.3,1.4,.5,1) both; }
@keyframes drop {
  0% { opacity: 0; transform: translateY(-80%) scale(1.5); }
  60% { opacity: 1; }
  100% { opacity: 0.95; transform: none; }
}
.pt .ripple { inset: 5%; border: 2px solid var(--gold-hi); animation: ripple 1.1s ease-out forwards; z-index: 2; }
.pt .ripple.r2 { animation-delay: 0.18s; opacity: 0; }
@keyframes ripple {
  0% { opacity: 0.95; transform: scale(0.8); }
  100% { opacity: 0; transform: scale(3.2); }
}
/* a capture flashes the removed stones before they clear */
.pt .ghost { inset: 4%; z-index: 2; animation: captured 1.4s ease-in forwards; }
@keyframes captured {
  0%, 30%, 60% { opacity: 1; transform: none; box-shadow: 0 0 0 0.12em var(--bad), 0 0 0.6em 0.1em var(--bad); }
  15%, 45% { opacity: 0.55; }
  100% { opacity: 0; transform: scale(0.2) rotate(40deg); }
}

@media (prefers-reduced-motion: reduce) {
  .pt[data-state="judging"] .ring::after, .pt[data-hot][data-state="open"]::before { animation: none; }
}

/* ---------- overview: peek (docked in the right column on a desktop,
   floating near the cell on a narrow window, a bottom sheet on touch) ---------- */
.peek {
  position: fixed; z-index: 50; left: 0; top: 0; width: 264px;
  background: var(--card); border: 1px solid var(--line); border-radius: 14px;
  box-shadow: 0 10px 34px rgba(30, 18, 2, 0.28), var(--shadow); padding: 10px;
  pointer-events: none; opacity: 0; visibility: hidden; transform: translateY(4px) scale(0.98);
  transition: opacity 0.12s, transform 0.12s, visibility 0s 0.12s;
}
.peek.on { opacity: 1; visibility: visible; transform: none; transition: opacity 0.12s, transform 0.12s; }
.peek-cv { display: block; width: 242px; height: 242px; border-radius: 6px; }
.peek-body { display: grid; gap: 6px; margin-top: 8px; font-size: 13px; }
.peek-h { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.peek-t { font-size: 15px; white-space: nowrap; }
.peek-st { font-size: 12px; padding: 1px 8px; }
.peek-st[data-s="open"] { color: var(--good); }
.peek-st[data-s="judging"] { color: var(--amber); border-color: var(--amber); }
.peek-st[data-s="frozen"] { color: var(--frozen); }
.peek-facts { display: flex; justify-content: space-between; align-items: center; gap: 8px; white-space: nowrap; }
.peek-tm { display: inline-flex; align-items: center; gap: 6px; font-weight: 650; }
.peek-tms { width: 13px; height: 13px; border-radius: 50%; display: inline-block; }
.peek-tms:not(.stone-b):not(.stone-w) { display: none; }
.peek-wr { display: flex; align-items: center; gap: 6px; color: var(--muted); font-size: 11px; }
.peek-wr .gauge { flex: 1; height: 10px; }
.peek-wrt { font-size: 12px; }
.peek-open, .peek-x { display: none; }
.peek.docked {
  position: static; width: auto; padding: 0; border: 0; box-shadow: none; background: none;
  transform: none; transition: none; display: none;
}
.peek.docked.on { display: block; }
.peek.docked .peek-cv { width: 100%; height: auto; aspect-ratio: 1; }
.peek-card { min-height: 0; }
.peek-card:has(.peek.docked.on) .hover-info { display: none; }
.hover-info { font-size: 14px; color: var(--muted); display: flex; align-items: center; justify-content: center; text-align: center; aspect-ratio: 1; max-height: 100%;
  border-radius: 6px; border: 1px dashed var(--line); padding: 16px; }
.hover-info b { color: var(--ink); }
@media (max-width: 999px) { .hover-info { aspect-ratio: auto; min-height: 3em; } }
body[data-finale="on"] .hover-info { aspect-ratio: auto; min-height: 0; border: 0; padding: 0; justify-content: flex-start; text-align: left; }
/* on a phone: a bottom sheet, the board left, the facts right */
.peek.sheet {
  left: 8px !important; right: 8px; top: auto !important; bottom: calc(8px + env(safe-area-inset-bottom)); width: auto;
  pointer-events: auto; display: grid; grid-template-columns: auto 1fr; gap: 12px; align-items: start;
}
.peek.sheet .peek-cv { width: min(46vw, 190px); height: min(46vw, 190px); }
.peek.sheet .peek-body { margin-top: 0; }
.peek.sheet .peek-facts { flex-direction: column; align-items: flex-start; gap: 2px; }
.peek.sheet .peek-open { display: block; text-align: center; text-decoration: none; padding: 7px 10px; margin-top: 2px; }
.peek.sheet .peek-x { display: block; position: absolute; top: -12px; right: -6px; width: 30px; height: 30px; font-size: 18px; line-height: 1; }

/* ---------- overview: happening now ---------- */
.ticker { list-style: none; margin: 0; padding: 0; font-size: 14px; display: flex; flex-direction: column; gap: 4px; }
.ticker li {
  display: flex; align-items: center; gap: 8px; padding: 4px 6px; border-radius: 6px;
  animation: tickin 0.4s ease-out;
}
.ticker li:first-child:not(.empty) { background: color-mix(in srgb, var(--accent) 9%, transparent); }
.ticker .t { margin-left: auto; padding-left: 8px; color: var(--muted); font-size: 12px; font-variant-numeric: tabular-nums; white-space: nowrap; text-align: right; }
.ticker .ic { width: 12px; height: 12px; border-radius: 50%; flex: none; }
.ticker .empty { color: var(--muted); padding-left: 0; }
@keyframes tickin { from { opacity: 0; transform: translateY(-4px); } }

/* ---------- board page: the left column ---------- */
.bp-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.bp-head h1 { margin: 0; font-size: 22px; letter-spacing: -0.01em; }
.bp-sub { font-size: 13px; margin-top: 2px; }
.watch { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: start; gap: 2px 9px; margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--line); font-size: 13.5px; line-height: 1.4; }
.watch-txt { min-width: 0; }
.watch-s { color: var(--muted); }
.watch-cd { grid-column: 2; font-size: 20px; font-weight: 750; color: var(--ink); }
.watch-cd:empty { display: none; }
.watch-ic { width: 12px; height: 12px; margin-top: 4px; border-radius: 50%; flex: none; background: var(--muted); }
.watch[data-kind="live"] .watch-ic { background: var(--live); animation: livedot 1.6s ease-in-out infinite; }
@keyframes livedot { 50% { box-shadow: 0 0 0 5px color-mix(in srgb, var(--live) 0%, transparent); } 0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--live) 55%, transparent); } }
.watch[data-kind="capture"] .watch-ic { background: var(--bad); }
.watch[data-kind="judging"] .watch-ic { width: 14px; height: 14px; background: none; border: 3px solid var(--amber); border-right-color: transparent; animation: spin 0.9s linear infinite; }
.watch[data-kind="judging"] b { color: var(--amber); }
.watch[data-kind^="locked"] .watch-ic { width: 16px; height: 16px; margin-top: 2px; box-shadow: 0 0 0 2px var(--gold-hi); }
.watch[data-kind="locked-black"] .watch-ic { background: radial-gradient(circle at 34% 30%, #7a7a7a 0, #2b2b2b 28%, #0b0b0b 62%, #000 100%); }
.watch[data-kind="locked-white"] .watch-ic { background: radial-gradient(circle at 34% 30%, #fff 0, #f4f2ec 35%, #d9d5cb 75%, #b8b3a7 100%); }
.watch[data-kind="frozen"] .watch-ic { background: var(--frozen); border-radius: 3px; }
@keyframes spin { to { transform: rotate(1turn); } }
@media (prefers-reduced-motion: reduce) { .watch-ic { animation: none !important; } }

.controls { display: grid; gap: 10px; }
.ctl-row { display: flex; gap: 10px; align-items: center; }
.status-box {
  flex: 1; min-width: 0; padding: 8px 12px; border-radius: 10px; border: 1px solid var(--line); min-height: 38px;
  font-weight: 650; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 14px;
}
.status-box:has(#move-status:empty) { border-color: transparent; }
.status-box:has(#move-status:empty)::before { content: "Your move shows here"; display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--muted); font: 400 13px/22px ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; }
.status-box.ok { color: var(--good); border-color: color-mix(in srgb, var(--good) 45%, var(--line)); }
.status-box.warn { color: var(--amber); border-color: color-mix(in srgb, var(--amber) 45%, var(--line)); }
.status-box.err { color: var(--bad); border-color: color-mix(in srgb, var(--bad) 45%, var(--line)); }
.status-hint { font-size: 13px; color: var(--muted); min-height: 1.2em; }
.frozen-link { display: block; font-weight: 650; text-decoration: none; padding: 8px 12px; border-radius: 10px; border: 1px solid var(--line); text-align: center; white-space: nowrap; }
.frozen-link[hidden] { display: none; }
/* a frozen or locked board takes no moves: no Pass, no "click a point" */
body[data-board="done"] #pass, body[data-board="done"] #hint, body[data-board="done"] .ctl-row:has(#move-status:empty), body[data-board="done"] .facts { display: none; }
.final-line { font-size: 16px; font-weight: 700; font-variant-numeric: tabular-nums; }
.final-line[hidden] { display: none; }
.facts { display: grid; grid-template-columns: 1.4fr 1fr 0.8fr; gap: 6px; }
.fact { background: color-mix(in srgb, var(--bg) 60%, var(--card)); border-radius: 10px; padding: 7px 9px; min-width: 0; }
.fact .k { font-size: 11px; text-transform: uppercase; letter-spacing: 0.07em; color: var(--muted); }
.fact .v { font-size: 18px; font-weight: 750; font-variant-numeric: tabular-nums; display: flex; align-items: center; gap: 6px; white-space: nowrap; }
.tomove { position: relative; width: 22px; height: 22px; flex: none; }
.tomove .st { position: absolute; inset: 3px; border-radius: 50%; }
.tomove svg { position: absolute; inset: 0; transform: rotate(-90deg); }
.tomove circle { fill: none; stroke: var(--accent); stroke-width: 2.5; stroke-dasharray: 63; stroke-dashoffset: 63; }
.tomove.tick circle { animation: tempo 1s linear forwards; }
@keyframes tempo { from { stroke-dashoffset: 0; } to { stroke-dashoffset: 63; } }

.stones-row { display: flex; align-items: baseline; gap: 10px; font-size: 13px; }
.stones-row b { font-size: 20px; }
.stonebar { position: relative; height: 8px; border-radius: 999px; background: var(--line); overflow: visible; margin: 8px 0 20px; }
.stonebar .f { position: absolute; inset: 0 auto 0 0; border-radius: 999px; background: var(--ink); transition: width 0.3s; }
.stonebar .tk { position: absolute; top: -4px; bottom: -4px; width: 2px; margin-left: -1px; background: var(--ink); opacity: 0.55; }
.stonebar .tl { position: absolute; top: 12px; font-size: 11px; color: var(--muted); transform: translateX(-50%); white-space: nowrap; }

/* ---------- board page: the right column ---------- */
.engine-card .gauge { height: 10px; }
.engine-t { margin-top: 7px; font-size: 13px; color: var(--muted); overflow-wrap: anywhere; } /* wraps: the move it read is the part people want */
/* FLAGS §8: a reading older than the board says its age and is dimmed, so a
   stale number never looks current. The dim waits 0.8 s, so the usual
   moment between a move and its reading does not flicker; the words do not. */
.engine-age { margin-top: 3px; font-size: 12px; color: var(--muted); font-style: italic; }
.engine-card .gauge, .engine-t, .peek-wr, .peek-wrt, .hood a { transition: opacity 0.2s; }
.engine-card[data-stale] .gauge, .engine-card[data-stale] .engine-t, .peek-wr[data-stale], .peek-wrt[data-stale] { opacity: 0.5; transition: opacity 0.3s ease 0.8s; }
.hood a[data-stale]:not([data-s="black"]):not([data-s="white"]) { opacity: 0.6; transition: opacity 0.3s ease 0.8s; }
.keys-hint { margin: 0; font-size: 12px; color: var(--muted); line-height: 1.9; padding: 0 4px; }

/* the neighbours: the same marks as the big board (flag outline, won stones, judging, frost) */
.hood { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; max-width: 100%; }
.hood a, .hood span.edge {
  aspect-ratio: 1; border-radius: 8px; display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-decoration: none; color: var(--ink); font-size: 12px; font-weight: 650; position: relative;
  background: linear-gradient(135deg, var(--wood) 0%, var(--wood-2) 100%); gap: 3px;
}
.hood a { --fw: 0px; --fc: transparent; box-shadow: inset 0 0 0 var(--fw) var(--fc); }
.hood a[data-lean="black"] { --fw: calc(1px + var(--lean, 0) * 3px); --fc: rgb(14 11 7 / calc(0.35 + 0.65 * var(--lean, 0))); }
.hood a[data-lean="white"] { --fw: calc(1px + var(--lean, 0) * 3px); --fc: rgb(255 253 246 / calc(0.35 + 0.65 * var(--lean, 0))); }
.hood a[data-s="judging"] { --fw: 2px; --fc: var(--amber); background: linear-gradient(color-mix(in srgb, var(--amber) 22%, transparent), color-mix(in srgb, var(--amber) 22%, transparent)), linear-gradient(135deg, var(--wood) 0%, var(--wood-2) 100%); }
.hood a[data-s="frozen"]::before { content: ""; position: absolute; inset: 8%; border-radius: 2px; background: repeating-linear-gradient(45deg, color-mix(in srgb, var(--frozen) 60%, transparent) 0 2px, transparent 2px 5px); }
.hood span.edge { background: transparent; border: 1px dashed var(--line); }
.hood a.me { outline: 3px solid var(--accent); outline-offset: 1px; }
.hood .mini { width: 46%; aspect-ratio: 1; border-radius: 50%; }
.hood .mini:not(.stone-b):not(.stone-w) { width: 10%; background: var(--wood-ink); opacity: 0.3; }
.hood .lab { color: var(--wood-ink); font-size: 11px; }
/* zoom levels: 0 is 3x3 ... 4 is the whole 19x19 big board */
.hood-bar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 10px; }
.hood-zoom, .hood-pad { display: flex; align-items: center; gap: 5px; }
.hood-bar .btn { min-width: 32px; padding-left: 0; padding-right: 0; justify-content: center; text-align: center; }
.hood-bar .btn:disabled { opacity: 0.35; cursor: default; }
.hood[data-zoom="1"] { gap: 4px; }
.hood[data-zoom="2"] { gap: 3px; }
.hood[data-zoom="3"], .hood[data-zoom="4"] { gap: 2px; }
.hood[data-zoom="1"] a, .hood[data-zoom="1"] span.edge { border-radius: 6px; }
.hood[data-zoom="2"] a, .hood[data-zoom="2"] span.edge { border-radius: 4px; }
.hood[data-zoom="3"] a, .hood[data-zoom="3"] span.edge, .hood[data-zoom="4"] a, .hood[data-zoom="4"] span.edge { border-radius: 2px; }
.hood[data-zoom="1"] .lab { font-size: 10px; }
.hood[data-zoom="2"] .lab, .hood[data-zoom="3"] .lab, .hood[data-zoom="4"] .lab { display: none; }
.hood[data-zoom="2"] .mini.stone-b, .hood[data-zoom="2"] .mini.stone-w, .hood[data-zoom="3"] .mini.stone-b, .hood[data-zoom="3"] .mini.stone-w, .hood[data-zoom="4"] .mini.stone-b, .hood[data-zoom="4"] .mini.stone-w { width: 70%; }
.hood[data-zoom="3"] a.me, .hood[data-zoom="4"] a.me { outline-width: 2px; }
.hood .mini.drop { animation: drop 0.6s cubic-bezier(.3, 1.4, .5, 1) both; }

/* ---------- board page: the goban fills the board square ---------- */
.goban {
  width: 100%; height: 100%;
  display: grid; grid-template-columns: 0.75fr repeat(19, 1fr) 0.75fr; grid-template-rows: 0.75fr repeat(19, 1fr) 0.75fr;
  background: linear-gradient(135deg, var(--wood) 0%, var(--wood-2) 100%);
  border-radius: 8px; box-shadow: var(--shadow); position: relative; touch-action: manipulation;
  container-type: size;
}
.goban .lbl {
  display: flex; align-items: center; justify-content: center;
  font-size: 2.2cqw; color: var(--wood-ink); font-weight: 600; opacity: 0.8; user-select: none;
}
.goban button.bp {
  position: relative; border: 0; padding: 0; margin: 0; background: transparent;
  cursor: pointer; min-width: 0; min-height: 0; font-size: 4.9cqw; outline: none;
}
.goban button.bp::before, .goban button.bp::after { content: ""; position: absolute; background: var(--wood-line); pointer-events: none; }
.goban button.bp::before { left: 0; right: 0; top: 50%; height: 1px; transform: translateY(-0.5px); }
.goban button.bp::after { top: 0; bottom: 0; left: 50%; width: 1px; transform: translateX(-0.5px); }
.goban button.bp.c0::before { left: 50%; }
.goban button.bp.c18::before { right: 50%; }
.goban button.bp.r0::after { top: 50%; }
.goban button.bp.r18::after { bottom: 50%; }
.goban button.bp.c0::before, .goban button.bp.c18::before { height: 2px; }
.goban button.bp.r0::after, .goban button.bp.r18::after { width: 2px; }
.goban .hoshi { position: absolute; left: 50%; top: 50%; width: 0.18em; height: 0.18em; margin: -0.09em; border-radius: 50%; background: var(--wood-line); }
.goban .st { position: absolute; inset: 3.5%; border-radius: 50%; z-index: 1; opacity: 0; transform: scale(0.7); }
.goban .bp[data-state="black"] .st, .goban .bp[data-state="white"] .st { opacity: 1; transform: none; transition: transform 0.12s ease-out, opacity 0.12s; }
.goban .bp.last .st::after {
  content: ""; position: absolute; inset: 31%; border-radius: 50%;
  border: max(1.5px, 0.07em) solid var(--accent);
}
.goban .bp.last[data-state="black"] .st::after { border-color: #fff; }
.goban .bp.last[data-state="white"] .st::after { border-color: #111; }
@media (hover: hover) {
  .goban.can-play .bp[data-state="empty"]:hover .st { opacity: 0.45; transform: none; }
}
.goban .bp:focus-visible { box-shadow: inset 0 0 0 2px var(--accent); border-radius: 4px; }
.goban .gone { position: absolute; inset: 3.5%; border-radius: 50%; z-index: 2; animation: gone 1.2s ease-in forwards; pointer-events: none; }
@keyframes gone {
  0%, 40% { opacity: 1; transform: none; box-shadow: 0 0 0 0.12em var(--bad), 0 0 0.5em 0.1em var(--bad); }
  20% { opacity: 0.6; }
  100% { opacity: 0; transform: scale(0.2); box-shadow: 0 0 0 0.12em var(--bad); }
}
.goban .ping {
  position: absolute; inset: 3.5%; border-radius: 50%; z-index: 2; pointer-events: none;
  border: max(2px, 0.08em) solid var(--live); animation: ping 0.85s ease-out forwards;
}
@keyframes ping { from { opacity: 0.9; transform: scale(0.9); } to { opacity: 0; transform: scale(2.6); } }
/* a move on its way: the stone is shown at once, dimmed and pulsing */
.goban .bp[data-pending] .st { opacity: 0.7; transform: none; animation: pend 0.9s ease-in-out infinite; }
@keyframes pend { 50% { opacity: 0.4; } }
.goban .bp.shake .st { opacity: 1; transform: none; }
.goban .bp.shake { animation: shake 0.4s; }
@keyframes shake { 20%, 60% { transform: translateX(-3px); } 40%, 80% { transform: translateX(3px); } }
.goban:not(.can-play) .bp[data-state="empty"] { cursor: not-allowed; }

/* the board's frame: amber while judged, gold once won, frost while frozen */
.overlay { position: absolute; inset: 0; z-index: 5; border-radius: 8px; pointer-events: none; opacity: 0; transition: opacity 0.5s, box-shadow 0.5s; }
.overlay.on { opacity: 1; }
.overlay.judging { box-shadow: inset 0 0 0 3px var(--amber); overflow: hidden; }
/* judging: a slow band of amber light sweeps the board; the grid dims, the stones keep full contrast */
.overlay.judging::before {
  content: ""; position: absolute; top: 0; bottom: 0; left: 0; width: 20%;
  background: linear-gradient(90deg, transparent, var(--amber) 50%, transparent); opacity: 0.18;
  animation: jsweep 1.6s linear infinite;
}
@keyframes jsweep { from { transform: translateX(-100%); } to { transform: translateX(500%); } }
.goban[data-disabled="judging"] .bp::before, .goban[data-disabled="judging"] .bp::after, .goban[data-disabled="judging"] .hoshi { opacity: 0.7; }
.overlay.locked { box-shadow: inset 0 0 0 3px var(--gold-hi), inset 0 0 0 5px color-mix(in srgb, var(--gold) 30%, transparent); }
.overlay.frozen { box-shadow: inset 0 0 0 3px var(--frozen); background: color-mix(in srgb, var(--frozen) 8%, transparent); }
/* the last notch: the board shakes, ±4 px three times in 240 ms */
.board-sq.quake { animation: quake 0.24s linear; }
@keyframes quake { 16% { transform: translateX(-4px); } 33% { transform: translateX(4px); } 50% { transform: translateX(-4px); } 66% { transform: translateX(4px); } 83% { transform: translateX(-4px); } }
/* a won board: a big faint stone of the winner (60% of the board) and a plaque */
.wm { position: absolute; inset: 0; z-index: 4; pointer-events: none; display: grid; place-items: center; }
.wm[hidden] { display: none; }
/* the stone lies on the wood, under the grid and the stones (goban's first child) */
.goban .wm-stone { position: absolute; left: 20%; top: 20%; width: 60%; height: 60%; border-radius: 50%; pointer-events: none; z-index: 0; display: none; }
.goban .wm-stone.on { display: block; opacity: 0.18; }
.goban .wm-stone.black { background: radial-gradient(circle at 34% 30%, #7a7a7a 0, #2b2b2b 28%, #0b0b0b 62%, #000 100%); }
.goban .wm-stone.white { background: radial-gradient(circle at 34% 30%, #ffffff 0, #f4f2ec 35%, #d9d5cb 75%, #b8b3a7 100%); opacity: 0.4; }
.goban .wm-stone.drop { animation: wmdrop 0.5s cubic-bezier(.2, .7, .3, 1) both; }
@keyframes wmdrop { from { transform: translateY(-70%) scale(1.25); opacity: 0; } }
.wm-plaque {
  position: relative; top: 26%; padding: 4px 16px 5px; border-radius: 8px; white-space: nowrap;
  font: 600 18px/1.25 "Iowan Old Style", "Palatino Linotype", Palatino, "Book Antiqua", Georgia, serif; color: var(--ink);
  background: color-mix(in srgb, var(--card) 80%, transparent); box-shadow: 0 2px 10px rgba(30, 18, 2, 0.18); -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px);
  text-decoration: underline 2px var(--gold-hi); text-underline-offset: 5px;
}
.wm.drop .wm-plaque { animation: wmplaque 0.4s ease-out 0.45s both; }
@keyframes wmplaque { from { opacity: 0; transform: translateY(6px); } }
@media (prefers-reduced-motion: reduce) {
  .goban .ping { display: none; }
  .goban .bp[data-pending] .st, .goban .bp.shake, .board-sq.quake, .overlay.judging, .hood .mini.drop, .goban .wm-stone, .wm .wm-plaque { animation: none !important; }
  .overlay.judging::before { display: none; }
}

/* ---------- prose (how to play) ---------- */
.prose { max-width: 760px; margin: 0 auto; }
.prose h1 { font-size: 30px; letter-spacing: -0.02em; margin: 8px 0 6px; }
.prose h2 { margin-top: 28px; font-size: 20px; }
.prose code, .prose pre { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 13px; }
.prose pre { background: var(--card); border: 1px solid var(--line); border-radius: 10px; padding: 12px; overflow-x: auto; }
.prose li { margin: 4px 0; }
.prose .lede { font-size: 17px; color: var(--muted); }

/* ---------- feedback, toast, skip link, intro ---------- */
.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; }
.skip {
  position: absolute; left: 8px; top: -60px; z-index: 50; padding: 8px 12px; border-radius: 8px;
  background: var(--accent); color: var(--accent-ink); font-weight: 650; text-decoration: none;
}
.skip:focus { top: 8px; }
#controls:focus { outline: none; }
#controls:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.toast {
  position: fixed; left: 50%; bottom: 20px; transform: translate(-50%, 20px); z-index: 60; opacity: 0; pointer-events: none;
  max-width: calc(100vw - 32px); padding: 10px 16px; border-radius: var(--radius); font-weight: 650;
  background: var(--card); border: 1px solid var(--accent); box-shadow: 0 6px 24px rgba(0,0,0,.25); transition: opacity .2s, transform .2s;
}
.toast.on { opacity: 1; transform: translate(-50%, 0); }
.intro {
  display: flex; align-items: flex-start; gap: 12px; padding: 10px 14px; border-radius: var(--radius);
  background: var(--card); border: 1px solid var(--line); font-size: 14px;
}
.intro[hidden] { display: none; }
.intro p { margin: 0; flex: 1; }
.intro .icon-btn { flex: none; }

/* =====================================================================
   The finale (FLAGS §6)
   ===================================================================== */
/* the title card: the left column on a desktop, under the board on a phone */
.fin-title {
  position: relative; padding: 18px 18px 16px; border-radius: var(--radius); overflow: hidden;
  background: radial-gradient(140% 90% at 0% 0%, color-mix(in srgb, var(--gold-hi) 16%, var(--card)) 0%, var(--card) 60%);
  border: 1px solid color-mix(in srgb, var(--gold) 50%, var(--line)); box-shadow: var(--shadow);
}
.fin-title[hidden] { display: none; }
.fin-title::after { content: ""; position: absolute; inset: 4px; border-radius: calc(var(--radius) - 4px); border: 1px solid color-mix(in srgb, var(--gold) 22%, transparent); pointer-events: none; }
.fin-top { display: flex; align-items: center; gap: 12px; }
.fin-stone { width: 40px; height: 40px; flex: none; border-radius: 50%; box-shadow: 0 0 0 2px var(--gold-hi), 0 0 0 5px color-mix(in srgb, var(--gold) 18%, transparent), 0 6px 16px rgba(0, 0, 0, 0.3); }
.fin-kicker { font-size: 11.5px; font-weight: 750; letter-spacing: 0.14em; text-transform: uppercase; color: var(--gold); line-height: 1.3; }
.fin-h { margin: 12px 0 10px; font: 600 40px/44px "Iowan Old Style", "Palatino Linotype", Palatino, "Book Antiqua", Georgia, serif; letter-spacing: -0.015em; }
.fin-next { display: flex; flex-direction: column; line-height: 1.05; padding: 10px 0 12px; border-top: 1px solid color-mix(in srgb, var(--gold) 28%, var(--line)); border-bottom: 1px solid color-mix(in srgb, var(--gold) 28%, var(--line)); }
.fin-next[hidden] { display: none; }
.fin-next-k { font-size: 11px; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted); margin-bottom: 4px; }
.fin-next b { font-size: 44px; font-weight: 750; letter-spacing: -0.02em; color: var(--ink); }
.fin-more { margin-top: 10px; }
.fin-more > summary { display: none; list-style: none; cursor: pointer; font-size: 13px; font-weight: 650; color: var(--muted); }
.fin-more > summary::-webkit-details-marker { display: none; }
.fin-facts { display: grid; gap: 5px; font-size: 14px; color: var(--muted); }
.fin-fact { display: flex; align-items: baseline; gap: 6px; }
.fin-fact b { color: var(--ink); font-weight: 700; font-variant-numeric: tabular-nums; font-size: 16px; }
.fin-fact .sw { align-self: center; width: 10px; height: 10px; }
.fin-say { margin: 12px 0 0; font-size: 13px; line-height: 1.45; color: var(--muted); font-style: italic; }
@media (max-width: 999px) {
  /* a phone: two lines first, the rest folds */
  .fin-title { padding: 12px 14px; }
  .fin-top { gap: 10px; }
  .fin-stone { width: 28px; height: 28px; }
  .fin-h { font-size: 26px; line-height: 30px; margin: 8px 0 6px; }
  .fin-next { flex-direction: row; align-items: baseline; gap: 8px; padding: 0; border: 0; }
  .fin-next-k { margin: 0; }
  .fin-next b { font-size: 20px; }
  .fin-more > summary { display: block; margin-top: 4px; }
}

body[data-finale="on"] #epoch-card, body[data-finale="on"] .side-key, body[data-finale="on"] .side-now, body[data-finale="on"] .intro, body[data-finale="on"] .live-hint, body[data-finale="on"] #zoom { display: none; }
body[data-finale="on"] .macro canvas.thumbs { opacity: 0; transition: opacity 0.8s ease; }
body[data-climax] .pt[data-state="frozen"]::before { display: none; } /* no frost while the epoch is being won */
body[data-finstrip="on"] .needle-card .strip-rope, body[data-finstrip="on"] .needle-card .strip-cap { visibility: hidden; } /* the strip shows the ending instead */
body[data-finale="on"] .pt::before, body[data-finale="on"] .pt .stone, body[data-finale="on"] .pt .ring { display: none; }
body[data-finale="on"] .macro-frame { box-shadow: 0 0 0 1px color-mix(in srgb, var(--gold) 60%, transparent), 0 0 0 4px color-mix(in srgb, var(--gold) 12%, transparent), var(--shadow); }
.fin-layer { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 1; }
/* the mist: the probability field under the grid; it rises when the endings
   arrive, thins while an ending is on show, comes back between them */
.fin-mist { opacity: 0; transition: opacity 1.2s ease; }
.fin-mist.in { opacity: 1; }
.fin-mist.in.dim { opacity: 0.3; transition-duration: 0.7s; }
.macro-frame { transition: box-shadow 0.6s, filter 0.6s; }
.macro-frame.fin-rare-on { filter: saturate(0.7); } /* an ending the winner lost: the board drains a little */
.fin-sheen { position: absolute; inset: 0; overflow: hidden; pointer-events: none; z-index: 1; border-radius: 4px; }
.fin-sheen::before {
  content: ""; position: absolute; top: -30%; bottom: -30%; left: -45%; width: 38%;
  background: linear-gradient(100deg, transparent 0%, rgb(255 248 225 / 0.06) 40%, rgb(255 248 225 / 0.11) 50%, rgb(255 248 225 / 0.06) 60%, transparent 100%);
  transform: translateX(0) skewX(-12deg); animation: sheen 13s ease-in-out 3s infinite;
}
@keyframes sheen { 0% { transform: translateX(0) skewX(-12deg); } 40%, 100% { transform: translateX(420%) skewX(-12deg); } }
.fin-still .fin-sheen, .fin-lite .fin-sheen { display: none; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .fin-sheen { display: none; } }
:root[data-theme="dark"] .fin-sheen { display: none; }

/* the moment the epoch is won: the board flashes the winner's colour, then
   every game still in play fades out (the frozen state) before the mist rises */
.board-flash { position: absolute; inset: 0; z-index: 8; border-radius: 8px; pointer-events: none; opacity: 0; animation: bflash 0.42s ease-out forwards; }
.board-flash.black { background: #000; }
.board-flash.white { background: #fff; }
@keyframes bflash { 0% { opacity: 0; } 12%, 70% { opacity: 0.12; } 100% { opacity: 0; } }
body[data-freeze="on"] .pt::before { opacity: 0; transition: opacity 0.8s ease; }

/* the flag strip during the finale: the ending on show and its area tally */
.fin-strip { position: absolute; inset: 0; z-index: 5; display: flex; flex-direction: column; justify-content: center; gap: 6px; background: var(--bg); }
.fin-strip[hidden] { display: none; }
.fin-cap { display: flex; align-items: center; gap: 8px; min-width: 0; max-width: 100%; height: 24px; font-size: 15px; font-weight: 600; line-height: 22px; white-space: nowrap; font-variant-numeric: tabular-nums; opacity: 0; transition: opacity 0.35s ease; }
.fin-cap.on { opacity: 1; }
.fin-cap > span { overflow: hidden; text-overflow: ellipsis; }
.fin-cap .pip { width: 11px; height: 11px; margin: 0; }
.fin-cap.rare { align-self: flex-start; padding: 0 12px 0 9px; border: 1px solid var(--muted); border-radius: 999px; }
.tally { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 10px; height: 22px; }
.tally[hidden] { display: none; }
.tl-n { display: inline-flex; align-items: baseline; gap: 6px; font-size: 15px; font-weight: 700; min-width: 70px; white-space: nowrap; }
.tl-n.b { justify-content: flex-end; }
.tl-n .pip { width: 11px; height: 11px; margin: 0; align-self: center; }
.tl-komi { font-size: 11px; font-weight: 600; color: var(--muted); margin-left: -3px; }
.tally[data-lead="black"] .tl-n.w b, .tally[data-lead="white"] .tl-n.b b { color: var(--muted); font-weight: 600; }
.tl-bar { position: relative; height: 12px; border-radius: 999px; overflow: hidden; background: color-mix(in srgb, var(--wood) 38%, var(--card)); } /* a wood track: both stones read on it */
.tl-bar i { position: absolute; top: 0; bottom: 0; width: 50%; transform: scaleX(0); transition: transform 0.12s linear; }
.tl-bar .tl-w { right: 50%; transform-origin: 100% 50%; background: #fbf8f1; box-shadow: inset 0 0 0 1.5px #8c7f6a; border-radius: 999px 0 0 999px; }
.tl-bar .tl-b { left: 50%; transform-origin: 0 50%; background: #16130f; border-radius: 0 999px 999px 0; }
.tl-bar .tl-mid { left: 50%; width: 2px; margin-left: -1px; transform: none; background: var(--gold-hi); box-shadow: 0 0 0 1px color-mix(in srgb, var(--ink) 35%, transparent); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .tl-bar .tl-b { box-shadow: inset 0 0 0 1px rgba(255, 245, 225, 0.4); } }
:root[data-theme="dark"] .tl-bar .tl-b { box-shadow: inset 0 0 0 1px rgba(255, 245, 225, 0.4); }
/* a phone: one title line under the strip */
.fin-band { display: none; }
@media (max-width: 999px) {
  body[data-finale="on"] .fin-band { display: block; width: var(--side); padding: 2px 0 8px; font: 600 16px/22px "Iowan Old Style", "Palatino Linotype", Palatino, "Book Antiqua", Georgia, serif; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-variant-numeric: tabular-nums; }
}
/* the title card's tug of war: the needle over the epoch */
.fin-tow { margin-top: 12px; }
.fin-tow[hidden] { display: none; }
.fin-tow-h { display: flex; flex-direction: column; gap: 1px; margin-bottom: 5px; font-size: 11px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted); }
.fin-tow-h span:last-child { text-transform: none; letter-spacing: 0; font-size: 13px; font-weight: 600; color: var(--ink); }
.fin-spark { display: block; width: 100%; height: 56px; }
.pip { display: inline-block; width: 9px; height: 9px; border-radius: 50%; margin-right: 5px; vertical-align: -1px; flex: none; }
.pip.b { background: radial-gradient(circle at 35% 30%, #666, #0d0b08 65%); }
.pip.w { background: radial-gradient(circle at 35% 30%, #fff, #e6e1d6 75%); box-shadow: 0 0 0 1px rgba(60, 40, 10, 0.3); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .pip.b { box-shadow: 0 0 0 1px rgba(255, 245, 225, 0.3); } }
:root[data-theme="dark"] .pip.b { box-shadow: 0 0 0 1px rgba(255, 245, 225, 0.3); }

/* the endings: one dot histogram (each dot one ending, or a few when they pile up) */
.fin-card[hidden] { display: none; }
.fin-hist-wrap { position: relative; border-radius: 6px; background: color-mix(in srgb, var(--wood) 26%, var(--card)); } /* a wood plinth: the dots read as stones */
/* dark: the dots sit on a dark wood plinth, so black ones read as stones */
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .fin-hist-wrap { background: color-mix(in srgb, var(--wood) 30%, var(--card)); } }
:root[data-theme="dark"] .fin-hist-wrap { background: color-mix(in srgb, var(--wood) 30%, var(--card)); }
.fin-wall { display: block; width: 100%; height: 150px; cursor: pointer; }
.fin-pip-now { position: absolute; left: 0; top: 0; width: 0; height: 0; pointer-events: none; }
.fin-pip-now::after { content: ""; position: absolute; left: -7px; top: -7px; width: 14px; height: 14px; border-radius: 50%; border: 2px solid var(--gold-hi); animation: pipnow 1.2s ease-out infinite; }
.fin-pip-now[hidden] { display: none; }
@keyframes pipnow { 0% { transform: scale(0.5); opacity: 1; } 100% { transform: scale(1.5); opacity: 0; } }
.fin-axis { position: relative; height: 18px; font-size: 11px; color: var(--muted); border-top: 1px solid var(--muted); margin-top: 1px; }
.fin-axis span { position: absolute; top: 2px; transform: translateX(-50%); white-space: nowrap; font-variant-numeric: tabular-nums; }
.fin-axis span.even::before { content: ""; position: absolute; left: 50%; top: -6px; width: 1px; height: 5px; background: var(--muted); }
.fin-axis span.mean { color: var(--ink); font-weight: 650; }
.fin-axis span.mean::before { content: ""; position: absolute; left: 50%; top: -7px; margin-left: -3px; border: 3px solid transparent; border-bottom-color: var(--ink); border-top: 0; }
.fin-wall-key { display: flex; flex-wrap: wrap; gap: 4px 12px; align-items: center; margin-top: 8px; font-size: 12px; color: var(--muted); }
.fin-wall-key > span { display: inline-flex; align-items: center; }
.fin-wall-key > span[hidden] { display: none; }
.fin-wall-key span:last-child { margin-left: auto; }
/* every ending agrees: no chart, the count, and a row of the winner's pips */
.fin-card[data-all="1"] .fin-hist-wrap, .fin-card[data-all="1"] .fin-axis, .fin-card[data-all="1"] .fin-wall-key { display: none; }
.fin-stamp { text-align: center; padding: 6px 0 2px; }
.fin-stamp[hidden] { display: none; }
.fin-all-n { font: 600 40px/1.1 "Iowan Old Style", "Palatino Linotype", Palatino, "Book Antiqua", Georgia, serif; font-variant-numeric: tabular-nums; letter-spacing: -0.01em; }
.fin-all-t { margin-top: 2px; font-size: 13px; color: var(--muted); }
.fin-all-row { height: 12px; margin-top: 12px; background-size: 12px 12px; background-repeat: repeat-x; background-position: center; }
.fin-all-row.b { background-image: radial-gradient(circle, #17130e 0 3.8px, transparent 4.4px); }
.fin-all-row.w { background-image: radial-gradient(circle, #fffdf7 0 3.6px, rgba(60, 40, 10, 0.5) 3.8px 4.6px, transparent 5px); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .fin-all-row.b { background-image: radial-gradient(circle, #0b0b0b 0 3.4px, rgba(255, 255, 255, 0.4) 3.6px 4.4px, transparent 4.8px); } }
:root[data-theme="dark"] .fin-all-row.b { background-image: radial-gradient(circle, #0b0b0b 0 3.4px, rgba(255, 255, 255, 0.4) 3.6px 4.4px, transparent 4.8px); }

.fin-dialog { position: fixed; inset: 0; z-index: 70; display: grid; place-items: start center; padding: 24px 16px; overflow-y: auto; background: rgb(12 9 5 / 0.6); }
.fin-dialog-in { position: relative; width: min(1120px, 100%); padding: 16px; border-radius: 16px; background: var(--bg); box-shadow: 0 24px 70px rgba(0, 0, 0, 0.45); }
.fin-x { position: absolute; right: -12px; top: -12px; z-index: 2; width: 34px; height: 34px; font-size: 18px; box-shadow: var(--shadow); }
.fin-dialog-grid { display: grid; gap: 16px; grid-template-columns: 270px minmax(0, 1fr) 300px; align-items: start; }
@media (max-width: 999px) { .fin-dialog-grid { grid-template-columns: minmax(0, 1fr); } }
.fin-dialog .fin-board { width: min(100%, calc(100vh - 170px)); position: relative; }
.fin-dialog .macro-frame { margin: 0; }
.fin-strip.fin-strip-d { position: relative; inset: auto; height: 60px; background: none; }
.fin-host { position: relative; width: 100%; aspect-ratio: 1; }

@media (prefers-reduced-motion: reduce) {
  .fin-mist, .fin-cap, .tl-bar i, .macro-frame { transition: none; }
  .board-flash { display: none; }
  .fin-sheen { display: none; }
  .fin-pip-now::after { animation: none; opacity: 1; transform: none; }
}

/* zoom in and out of a game: the stage stays put, the page cross-fades */
@view-transition { navigation: auto; }
::view-transition-group(root) { animation-duration: 0.22s; }
@media (prefers-reduced-motion: reduce) { @view-transition { navigation: none; } }
