/* The court page (M47 D11): one rule set for both themes, transcribed from A7. The theme blocks
   declare custom properties only, so the toggle flips one attribute and swaps colour, never
   layout. Night carries A7's base hexes, day B7's; every other tone is mixed from them by the
   shared formulas. Type scale: 12 meta · 13 body · 15 card titles · 22 title; on the canvas
   11 / 12 / 13 / 19 user units. */
@font-face {
  font-family: 'Source Serif 4';
  src: url('/fonts/source-serif-4.woff2') format('woff2');
  font-weight: 200 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Source Sans 3';
  src: url('/fonts/source-sans-3.woff2') format('woff2');
  font-weight: 200 900;
  font-style: normal;
  font-display: swap;
}
/* A self-hosted subset of Noto Serif CJK SC (SIL OFL 1.1): the board's and the court page's CJK glyphs only. */
@font-face {
  font-family: 'Sansheng Serif SC';
  src: url('/fonts/noto-serif-sc.woff2') format('woff2');
  font-weight: 200 900;
  font-style: normal;
  font-display: swap;
  unicode-range: U+4E09, U+4E0B, U+4E2D, U+4E66, U+4E8B, U+505C, U+516D, U+51C6, U+529E, U+5370, U+5386, U+53F2, U+542F, U+5802, U+58A8, U+591C, U+5B8C, U+5BA1, U+5C1A, U+5DE5, U+5E9F, U+5EAD, U+5F85, U+5FA1, U+603B, U+6210, U+6237, U+6267, U+6279, U+6536, U+6587, U+663C, U+6682, U+66F8, U+671D, U+672A, U+6731, U+6B62, U+6C47, U+6C60, U+767D, U+7701, U+793C, U+7ED9, U+8349, U+884C, U+8BAE, U+8BCF, U+8D77, U+8FD0, U+90E8, U+9580, U+95E8, U+9A73;
}
/* THEME:BEGIN */
:root, :root[data-theme="night"] {
  --scheme: dark;
  --paper: #0d1220;
  --text: #c9cfdc;
  --cinnabar: #c3272b;
  --ink: color-mix(in srgb, var(--text) 56%, var(--paper));
  --seal-ink: var(--text);
  --card: color-mix(in srgb, var(--text) 6%, var(--paper));
  --wash: color-mix(in srgb, var(--text) 3%, var(--paper));
}
:root[data-theme="day"] {
  --scheme: light;
  --paper: #f5efe0;
  --text: #1f1c18;
  --cinnabar: #b02a1d;
  --ink: #6b655b;
  --seal-ink: var(--paper);
  --card: var(--paper);
  --wash: color-mix(in srgb, var(--text) 5.5%, var(--paper));
}
/* THEME:END */
/* Derived tones, the five project tints (shared by both themes, indexed by `tintIndex`), the
   board's self-hosted faces and the token opacities. */
:root {
  --mist: color-mix(in srgb, var(--text) 68%, var(--paper));
  --ink-soft: color-mix(in srgb, var(--text) 16%, var(--paper));
  --seal-wash: color-mix(in srgb, var(--cinnabar) 9%, var(--paper));
  --tint-0: #7f978a;
  --tint-1: #a8956f;
  --tint-2: #7e8b9b;
  --tint-3: #937f90;
  --tint-4: #a67d6c;
  --serif: 'Source Serif 4', 'Sansheng Serif SC', 'Noto Serif SC', Georgia, 'Times New Roman', serif;
  --sans: 'Source Sans 3', 'Noto Sans SC', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --ghost-op: 0.15;
  --wait-op: 0.55;
  --gap: 16px;
  color-scheme: var(--scheme);
}
.pj-0 { --pj: var(--tint-0); }
.pj-1 { --pj: var(--tint-1); }
.pj-2 { --pj: var(--tint-2); }
.pj-3 { --pj: var(--tint-3); }
.pj-4 { --pj: var(--tint-4); }

* { box-sizing: border-box; }
html { background: var(--paper); }
body {
  margin: 0;
  min-height: 100vh;
  color: var(--text);
  font: 13px/1.5 var(--sans);
  font-variant-numeric: tabular-nums;
  background: var(--paper);
  transition: background-color 0.6s ease, color 0.6s ease;
}
.page { max-width: 1400px; margin: 0 auto; padding: 24px 32px 56px; }
button { font: inherit; cursor: pointer; }
button:focus-visible, .token:focus-visible, .pool-item:focus-visible { outline: 1px solid var(--text); outline-offset: 3px; }
a { color: var(--text); }

/* Title row: the mark, the screen's name with the connection word, the finding strip under it,
   and the day/night toggle on the right. */
.top { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.top .mark { width: 40px; height: 40px; flex: none; display: grid; place-items: center; border: 1px solid var(--ink);
  border-radius: 4px; color: var(--text); font: 600 22px var(--serif); }
.top .names { flex: 1 1 280px; min-width: 0; }
.title-line { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 14px; }
.top h1 { margin: 0; font: 600 22px/1.25 var(--serif); color: var(--text); letter-spacing: 0.04em; }
.top .product { margin: 0; font-size: 13px; color: var(--mist); }
.top .product b { color: var(--text); font-weight: 600; }
.finding { margin: 4px 0 0; font-size: 13px; color: var(--text); }
.finding .warn { color: var(--text); font-weight: 600; }
.finding .stop { display: inline-grid; place-items: center; width: 18px; height: 18px; margin-right: 5px; border-radius: 3px; vertical-align: -3px;
  font: 600 12px/1 var(--serif); color: var(--seal-ink); background: var(--cinnabar); }
.top .actions { display: flex; gap: 8px; flex: none; }
.toggle { display: inline-flex; align-items: center; gap: 2px; min-height: 34px; padding: 3px; border: 1px solid var(--ink); border-radius: 999px;
  background: transparent; color: var(--text); transition: border-color 0.2s; }
.toggle:hover { border-color: var(--text); }
.toggle .opt { padding: 3px 12px; border-radius: 999px; font-size: 13px; color: var(--mist); transition: background-color 0.6s, color 0.6s; }
.toggle .opt.on { color: var(--paper); background: var(--text); }
.toggle .glyph { font-family: var(--serif); margin-right: 5px; }

/* Filter bar: All plus one chip per project, each with its live count. */
.filters { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 14px 0 var(--gap); }
.filters[hidden] { display: none; }
.filters .k { font-size: 12px; color: var(--mist); margin-right: 4px; }
.chip { display: inline-flex; align-items: center; gap: 7px; border: 1px solid var(--ink-soft); background: transparent;
  color: var(--mist); border-radius: 999px; padding: 5px 12px 5px 10px; min-height: 32px; font-size: 13px;
  transition: border-color 0.2s, color 0.2s, background-color 0.6s; }
.chip:hover { border-color: var(--ink); }
.chip .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--pj); }
.chip[aria-pressed="true"] { color: var(--text); border-color: var(--ink); background: var(--card); }
.chip .n { color: var(--mist); }

/* The court frame and the status panel (over the canvas on wide screens, under it on narrow ones). */
.stage { position: relative; }
.frame { position: relative; border: 1px solid var(--ink-soft); border-radius: 8px; padding: 8px; }
.court { display: block; width: 100%; height: auto; }
.court text { font-family: var(--sans); }
.frame .caption { position: absolute; right: 16px; bottom: 10px; margin: 0; font-size: 12px; color: var(--mist); }

/* Zones: two flat washes behind everything else on the canvas; the label is the caption tone. */
.zone { fill: var(--wash); transition: fill 0.6s; }
.zone-label { fill: var(--mist); font-size: 12px; }
.zone-label .zk { fill: var(--text); font-family: var(--serif); font-weight: 600; }

/* Arcs: the journey lane (one thin structure-ink line) and the loop arc (one thin vermilion
   dry-brush dash). */
.lane { fill: none; stroke: var(--ink); stroke-width: 1; stroke-linecap: round; opacity: 0.7; }
.loop { fill: none; stroke: var(--cinnabar); stroke-width: 1.2; stroke-dasharray: 7 3 2 4; stroke-linecap: round; }
.loop-label { fill: var(--mist); font-size: 12px; }
.arrow { fill: var(--cinnabar); }
.bead { fill: var(--pj); transition: opacity 0.4s; }

/* Gates and bays: hairline places. */
.place-frame { fill: none; stroke: var(--ink-soft); stroke-width: 1; }
.place-label { fill: var(--mist); font-size: 12px; }
.waypoint { fill: var(--paper); stroke: var(--ink); stroke-width: 1; }

/* Cards: one chrome for seats and edicts alike; a busy seat gains a soft vermilion ring that breathes. */
.card { fill: var(--card); stroke: var(--ink); stroke-width: 1; transition: fill 0.6s, stroke 0.6s; }
.busy-ring { fill: none; stroke: var(--cinnabar); stroke-width: 1.4; opacity: 0; transition: opacity 1.2s ease; }
.seat.busy .busy-ring { opacity: 0.55; animation: breath 5.6s ease-in-out infinite alternate; }
@keyframes breath { from { opacity: 0.32; } to { opacity: 0.62; } }
.seat-name { fill: var(--text); font-family: var(--serif) !important; font-size: 19px; font-weight: 600; letter-spacing: 0.04em; }
.seat-sub { fill: var(--mist); font-size: 12px; }
.seat-status { fill: var(--mist); font-size: 12px; }
.seat.busy .seat-status { fill: var(--text); font-weight: 600; }
.seat-step { fill: var(--text); font-size: 13px; }
.glyph-idle { fill: none; stroke: var(--ink); stroke-width: 1.2; }
.glyph-open { fill: var(--cinnabar); }
.meter-k, .meter-v, .elapsed { font-size: 12px; font-variant-numeric: tabular-nums; }
.meter-k, .elapsed { fill: var(--mist); }
.meter-v { fill: var(--text); font-weight: 600; }
.meter-bg { fill: var(--ink-soft); }
.meter-fill { fill: var(--ink); transform-box: fill-box; transform-origin: left center; transition: transform 0.9s cubic-bezier(0.2, 0.8, 0.2, 1); }
.meter-fill.hot { fill: var(--text); }

/* Edict tokens: one shape, the small kanban card, with a 3px project strip. State lives on the card:
   executing: the pulse layer breathes on a 2.4s cycle, opacity only;
   waiting:   strip, words and border at 55% on an opaque fill;
   halted:    the vermilion border on a vermilion wash, held still.
   The token's opacity is its one transition; its place is set directly. */
.token { cursor: pointer; transition: opacity 0.4s; }
.token.s-waiting .tok-strip, .token.s-waiting text { opacity: var(--wait-op); }
.token.s-waiting .card { stroke-opacity: var(--wait-op); }
.token.s-halted .card { stroke: var(--cinnabar); stroke-width: 1.4; fill: var(--seal-wash); }
.tok-strip { fill: var(--pj); }
.tok-pulse { fill: var(--text); fill-opacity: 0.1; stroke: var(--text); stroke-width: 1; opacity: 0; pointer-events: none; }
.token.s-running .tok-pulse { opacity: 0.7; animation: pulse 2.4s ease-in-out infinite; }
@keyframes pulse { 0%, 100% { opacity: 0.12; } 50% { opacity: 1; } }
.tok-select { fill: none; stroke: var(--text); stroke-width: 1; opacity: 0; }
.token.selected .tok-select, .token:hover .tok-select { opacity: 0.8; }
.tok-id { fill: var(--mist); font-size: 11px; letter-spacing: 0.02em; }
.tok-title { fill: var(--text); font-size: 13px; }
.token.s-halted .tok-id { fill: var(--text); }
.token.more .card { stroke-dasharray: 3 3; }
.ghost { opacity: var(--ghost-op) !important; }

/* Seals: 准 is carved 白文 (solid, light glyph), 驳 is carved 朱文 (outline, vermilion glyph). */
.seal-solid rect { fill: var(--cinnabar); }
.seal-solid text { fill: var(--seal-ink); }
.seal-line rect { fill: var(--paper); stroke: var(--cinnabar); stroke-width: 2; }
.seal-line text { fill: var(--cinnabar); }
.seal-solid text, .seal-line text { font-family: var(--serif); font-weight: 600; }

/* The status panel (A8 `:187–262`): over the canvas on wide screens. The header (band, id, title,
   project, state chip, Close with the History toggle under it), the status line, then the brief —
   Now, the plan, the work done, the result. */
.panel { position: absolute; top: 16px; right: 16px; width: 380px; max-height: calc(100% - 32px); overflow: auto;
  background: var(--card); border: 1px solid var(--ink); border-radius: 8px; padding: 14px 16px 16px; }
.panel[hidden] { display: none; }
.panel .p-head { display: flex; align-items: flex-start; gap: 10px; }
.panel .band { width: 3px; align-self: stretch; background: var(--pj); border-radius: 2px; }
.panel .p-id { font-size: 12px; color: var(--mist); }
.panel h2 { margin: 1px 0 0; font: 600 15px/1.35 var(--serif); color: var(--text); }
.panel .p-project { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 6px; font-size: 12px; color: var(--mist); }
.panel .p-project b { color: var(--text); font-weight: 600; }
.panel .board-open { color: var(--mist); font-size: 12px; text-underline-offset: 2px; }
.panel .board-open:hover { color: var(--text); }
.state-chip { font-size: 12px; padding: 1px 10px; border-radius: 999px; border: 1px solid var(--ink); color: var(--text); white-space: nowrap; }
.state-chip.halted { border-color: var(--cinnabar); }
.panel .p-actions { margin-left: auto; flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: 6px; }
.panel .close, .panel .hist { flex: none; border: 1px solid var(--ink-soft); background: transparent; color: var(--mist);
  border-radius: 999px; padding: 3px 12px; font-size: 12px; min-height: 28px; white-space: nowrap; }
.panel .close:hover, .panel .hist:hover:not(:disabled) { color: var(--text); border-color: var(--ink); }
.panel .hist[aria-expanded="true"] { color: var(--text); border-color: var(--ink); }
.panel .hist:disabled { cursor: default; }
.replay-mark { margin: 12px 0 0; padding: 7px 10px; border: 1px dashed var(--ink); border-radius: 6px; font-size: 12px; color: var(--mist); }
.replay-mark b { color: var(--text); font-weight: 600; }
.panel .statusline { margin: 10px 0 0; font-size: 12px; color: var(--mist); }
.panel .statusline b { color: var(--text); font-weight: 600; }
.panel h3 { margin: 16px 0 6px; font: 600 13px var(--serif); color: var(--text); }
.panel h3.dim { color: var(--mist); }
.panel p { margin: 0; }

/* The History section (A8 `:206–227`): the scrub bar (position, Prev, Next, Play, Now) and every
   stop as a small button; the chosen one filled, a 驳 or a halt with the vermilion border. It
   unfolds once on open (instant under reduced motion); stepping leaves the section unfolded. */
.scrub { margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--ink-soft); }
.scrub[hidden] { display: none; }
.scrub.unfold { animation: unfold 0.22s cubic-bezier(0.2, 0.8, 0.2, 1) both; }
@keyframes unfold { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }
.scrub-bar { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.scrub-bar .pos { margin-right: auto; font-size: 12px; color: var(--mist); }
.scrub-bar .pos b { color: var(--text); font-weight: 600; }
.sbtn { flex: none; white-space: nowrap; border: 1px solid var(--ink); background: transparent; color: var(--text); border-radius: 999px;
  padding: 2px 11px; min-height: 28px; font-size: 12px; transition: border-color 0.2s, background-color 0.2s; }
.sbtn:hover:not(:disabled) { border-color: var(--text); }
.sbtn:disabled { color: var(--mist); border-color: var(--ink-soft); cursor: default; }
.sbtn.go-now[aria-pressed="true"], .sbtn.play[aria-pressed="true"] { color: var(--paper); background: var(--text); border-color: var(--text); }
.stages { list-style: none; margin: 8px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 5px; }
.stages button { border: 1px solid var(--ink-soft); background: transparent; color: var(--mist); border-radius: 4px; padding: 2px 8px;
  min-height: 26px; font-size: 12px; white-space: nowrap; transition: border-color 0.2s; }
.stages button:hover { border-color: var(--ink); color: var(--text); }
.stages button.red { border-color: var(--cinnabar); color: var(--text); }
.stages button.live { color: var(--text); border-color: var(--ink); }
.stages button[aria-current="step"] { color: var(--paper); background: var(--text); border-color: var(--text); }

/* The brief's blocks (A8 `:229–262`): leads and notes, the halt reason, quotes, the brief and plan
   terms, subtask rows and the verdict with its seal (准 solid, 驳 outline; the press on a replayed
   verdict). A quote keeps the message's line breaks. */
.now-lead { font-size: 13px; color: var(--text); }
.now-note { margin-top: 4px; font-size: 12px; color: var(--mist); }
.halt-reason { margin-top: 2px; padding: 8px 12px; border-left: 2px solid var(--cinnabar); background: var(--seal-wash); font-size: 15px; line-height: 1.45; color: var(--text); }
.quote { margin-top: 8px; padding: 6px 12px; border-left: 2px solid var(--ink-soft); font-size: 13px; color: var(--text); overflow-wrap: anywhere; white-space: pre-wrap; }
.brief { margin: 8px 0 0; display: grid; grid-template-columns: 76px 1fr; gap: 4px 10px; font-size: 13px; }
.brief dt { color: var(--mist); font-size: 12px; padding-top: 1px; }
.brief dd { margin: 0; color: var(--text); overflow-wrap: anywhere; }
.outline { margin-top: 8px; }
.subs { list-style: none; margin: 8px 0 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.subs li { padding: 6px 10px 7px 12px; border-left: 2px solid var(--ink-soft); }
.subs li.current { border-left-color: var(--text); }
.subs li.failed { border-left-color: var(--cinnabar); }
.subs .s-head { display: flex; gap: 8px; align-items: baseline; font-size: 12px; color: var(--mist); }
.subs .s-head .s-state { margin-left: auto; color: var(--mist); white-space: nowrap; }
.subs li.current .s-state, .subs li.failed .s-state { color: var(--text); }
.subs .s-title { font-size: 13px; color: var(--text); }
.subs .s-detail { font-size: 12px; color: var(--mist); margin-top: 1px; }
.verdict { margin: 8px 0 4px; padding: 8px 12px 9px 44px; position: relative; border: 1px solid var(--ink-soft); border-radius: 4px; }
.verdict .seal { position: absolute; left: 10px; top: 9px; width: 24px; height: 24px; border-radius: 3px; display: grid; place-items: center;
  font: 600 14px var(--serif); transform: rotate(-4deg); }
.verdict .seal.approve { color: var(--seal-ink); background: var(--cinnabar); }
.verdict .seal.reject { color: var(--cinnabar); border: 1.5px solid var(--cinnabar); }
.verdict .seal.press { animation: press 0.6s cubic-bezier(0.3, 1.4, 0.6, 1) both; }
@keyframes press { 0% { opacity: 0; transform: scale(1.8) rotate(-4deg); } 62% { opacity: 1; transform: scale(0.92) rotate(-4deg); } 100% { opacity: 1; transform: scale(1) rotate(-4deg); } }
.verdict .v-head { font-size: 12px; color: var(--mist); }
.verdict .v-head b { color: var(--text); font-weight: 600; }
.verdict .v-text { margin-top: 2px; font-size: 13px; color: var(--text); overflow-wrap: anywhere; }

/* D4: a failed read is one muted line in the region its data would fill — the timeline's under the
   status line, the snapshot's in the Now block, a transcript's in its stop detail. No toast. */
.timeline-error, .detail-error { margin-top: 8px; font-size: 12px; color: var(--mist); }

/* The court row: the map, and the run pool in a rail beside it on wide screens (under it otherwise). */
.court-row { display: grid; grid-template-columns: minmax(0, 1fr) 360px; gap: var(--gap); align-items: stretch; }
.court-row .stage { align-self: start; }

/* Court roll: the seven seats and the edicts on the map at reading size, shown on narrow screens
   and when a `+n` token opens it. */
.roll { display: none; margin-top: var(--gap); border: 1px solid var(--ink-soft); border-radius: 8px; padding: 14px 16px 16px; }
.roll.open { display: block; }
.roll h2 { margin: 0; font: 600 15px var(--serif); color: var(--text); }
.roll-grid { display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); gap: var(--gap) 24px; margin-top: 10px; }
.roll h3 { margin: 0 0 4px; font-size: 12px; font-weight: 400; color: var(--mist); }
.seat-list { list-style: none; margin: 0; padding: 0; }
.seat-list li { display: grid; grid-template-columns: 1fr auto; gap: 0 12px; padding: 7px 0; border-top: 1px solid var(--ink-soft); }
.seat-list .r-name { font: 600 15px/1.3 var(--serif); color: var(--text); }
.seat-list .r-name small { margin-left: 8px; font: 12px var(--sans); color: var(--mist); }
.seat-list .r-name small.open { color: var(--text); font-weight: 600; }
.seat-list .r-fig { font-size: 13px; font-weight: 600; text-align: right; }
.seat-list .r-sub { grid-column: 1 / -1; font-size: 12px; color: var(--mist); }
.roll .pool-row { display: grid; grid-template-columns: 1fr; gap: 12px var(--gap); }
.pool-item { display: flex; align-items: center; gap: 10px; min-width: 0; cursor: pointer; border-radius: 6px; transition: opacity 0.4s; }
.pool-item svg { flex: none; overflow: visible; }
.pool-cap { min-width: 0; }
.pool-cap .top-line { display: flex; gap: 6px; align-items: baseline; font-size: 12px; color: var(--mist); white-space: nowrap; }
.pool-cap .top-line b { color: var(--text); font-weight: 600; letter-spacing: 0.02em; }
.pool-cap .where { font-size: 12px; color: var(--mist); margin-top: 1px; }
.pool-cap .where.hold { color: var(--text); }

/* Run-pool rail (§4.8): the cap note, the two groups of token rows and the foot count; a pool row
   is a button, so its token keeps the pointer. */
.pool { display: flex; flex-direction: column; border: 1px solid var(--ink-soft); border-radius: 8px; padding: 14px 16px 16px;
  transition: background-color 0.6s; }
.pool-foot { margin: auto 0 0; padding-top: 12px; font-size: 13px; color: var(--text); }
.pool-head { display: flex; align-items: baseline; gap: 6px 10px; flex-wrap: wrap; }
.pool-head h2 { margin: 0; font: 600 15px var(--serif); color: var(--text); }
.pool-head .note { font-size: 13px; color: var(--mist); }
.pool-body { display: grid; grid-template-columns: 1fr; gap: var(--gap); margin-top: 12px; }
.pool-group { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.pool-group .k { font-size: 12px; color: var(--mist); }
.pool .pool-row { display: grid; grid-template-columns: repeat(auto-fill, minmax(296px, 1fr)); gap: 12px var(--gap); }
.pool-cap .stage-line { font-size: 12px; color: var(--text); margin-top: 1px; }

/* Legend: six groups in one bordered strip, wrapping as the width allows. */
.legend { margin-top: var(--gap); display: flex; flex-wrap: wrap; gap: 4px var(--gap); padding: 2px 0;
  border: 1px solid var(--ink-soft); border-radius: 8px; }
.legend section { flex: 1 1 200px; padding: 12px 16px 14px; min-width: 0; }
.legend h3 { margin: 0 0 8px; font: 600 15px var(--serif); color: var(--text); }
.legend ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; font-size: 13px; color: var(--text); }
.legend li { display: flex; align-items: center; gap: 8px; }
.legend svg { flex: none; overflow: visible; }
.legend .muted { color: var(--mist); }
.legend li > .muted:first-child { flex: none; white-space: nowrap; }
.legend .swatch { display: inline-block; width: 12px; height: 12px; border-radius: 50%; background: var(--pj); flex: none; }

/* Breakpoints: at 1199px `.court-row` takes one column, so the run pool moves under the map, and
   `.pool-body` sets its two groups side by side; under 900px the panel moves under the canvas, the
   court roll appears and the groups stack; at 640px the margins tighten, the mark shrinks, the
   toggle drops its words and the pool rows take one column. */
@media (max-width: 1199px) {
  .court-row { grid-template-columns: minmax(0, 1fr); }
  .pool-body { grid-template-columns: 3fr 2fr; }
}
@media (max-width: 899px) {
  .panel { position: static; width: auto; max-height: none; margin-top: var(--gap); }
  .roll { display: block; }
  .pool-body { grid-template-columns: 1fr; }
}
@media (max-width: 640px) {
  .page { padding: 16px 16px 40px; }
  .top { gap: 12px; align-items: flex-start; }
  .top .mark { width: 32px; height: 32px; font-size: 18px; }
  .top h1 { font-size: 20px; }
  .toggle .wd { display: none; }
  .frame { padding: 4px; }
  .roll-grid { grid-template-columns: 1fr; }
  .pool .pool-row { grid-template-columns: 1fr; }
}

/* Reduced motion: the static layout, no animation or transition. The executing pulse layer keeps
   its fixed lift (opacity 0.7 above) and the meters stand at their value. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}
