/* TrigammonX v2.2.0 — 02-board-game.css
 * Auto-extracted verbatim from TrigammonX-v2.1.9.html's single <style> block
 * as part of the v2.2.0 modularisation pass (match log, board/game feature panels continuing into board-game visual components).
 * See README-ARCHITECTURE.md for exact cascade/load order.
 */
/* v142: rolling animation — tumble + shadow pulse */
@keyframes dieTumble {
  0%   { transform: rotate(var(--r0)) scale(1.02); box-shadow: 0 0 8px rgba(216,180,106,0.55), 0 4px 8px rgba(0,0,0,0.4); }
  25%  { transform: rotate(var(--r1)) scale(0.97); box-shadow: 0 0 4px rgba(216,180,106,0.25), 0 4px 8px rgba(0,0,0,0.4); }
  50%  { transform: rotate(var(--r2)) scale(1.05); box-shadow: 0 0 12px rgba(216,180,106,0.65), 0 4px 8px rgba(0,0,0,0.4); }
  75%  { transform: rotate(var(--r3)) scale(0.98); box-shadow: 0 0 5px rgba(216,180,106,0.3), 0 4px 8px rgba(0,0,0,0.4); }
  100% { transform: rotate(var(--r0)) scale(1.02); box-shadow: 0 0 8px rgba(216,180,106,0.55), 0 4px 8px rgba(0,0,0,0.4); }
}
.die-chip.rolling {
  animation: dieTumble 0.18s linear infinite;
  border-color: #fff;
  background: linear-gradient(155deg, #2c3a64 0%, #1e2a4a 60%, #131c34 100%);
}
.die-slot-num {
  position: absolute; top: 1px; right: 2px;
  font-size: 7px; color: #888; font-family: 'Courier New', monospace;
}
.dice-test-inputs {
  display: flex; gap: 5px; align-items: center; flex-wrap: wrap;
}
.dice-test-inputs input {
  width: 36px; height: 28px;
  background: #16213e; border: 1px solid #555;
  color: #ffd700; border-radius: 4px;
  text-align: center; font-size: 14px; font-family: 'Courier New', monospace;
}

/* ── Admin Test Dice inputs (v177) ── */
.admin-test-dice-inputs {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
}
.admin-test-dice-inputs input {
  width: 44px;
  height: 28px;
  background: #16213e;
  border: 1px solid #555;
  color: #ffd700;
  border-radius: 4px;
  text-align: center;
  font-size: 14px;
  font-family: 'Courier New', monospace;
}
.admin-test-dice-inputs button {
  width: auto;
  text-align: center;
  border-color: #ffd700;
  color: #ffd700;
}
.turn-badge {
  padding: 4px 12px; border-radius: 12px;
  font-weight: bold; font-size: 13px;
  max-width: 160px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  display: inline-block; vertical-align: middle;
}
.turn-badge.blue  { background: rgba(116,185,255,0.2); color:#74b9ff; border:1px solid #74b9ff; }
.turn-badge.green { background: rgba(85,239,196,0.2);  color:#55efc4; border:1px solid #55efc4; }
.turn-badge.red   { background: rgba(255,118,117,0.2); color:#ff7675; border:1px solid #ff7675; }
.roll-type { font-size: 11px; color: #a29bfe; margin-top: 2px; }

/* ── Point zones (click targets) ── */
.pt-zone {
  position: absolute;
  width: 50px; height: 50px;   /* v262: this is the actual click/touch target — deliberately
                                   left at 50px at every screen size (see below); only the
                                   VISIBLE ring (::after) is ever resized for mobile. This
                                   div's position (left/top, set in renderPointZones() from
                                   CLICK_POINTS via bToS()) and size are never touched by v262. */
  border-radius: 50%;
  cursor: pointer;
  transform: translate(-50%, -50%);
  z-index: 10;
}
.pt-zone.legal-dest {
  z-index: 25;       /* above checkers (z-index:20) so ring is visible even when covered */
  pointer-events: auto;
}

/* ── v3.7.2 Task 7 / v3.7.2 tablet fix Task 4: software-rendered Bar
   bays ──
   Three compact, subtle, colour-specific bays (one per colour), drawn by
   renderBarZones() (04-board-render.js) purely from the board-space
   BAR_ANCHORS the captured checkers themselves use. The single large dark
   central rectangle (.bar-zone-rail) is retired — these narrow vertical
   rails hug each colour's checker column and grow UPWARD with the stack,
   so the central logo reads through and the board centre no longer looks
   like one dark block. z-index sits below .checker (20) and .pt-zone (10)
   so a bay can never cover a checker or intercept a point click;
   pointer-events:none for the same reason. Board-design-independent:
   positioned only via bToS(), never from board artwork. ── */
.bar-zone-color {
  position: absolute;
  z-index: 4;
  pointer-events: none;
  border-radius: 999px;
  transition: height 0.2s ease, top 0.2s ease, background 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
}
/* v3.7.2 follow-up: the first pass read as barely-there. Opacity is up a
   step so the three bays clearly look intentional (and evenly placed
   around the logo), while staying translucent enough that the board art
   and the central logo still read through. Each colour keeps a distinct
   hue plus a stronger solid-colour rim at the base as an at-a-glance
   "this bay is Blue / Red / Green" cue. */
.bar-zone-color.bar-zone-blue {
  background: linear-gradient(180deg, rgba(116,185,255,0.18), rgba(116,185,255,0.38));
  border: 1px solid rgba(116,185,255,0.60);
  border-bottom: 3px solid rgba(116,185,255,0.90);
  box-shadow: inset 0 0 14px rgba(116,185,255,0.24), 0 1px 4px rgba(0,0,0,0.4);
}
.bar-zone-color.bar-zone-green {
  background: linear-gradient(180deg, rgba(85,239,196,0.18), rgba(85,239,196,0.38));
  border: 1px solid rgba(85,239,196,0.60);
  border-bottom: 3px solid rgba(85,239,196,0.90);
  box-shadow: inset 0 0 14px rgba(85,239,196,0.24), 0 1px 4px rgba(0,0,0,0.4);
}
.bar-zone-color.bar-zone-red {
  background: linear-gradient(180deg, rgba(255,118,117,0.18), rgba(255,118,117,0.38));
  border: 1px solid rgba(255,118,117,0.60);
  border-bottom: 3px solid rgba(255,118,117,0.90);
  box-shadow: inset 0 0 14px rgba(255,118,117,0.24), 0 1px 4px rgba(0,0,0,0.4);
}
/* Clearly stronger once that colour actually has checkers on the bar. */
.bar-zone-color.bar-zone-occupied.bar-zone-blue {
  background: linear-gradient(180deg, rgba(116,185,255,0.22), rgba(116,185,255,0.46));
  border-color: rgba(116,185,255,0.80);
}
.bar-zone-color.bar-zone-occupied.bar-zone-green {
  background: linear-gradient(180deg, rgba(85,239,196,0.22), rgba(85,239,196,0.46));
  border-color: rgba(85,239,196,0.80);
}
.bar-zone-color.bar-zone-occupied.bar-zone-red {
  background: linear-gradient(180deg, rgba(255,118,117,0.22), rgba(255,118,117,0.46));
  border-color: rgba(255,118,117,0.80);
}
/* v262: the visible legal-destination ring is now a separate inner
   ::after pseudo-element, decoupled from .pt-zone's own 50x50 box (the
   actual touch/click target, unchanged above). Default size/appearance
   here is identical to the pre-v262 .pt-zone.legal-dest box (50px
   diameter, same border/background/box-shadow values) — desktop/tablet
   look exactly as before. Only the two mobile media queries further
   below shrink it. pointer-events:none on the ring itself — .pt-zone
   remains the sole element that ever receives the click. */
/* v3.9 refinement — the legal-destination ring hue follows the mover's
   colour (body.tgx-legal-blue/green/red, set by highlightDestinations()).
   Default (no class / green player) keeps the exact pre-v3.9 green look.
   Same shape/size/glow structure for all three — only the hue changes —
   plus a faint white inner outline so the ring still reads as a positive
   target on any board design. Legality, marker count, coordinates and
   interaction are untouched. */
:root {
  --tgx-ring-rgb: 85, 239, 196;   /* green — unchanged default */
  --tgx-ring-hex: #55efc4;
}
body.tgx-legal-blue  { --tgx-ring-rgb: 116, 185, 255; --tgx-ring-hex: #74b9ff; }
body.tgx-legal-green { --tgx-ring-rgb: 85, 239, 196;  --tgx-ring-hex: #55efc4; }
body.tgx-legal-red   { --tgx-ring-rgb: 255, 118, 117; --tgx-ring-hex: #ff7675; }

.pt-zone.legal-dest::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 50px;
  height: 50px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: rgba(var(--tgx-ring-rgb), 0.20);
  border: 3px solid var(--tgx-ring-hex);
  box-shadow:
    0 0 14px rgba(var(--tgx-ring-rgb), 0.7),
    inset 0 0 8px rgba(var(--tgx-ring-rgb), 0.25),
    inset 0 0 0 1px rgba(255,255,255,0.45);
  pointer-events: none;
}
.pt-zone.legal-dest:hover::after {
  background: rgba(var(--tgx-ring-rgb), 0.50);
}
/* v262: narrow/mobile screens only — shrink the VISIBLE ring (border
   thickness and glow scaled down proportionally too, so the glow itself
   doesn't stay large and defeat the purpose). The 50x50 .pt-zone touch
   target above is completely unaffected at every width — the actual
   clickable area, its position, and CLICK_POINTS/legal-move logic are
   untouched. Breakpoints reuse this file's own existing 520px/360px
   convention (already used elsewhere in this stylesheet). */
@media (max-width: 520px) {
  .pt-zone.legal-dest::after {
    width: 22px;
    height: 22px;
    border-width: 2px;
    box-shadow: 0 0 7px rgba(var(--tgx-ring-rgb),0.7), inset 0 0 4px rgba(var(--tgx-ring-rgb),0.25), inset 0 0 0 1px rgba(255,255,255,0.45);
  }
}
@media (max-width: 360px) {
  .pt-zone.legal-dest::after {
    width: 18px;
    height: 18px;
    border-width: 1.5px;
    box-shadow: 0 0 5px rgba(var(--tgx-ring-rgb),0.7), inset 0 0 3px rgba(var(--tgx-ring-rgb),0.25), inset 0 0 0 1px rgba(255,255,255,0.4);
  }
}

/* When destinations are active, dim normal point-number labels so they
   don't compete with the bold destination labels.                       */
body.destinations-active .pt-num {
  opacity: 0.20;
}

/* ── Point number labels (v97 style, v99 outside placement) ── */
.pt-num {
  position: absolute;
  font-size: 11px;
  font-weight: 900;
  color: #0d0d0d;
  background: #ffd700;
  padding: 2px 5px;
  border-radius: 4px;
  border: 1px solid rgba(0,0,0,0.30);
  box-shadow: 0 1px 3px rgba(0,0,0,0.50);
  pointer-events: none;
  z-index: 13;
  display: none;
  font-family: 'Courier New', monospace;
  white-space: nowrap;
  line-height: 1.2;
  transform: translate(-50%, -50%);
  transition: opacity 0.15s;
  letter-spacing: 0.3px;
}
body.show-numbers .pt-num { display: block; }

/* ── Checker circles ── */
.checker {
  position: absolute;
  border-radius: 50%;
  cursor: pointer;
  transform: translate(-50%, -50%);
  z-index: 20;
  /* v3.9 Module A — a checker is a drag source: suppress the browser's own
     pan/scroll gesture only for touches that START on a checker, so a
     Human drag isn't stolen by the page. Page scrolling everywhere else
     (board wood, point zones, panels) is untouched — this is not a global
     scroll lock. A quick tap still selects exactly as before. */
  touch-action: none;
  /* v3.9 refinement (2nd pass) — suppress the native iOS long-press
     callout / image-drag magnifier ONLY on the checker itself (the app's
     own selection loupe replaces it). Nothing else on the page is
     affected. */
  -webkit-touch-callout: none;
  -webkit-user-drag: none;
  font-size: 10px;
  font-weight: bold;
  color: rgba(0,0,0,0.7);
  display: flex; align-items: center; justify-content: center;
  border: 2px solid rgba(255,255,255,0.35);
  transition: box-shadow 0.15s, border-color 0.15s;
  font-family: 'Courier New', monospace;
  user-select: none;
  /* v186: layered shadow gives each checker real height off the board —
     a tight contact shadow grounds it, a wider soft shadow lifts it,
     and the inset highlight/shade pair simulates a domed glossy top. */
  box-shadow:
    inset 0 -3px 5px rgba(0,0,0,0.35),
    inset 0 2px 3px rgba(255,255,255,0.45),
    0 1px 1px rgba(0,0,0,0.5),
    0 3px 6px rgba(0,0,0,0.45);
}
.checker::after {
  /* Specular highlight — a small bright glint near the top-left, like
     light catching a polished domed checker. Purely decorative; does
     not affect layout, sizing, or click targets (pointer-events:none). */
  content: '';
  position: absolute;
  top: 14%;
  left: 22%;
  width: 32%;
  height: 22%;
  border-radius: 50%;
  background: radial-gradient(circle at center, rgba(255,255,255,0.75), rgba(255,255,255,0) 75%);
  pointer-events: none;
}
.checker::before {
  /* v262: invisible touch/click halo — expands the checker's actual
     hit area slightly beyond its visible circle, without moving or
     resizing the visible checker (this rule is purely geometric/
     invisible; the specular ::after above is untouched). A click
     anywhere in this pseudo-element's box is reported by the browser as
     a click on the .checker element itself (pseudo-elements are not
     separate event targets), so the existing click listener on each
     checker fires exactly as before — no new JS click handling needed.
     Size comes from --checker-halo-inset, set once per render in
     renderPieces()/renderBarPieces() from the small, geometrically-
     capped HALO_INSET_BOARD constant (see its definition for the
     board-wide spacing check) scaled by the same board-scale factor as
     the checker itself, so the halo stays proportionally tiny relative
     to checker size at every viewport and can never reach a
     neighbouring point's checker or click target. */
  content: '';
  position: absolute;
  inset: calc(-1 * var(--checker-halo-inset, 0px));
  border-radius: 50%;
  background: transparent;
}
.checker.blue  { background: radial-gradient(circle at 35% 32%, #8fc6ff 0%, #4a90d9 45%, #1d5f99 80%, #134a7d 100%); }
.checker.green { background: radial-gradient(circle at 35% 32%, #82f5d9 0%, #2cd9a8 45%, #009873 80%, #00735a 100%); }
.checker.red   { background: radial-gradient(circle at 35% 32%, #ff9b9a 0%, #ec5e5d 45%, #b8332f 80%, #962720 100%); }
.checker.selected {
  border-color: var(--tx-gold);
  box-shadow:
    inset 0 -3px 5px rgba(0,0,0,0.35),
    inset 0 2px 3px rgba(255,255,255,0.45),
    0 0 0 2px rgba(216,180,106,0.4),
    0 0 14px rgba(216,180,106,0.85),
    0 3px 6px rgba(0,0,0,0.45);
}
.checker:hover { border-color: rgba(255,255,255,0.75); }

/* ════════════════════════════════════════════════════════════════════
   v3.7.10 Task 4 / 5 — AI checker-move presentation animation
   (+ v3.8 polish: selection dwell, checker visibility, red-finger fix;
    + v3.8.1 polish: longer dwell, bigger + glowing hand, SE fingertip
    contact, gentle dwell pulse;
    + v3.9 Module A: the SAME hand language for a HUMAN drag — see the
    .tgx-human-drag-proxy / .tgx-human-hand block further down).
   Purely visual overlay elements added/removed inside #board-wrap by
   js/04-board-render.js. They never receive pointer events and never
   affect layout or the authoritative .checker elements.
   ════════════════════════════════════════════════════════════════════ */
.tgx-move-traveller {
  position: absolute;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  transform-origin: center center;
  z-index: 46;                     /* above .checker (20) + selected ring (25/35), below the finger */
  pointer-events: none;
  /* v3.8 Task 2 — a stronger outline + contrast ring so the moving
     checker stays clearly readable next to the finger. */
  border: 3px solid rgba(255,255,255,0.9);
  box-shadow:
    inset 0 -3px 5px rgba(0,0,0,0.35),
    inset 0 2px 3px rgba(255,255,255,0.5),
    0 0 0 2px rgba(0,0,0,0.55),
    0 0 10px rgba(255,255,255,0.35),
    0 6px 16px rgba(0,0,0,0.55);
  will-change: left, top, transform;
  transition: transform 0.12s ease-out, box-shadow 0.12s ease-out;
}
.tgx-move-traveller.blue  { background: radial-gradient(circle at 35% 32%, #8fc6ff 0%, #4a90d9 45%, #1d5f99 80%, #134a7d 100%); }
.tgx-move-traveller.green { background: radial-gradient(circle at 35% 32%, #82f5d9 0%, #2cd9a8 45%, #009873 80%, #00735a 100%); }
.tgx-move-traveller.red   { background: radial-gradient(circle at 35% 32%, #ff9b9a 0%, #ec5e5d 45%, #b8332f 80%, #962720 100%); }
.tgx-move-traveller.tgx-move-emphasize {
  transform: translate(-50%, -50%) scale(1.22);
  box-shadow:
    inset 0 -3px 5px rgba(0,0,0,0.35),
    inset 0 2px 3px rgba(255,255,255,0.5),
    0 0 0 3px rgba(255,255,255,0.55),
    0 0 20px rgba(255,255,255,0.7),
    0 6px 16px rgba(0,0,0,0.55);
  /* v3.8.1 Task 4 — a gentle pulse while the finger dwells on the source
     checker, so the eye is drawn to it. Subtle (±2%), the checker stays
     the star; disabled for prefers-reduced-motion below. */
  animation: tgxDwellPulse 1.05s ease-in-out infinite;
}
@keyframes tgxDwellPulse {
  0%, 100% { transform: translate(-50%, -50%) scale(1.20);
             box-shadow: inset 0 -3px 5px rgba(0,0,0,0.35), inset 0 2px 3px rgba(255,255,255,0.5),
                         0 0 0 3px rgba(255,255,255,0.5), 0 0 16px rgba(255,255,255,0.6), 0 6px 16px rgba(0,0,0,0.55); }
  50%      { transform: translate(-50%, -50%) scale(1.25);
             box-shadow: inset 0 -3px 5px rgba(0,0,0,0.35), inset 0 2px 3px rgba(255,255,255,0.5),
                         0 0 0 3px rgba(255,255,255,0.65), 0 0 24px rgba(255,255,255,0.85), 0 6px 16px rgba(0,0,0,0.55); }
}
/* v3.8 Task 2 — stays visibly larger than a normal checker for the whole
   travel so the eye tracks it under/beside the finger. */
.tgx-move-traveller.tgx-move-travelling {
  transform: translate(-50%, -50%) scale(1.16);
}
.tgx-move-traveller.tgx-move-settle {
  animation: tgxMoveSettle 0.16s ease-out;
  animation-fill-mode: forwards;
}
@keyframes tgxMoveSettle {
  0%   { transform: translate(-50%, -50%) scale(1.16); }
  55%  { transform: translate(-50%, -50%) scale(1.05); }
  100% { transform: translate(-50%, -50%) scale(1.12); }
}

.tgx-move-finger {
  /* v3.8 Task 3 — `position: fixed` (set inline by js/04-board-render.js)
     on <body>, so the pointer is NEVER inside the auto-rotating
     #board-rotation-shell and always renders upright on screen, whatever
     the board view (Blue 0° / Green 120° / Red 240°). A rAF loop keeps it
     glued to the travelling checker's live on-screen position.
     v3.8.1 Task 3 — the JS now places the fingertip (at ~24%,6% of the
     artwork) at the checker's SOUTH-EAST edge, so it reads as the index
     finger guiding the checker rather than the palm.
     v3.8.1 Task 2 — ~25% larger and a soft player-colour glow (per-colour
     filter below) so the hand is easy to notice; the checker stays
     dominant. `--tgx-finger-rot` is a small screen-space lean. */
  transform: rotate(var(--tgx-finger-rot, 0deg));
  transform-origin: 24% 6%;        /* the fingertip */
  z-index: 2000;                   /* above the board layer; the finger is cleared before any modal opens */
  pointer-events: none;
  height: auto;
  filter: drop-shadow(0 3px 6px rgba(0,0,0,0.6));
  will-change: left, top, transform, opacity;
}
/* v3.8.1 Task 2 — restrained coloured halo, layered over the contact
   shadow. Readable across board designs; not cartoonish. */
.tgx-move-finger.blue  { filter: drop-shadow(0 3px 6px rgba(0,0,0,0.6)) drop-shadow(0 0 7px rgba(90,175,255,0.95)) drop-shadow(0 0 16px rgba(90,175,255,0.55)); }
.tgx-move-finger.green { filter: drop-shadow(0 3px 6px rgba(0,0,0,0.6)) drop-shadow(0 0 7px rgba(64,235,190,0.95)) drop-shadow(0 0 16px rgba(64,235,190,0.55)); }
.tgx-move-finger.red   { filter: drop-shadow(0 3px 6px rgba(0,0,0,0.6)) drop-shadow(0 0 7px rgba(255,120,118,0.95)) drop-shadow(0 0 16px rgba(255,120,118,0.55)); }

.tgx-move-ghost {
  position: absolute;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  z-index: 44;
  pointer-events: none;
  opacity: 0.85;
  border: 2px solid rgba(255,255,255,0.35);
  box-shadow: 0 2px 6px rgba(0,0,0,0.5);
}
.tgx-move-ghost.blue  { background: radial-gradient(circle at 35% 32%, #8fc6ff 0%, #4a90d9 45%, #1d5f99 80%, #134a7d 100%); }
.tgx-move-ghost.green { background: radial-gradient(circle at 35% 32%, #82f5d9 0%, #2cd9a8 45%, #009873 80%, #00735a 100%); }
.tgx-move-ghost.red   { background: radial-gradient(circle at 35% 32%, #ff9b9a 0%, #ec5e5d 45%, #b8332f 80%, #962720 100%); }

@media (prefers-reduced-motion: reduce) {
  .tgx-move-traveller { transition: none; }
  .tgx-move-traveller.tgx-move-emphasize  { animation: none; transform: translate(-50%, -50%) scale(1.14); }
  .tgx-move-traveller.tgx-move-travelling { transform: translate(-50%, -50%) scale(1.12); }
  .tgx-move-traveller.tgx-move-settle { animation: none; transform: translate(-50%, -50%) scale(1.12); }
}

/* ════════════════════════════════════════════════════════════════════
   v3.9 MODULE A — HUMAN DRAG-AND-DROP PROXY + MATCHING COLOURED HAND
   A pointer-driven drag proxy for a HUMAN player. Both elements are
   `position: fixed` on <body> (set inline by js/04-board-render.js), so
   like the AI hand they NEVER inherit #board-rotation-shell's Blue/Green/
   Red rotation and always render upright. pointer-events:none end to end,
   so the drop is resolved from the real element under the release, never
   from the proxy. The hand reuses .tgx-move-finger verbatim (colour glow,
   SE fingertip, --tgx-finger-rot lean); only the extra .tgx-human-hand
   marker class is added so cleanup can target human vs AI hands.
   ════════════════════════════════════════════════════════════════════ */
.tgx-human-drag-proxy {
  position: fixed;
  border-radius: 50%;
  transform: translate(-50%, -50%) scale(1.16);   /* stays visibly dominant, like the AI traveller in flight */
  transform-origin: center center;
  z-index: 1990;                  /* above the board layer, just below the hand (2000) */
  pointer-events: none;
  border: 3px solid rgba(255,255,255,0.9);
  box-shadow:
    inset 0 -3px 5px rgba(0,0,0,0.35),
    inset 0 2px 3px rgba(255,255,255,0.5),
    0 0 0 2px rgba(0,0,0,0.55),
    0 0 12px rgba(255,255,255,0.4),
    0 8px 20px rgba(0,0,0,0.55);
  will-change: left, top;
}
.tgx-human-drag-proxy.blue  { background: radial-gradient(circle at 35% 32%, #8fc6ff 0%, #4a90d9 45%, #1d5f99 80%, #134a7d 100%); }
.tgx-human-drag-proxy.green { background: radial-gradient(circle at 35% 32%, #82f5d9 0%, #2cd9a8 45%, #009873 80%, #00735a 100%); }
.tgx-human-drag-proxy.red   { background: radial-gradient(circle at 35% 32%, #ff9b9a 0%, #ec5e5d 45%, #b8332f 80%, #962720 100%); }

/* While a Human drag is live, don't let the source checker's own :hover
   border flicker under a stationary pointer, and keep the text cursor
   from appearing over the board. Purely cosmetic. */
body.tgx-human-dragging { cursor: grabbing; }
body.tgx-human-dragging .checker:hover { border-color: rgba(255,255,255,0.35); }

/* v3.9 refinement (2nd pass) — HUMAN SELECTION LOUPE (Task 3).
   A small app-owned magnifier (deterministic — NOT the flaky native iOS
   one) shown while a Human has a movable checker under the pointer: an
   enlarged, colour-matched checker, screen-upright, positioned above the
   finger (JS) so the finger never hides it. z below the hand (2000) and
   proxy is 1990; pointer-events:none so it can never intercept a ring or
   a drop. Created on pointerdown, removed on every exit path. */
.tgx-human-loupe {
  position: fixed;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  transform-origin: center center;
  z-index: 1996;
  pointer-events: none;
  display: flex; align-items: center; justify-content: center;
  background: radial-gradient(circle at 50% 38%, rgba(24,26,32,0.92), rgba(8,9,12,0.96));
  border: 2px solid rgba(255,255,255,0.55);
  box-shadow: 0 6px 18px rgba(0,0,0,0.55), inset 0 0 10px rgba(0,0,0,0.5);
  will-change: left, top;
}
.tgx-human-loupe.blue  { box-shadow: 0 6px 18px rgba(0,0,0,0.55), inset 0 0 10px rgba(0,0,0,0.5), 0 0 0 3px rgba(90,175,255,0.5),  0 0 16px rgba(90,175,255,0.55); }
.tgx-human-loupe.green { box-shadow: 0 6px 18px rgba(0,0,0,0.55), inset 0 0 10px rgba(0,0,0,0.5), 0 0 0 3px rgba(64,235,190,0.5),  0 0 16px rgba(64,235,190,0.55); }
.tgx-human-loupe.red   { box-shadow: 0 6px 18px rgba(0,0,0,0.55), inset 0 0 10px rgba(0,0,0,0.5), 0 0 0 3px rgba(255,120,118,0.5), 0 0 16px rgba(255,120,118,0.55); }
.tgx-human-loupe-checker {
  border-radius: 50%;
  border: 3px solid rgba(255,255,255,0.92);
  box-shadow:
    inset 0 -3px 6px rgba(0,0,0,0.4),
    inset 0 3px 5px rgba(255,255,255,0.45),
    0 2px 6px rgba(0,0,0,0.5);
  display: flex; align-items: center; justify-content: center;
  color: rgba(0,0,0,0.7); font-weight: bold; font-family: 'Courier New', monospace;
}
.tgx-human-loupe-checker.blue  { background: radial-gradient(circle at 35% 32%, #8fc6ff 0%, #4a90d9 45%, #1d5f99 80%, #134a7d 100%); }
.tgx-human-loupe-checker.green { background: radial-gradient(circle at 35% 32%, #82f5d9 0%, #2cd9a8 45%, #009873 80%, #00735a 100%); }
.tgx-human-loupe-checker.red   { background: radial-gradient(circle at 35% 32%, #ff9b9a 0%, #ec5e5d 45%, #b8332f 80%, #962720 100%); }

@media (prefers-reduced-motion: reduce) {
  .tgx-human-drag-proxy { transform: translate(-50%, -50%) scale(1.12); }
}

/* ── Destination hint labels (v96 — point number is dominant) ── */
/* ── Destination hint labels — v107: compact, offset, minimal ── */
.dest-hint {
  position: absolute;
  pointer-events: none;
  z-index: 35;
  background: rgba(8, 12, 22, 0.82);
  color: #55efc4;
  font-size: 10px;
  font-weight: bold;
  font-family: 'Courier New', monospace;
  padding: 2px 5px;
  border-radius: 3px;
  border: 1px solid rgba(85,239,196,0.4);
  white-space: nowrap;
  line-height: 1.35;
  box-shadow: 0 1px 4px rgba(0,0,0,0.6);
}
/* Point number inside the destination ring */
.dest-ring-num {
  position: absolute;
  pointer-events: none;
  z-index: 16;
  transform: translate(-50%, -50%);
  font-size: 11px;
  font-weight: 900;
  font-family: 'Courier New', monospace;
  color: #55efc4;
  text-shadow: 0 0 5px rgba(0,0,0,0.95), 0 0 10px rgba(0,0,0,0.8);
  white-space: nowrap;
  line-height: 1;
}

/* ── Move log ── */
.move-log .ml-blue  { color: #74b9ff; }
.move-log .ml-green { color: #55efc4; }
.move-log .ml-red   { color: #ff7675; }
.move-log .ml-sys   { color: #a29bfe; }

.dice-label {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 1px;
  color: #d8d8d8;
  margin-bottom: 2px;
}
.turn-badge {
  padding: 4px 12px; border-radius: 12px;
  font-weight: bold; font-size: 13px;
  max-width: 160px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  display: inline-block; vertical-align: middle;
}
.turn-badge.blue  { background: rgba(116,185,255,0.2); color:#74b9ff; border:1px solid #74b9ff; }
.turn-badge.green { background: rgba(85,239,196,0.2);  color:#55efc4; border:1px solid #55efc4; }
.turn-badge.red   { background: rgba(255,118,117,0.2); color:#ff7675; border:1px solid #ff7675; }
.roll-type { font-size: 11px; color: #a29bfe; margin-top: 2px; }
.info-bar .ok  { color: #55efc4; }
.info-bar .err { color: #ff7675; }

/* ── Move list panel ── */
.move-list-panel.active { display: block; }
.move-list-panel .mlp-title {
  color: #a29bfe; font-weight: bold; font-size: 11px;
  text-transform: uppercase; letter-spacing: 0.8px; margin-bottom: 4px;
}
.move-list-panel .mlp-row    { color: #55efc4; }
.move-list-panel .mlp-blocked { color: #ff7675; }
/* ── Anchor calibration overlay (v87) ── */
.anchor-dot {
  position: absolute;
  pointer-events: none;
  z-index: 50;
  transform: translate(-50%, -50%);
}
/* Crosshair arms */
.anchor-dot::before,
.anchor-dot::after {
  content: '';
  position: absolute;
  background: #ff0080;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
}
.anchor-dot::before { width: 14px; height: 2px; }   /* horizontal */
.anchor-dot::after  { width: 2px;  height: 14px; }  /* vertical */
/* Centre fill */
.anchor-dot-inner {
  position: absolute;
  width: 6px; height: 6px;
  background: #ff0080;
  border-radius: 50%;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  pointer-events: none;
}
.anchor-label {
  position: absolute;
  pointer-events: none;
  z-index: 51;
  font-size: 10px;
  font-weight: bold;
  font-family: 'Courier New', monospace;
  color: #ff0080;
  background: rgba(0,0,0,0.75);
  padding: 1px 4px;
  border-radius: 3px;
  white-space: nowrap;
  /* positioned via JS */
}
/* Stack step preview line (A→D connector) */
.anchor-step-line {
  position: absolute;
  pointer-events: none;
  z-index: 49;
  background: rgba(0,206,201,0.55);
  height: 2px;
  transform-origin: left center;
}
/* Direction handle — cyan rotated square (diamond) */
.dir-dot {
  position: absolute;
  pointer-events: none;
  z-index: 52;
  width: 14px; height: 14px;
  background: #00cec9;
  border: 2px solid #fff;
  border-radius: 3px;
  transform: translate(-50%,-50%) rotate(45deg);
}
/* Direction label D{N} */
.dir-label {
  position: absolute;
  pointer-events: none;
  z-index: 53;
  font-size: 10px;
  font-weight: bold;
  font-family: 'Courier New', monospace;
  color: #00cec9;
  background: rgba(0,0,0,0.78);
  padding: 1px 4px;
  border-radius: 3px;
  white-space: nowrap;
}
/* Edit-mode: make direction handles draggable */
body.anchor-edit-mode .dir-dot {
  cursor: crosshair !important;
  pointer-events: auto !important;
  outline: 2px solid #ffd700;
  outline-offset: 3px;
  z-index: 72 !important;
  user-select: none;
}
body.anchor-edit-mode .dir-dot:hover {
  outline-color: #ff0080;
  background: #81ecec;
}
/* Export panel */
.anchor-export-panel {
  max-width: 900px; width: 100%;
  margin-top: 8px;
  background: var(--tx-bg-panel-2);
  border: 1px solid #ff0080;
  border-radius: 6px;
  padding: 10px 14px;
  display: none;
}
.anchor-export-panel.open { display: block; }
.anchor-export-panel textarea {
  width: 100%;
  min-height: 120px;
  background: #070710;
  border: 1px solid #444;
  color: #ff80d0;
  font-family: 'Courier New', monospace;
  font-size: 11px;
  border-radius: 4px;
  padding: 6px;
  resize: vertical;
}
/* ── Last-move markers (v91) ── */
.last-move-label {
  position: absolute;
  pointer-events: none;
  z-index: 40;
  font-size: 11px;
  font-weight: bold;
  font-family: 'Courier New', monospace;
  padding: 2px 6px;
  border-radius: 4px;
  white-space: nowrap;
  transform: translate(-50%, -220%);
  border: 1px solid currentColor;
  opacity: 0.92;
}
.last-move-label.lm-from {
  background: rgba(0,0,0,0.75);
  /* colour set per player via inline style */
}
.last-move-label.lm-to {
  background: rgba(0,0,0,0.75);
  transform: translate(-50%, 120%);
}
/* Arrow connector between FROM and TO zones */
.last-move-connector {
  position: absolute;
  pointer-events: none;
  z-index: 38;
  height: 2px;
  transform-origin: left center;
  opacity: 0.55;
}
/* ── Click-zone overlay (v94) ── */
.czl-ring {
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
  z-index: 55;
  transform: translate(-50%, -50%);
  background: rgba(180, 180, 180, 0.16);
  border: 2px solid rgba(235, 235, 235, 0.85);
  box-shadow:
    0 0 10px rgba(255,255,255,0.75),
    0 0 20px rgba(120,120,120,0.45),
    inset 0 0 8px rgba(255,255,255,0.25);
}
.czl-label {
  position: absolute;
  pointer-events: none;
  z-index: 56;
  font-size: 11px;
  font-weight: bold;
  font-family: 'Courier New', monospace;
  color: #f5f5f5;
  text-shadow: 0 1px 2px #000;
  background: rgba(40,40,40,0.85);
  padding: 1px 4px;
  border-radius: 3px;
  white-space: nowrap;
  border: 1px solid rgba(220,220,220,0.60);
}
/* ── Point-label export panel — removed in v105 (edit tools hidden) ── */
/* ── Checker-anchor drag editor (v108) ── */
body.anchor-edit-mode .anchor-dot {
  cursor: move !important;
  pointer-events: auto !important;
  outline: 3px solid #00cec9;
  outline-offset: 2px;
  z-index: 70 !important;
  user-select: none;
}
body.anchor-edit-mode .anchor-dot:hover {
  outline-color: #ffd700;
}
/* Instruction hint shown in anchor-edit mode */
#anchor-edit-hint {
  display: none;
  max-width: 900px;
  width: 100%;
  padding: 5px 12px;
  background: rgba(0,206,201,0.10);
  border: 1px solid #00cec9;
  border-radius: 5px;
  color: #81ecec;
  font-size: 11px;
  font-family: 'Courier New', monospace;
  margin-bottom: 6px;
  text-align: center;
}
body.anchor-edit-mode #anchor-edit-hint { display: block; }
/* ── Left-side diagnostic overlay (v113) ── */
/* Selected-point badge beside the selected checker */
.selected-pt-badge {
  position: absolute;
  pointer-events: none;
  z-index: 80;
  background: #ffd700;
  color: #0d0d0d;
  font-size: 11px;
  font-weight: 900;
  font-family: 'Courier New', monospace;
  padding: 3px 7px;
  border-radius: 4px;
  border: 1px solid rgba(0,0,0,0.4);
  box-shadow: 0 2px 6px rgba(0,0,0,0.7);
  white-space: nowrap;
  transform: translate(22px, -50%);
}
/* Debug overlay markers for left side (pts 13-24) */
.dbg-click  { position:absolute;pointer-events:none;z-index:62;border-radius:50%;
              width:20px;height:20px;border:2px solid #ffd700;background:rgba(255,215,0,0.15);
              transform:translate(-50%,-50%); }
.dbg-anchor { position:absolute;pointer-events:none;z-index:63;
              width:12px;height:12px;transform:translate(-50%,-50%);
              background:#ff0080;border-radius:50%; }
.dbg-label-marker { position:absolute;pointer-events:none;z-index:64; }
.dbg-text  { position:absolute;pointer-events:none;z-index:65;
              font-size:9px;font-family:'Courier New',monospace;font-weight:bold;
              white-space:nowrap;background:rgba(0,0,0,0.75);padding:1px 3px;border-radius:2px; }
.dbg-text.tc { color:#ffd700; }   /* click point — yellow */
.dbg-text.ta { color:#ff80d0; }   /* anchor — pink */
.dbg-text.tl { color:#81ecec; }   /* label position — cyan */
/* ── v245: Game Trends — Pip Race / Dice Fortune inline-SVG charts ── */
.gt-chart-block {
  background: rgba(4, 6, 14, 0.85);
  border: 1px solid var(--tx-line);
  border-radius: var(--tx-radius-sm);
  padding: 8px 8px 6px;
  margin-bottom: 8px;
  box-shadow: inset 0 2px 6px rgba(0,0,0,0.5), inset 0 -1px 0 rgba(255,255,255,0.03);
}
.gt-chart-title {
  font-size: 10px;
  font-family: 'Courier New', monospace;
  font-weight: bold;
  color: var(--tx-text-dim);
  margin-bottom: 4px;
  letter-spacing: 0.3px;
}
.gt-chart-sub {
  font-weight: normal;
  font-size: 9px;
  color: var(--tx-text-faint);
  text-transform: none;
  letter-spacing: 0;
}
.gt-chart-svg-wrap {
  width: 100%;
  line-height: 0;   /* avoid a stray inline-svg baseline gap */
}
.gt-chart-svg-wrap svg {
  display: block;
  width: 100%;
  height: auto;
  /* v4.1.1 (Pip Race recording stability): pin the chart's rendered
     height to the fixed 620×300 viewBox ratio explicitly. render-
     GameTrendsCharts() rebuilds the SVG by reassigning innerHTML every
     completed turn; an explicit aspect-ratio makes the new node's height
     resolve deterministically from the (stable) column width on the first
     layout pass — no dependence on viewBox intrinsic-ratio timing, and no
     change on any axis-scale or value-label update. Height stays purely a
     function of the column width, i.e. responsive at every breakpoint
     with no fixed desktop-only pixel height. NOTE: the wrapper itself is
     deliberately left to size to its content — it also holds the fixed
     .gt-legend row, so a hard height/overflow on the wrapper would clip
     the legend. */
  aspect-ratio: 620 / 300;
}
/* The two chart blocks are rewritten one after the other inside a single
   renderGameTrendsCharts() call; flex-start stops a one-frame height
   difference between them from stretching the row (and the Game Trends
   section) taller mid-update. */
.gt-large-row {
  align-items: flex-start;
}
/* Keep the Game Trends card's own per-turn innerHTML rebuild from
   propagating layout work to the rest of the page, and keep the card from
   being chosen as the scroll anchor while its subtree is being replaced.
   (Defensive — measured chart-container movement is already zero.) */
#pro-card-trends {
  contain: layout;
  overflow-anchor: none;
}

/* ── v5.0.6 (public §1) — Pip Race / Game Trends promoted to a WIDE
   visual area placed directly ABOVE Table Talk, inside the board column
   (.board-panel). Uses the full board-column width (up to .board-panel's
   980px max), with the two large charts side by side on desktop and
   stacked on iPad / narrow / mobile — purely via flex-wrap, no JS layout
   switching. The v4.1.1 stability guarantees are untouched:
   #pro-card-trends still has contain:layout + overflow-anchor:none above,
   and each chart SVG still resolves its height from the fixed
   aspect-ratio:620/300 and the (stable) column width — no vertical bob
   on axis-scale / value-label updates. Chart ids, data, calculations and
   update timing are unchanged; only the card's DOM position and width
   changed. ── */
.board-panel > #pro-card-trends {
  width: 100%;
  margin: 4px 0 2px;
}
.board-panel > #pro-card-trends .gt-large-row {
  gap: 14px;
}
.board-panel > #pro-card-trends .gt-chart-block-large {
  /* two-up whenever the board column is wide enough for a readable pair
     (~560px+ each side of the gap); below that they wrap and stack. */
  flex: 1 1 46%;
  min-width: 0;
  max-width: none;
  padding: 12px 14px 10px;
}
@media (max-width: 700px) {
  .board-panel > #pro-card-trends .gt-chart-block-large {
    flex: 1 1 100%;   /* explicit single-column stack on narrow / iPad portrait / mobile */
  }
  .board-panel > #pro-card-trends .gt-large-row { gap: 10px; }
}
.gt-legend {
  display: flex;
  gap: 10px;
  justify-content: center;
  margin-top: 4px;
  font-size: 9px;
  font-family: 'Courier New', monospace;
  color: var(--tx-text-dim);
}
.gt-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.gt-legend-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  display: inline-block;
}

/* ── v245 (large-charts-rng pass): full-width Game Trends section,
   below the board/sidebar layout, above the Admin/Setup shell. Charts
   sit side-by-side on wide screens and stack on narrow ones purely via
   flex-wrap — no JS-driven layout switching needed. ── */
.game-trends-shell {
  width: 100%;
  max-width: 1400px;
  margin: 18px auto 0 auto;
}
.game-trends-shell .panel-title {
  font-size: 12px;
  letter-spacing: 2px;
}
.gt-large-row {
  display: flex;
  flex-wrap: wrap;
  gap: 18px;
  justify-content: center;
}
.gt-chart-block-large {
  flex: 1 1 480px;
  max-width: 700px;
  min-width: 320px;
  padding: 16px 18px 12px;
}
.gt-chart-block-large .gt-chart-title {
  font-size: 15px;
  margin-bottom: 8px;
}
.gt-chart-block-large .gt-chart-sub {
  font-size: 12px;
}
.gt-chart-block-large .gt-legend {
  font-size: 12px;
  gap: 16px;
  margin-top: 8px;
}
.gt-chart-block-large .gt-legend-dot {
  width: 10px;
  height: 10px;
}

/* ── Pip bar graph (v125). v245 (large-charts-rng pass): converted from a
   small relative best-vs-worst comparison into a larger, more prominent
   fixed-scale race-progress display (see renderPipDisplay()/
   PIP_RACE_START) — bigger track height, an added %-complete column, and
   a finish-line tick at the right edge of each track. ── */
.pip-display {
  font-size: 12px;
  font-family: 'Courier New', monospace;
  line-height: 1.6;
  min-width: 170px;
}
.pip-row {
  display: grid;
  grid-template-columns: 50px 40px 1fr 38px;
  gap: 7px;
  align-items: center;
  margin: 6px 0;
}
.pip-name.blue  { color: #74b9ff; }
.pip-name.green { color: #55efc4; }
.pip-name.red   { color: #ff7675; }
.pip-name {
  font-weight: bold;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.pip-num {
  color: #ddd;
  text-align: right;
  font-size: 12px;
}
.pip-pct {
  color: var(--tx-text-dim);
  text-align: right;
  font-size: 11px;
}
.pip-track {
  position: relative;
  height: 20px;
  background: #1a1a2a;
  border-radius: 6px;
  overflow: visible;
  border: 1px solid #333;
}
.pip-track::before {
  /* finish-line marker at the fixed right edge of the track */
  content: '🏁';
  position: absolute;
  right: -13px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 12px;
  line-height: 1;
  opacity: 0.85;
}
.pip-fill {
  position: relative;
  height: 100%;
  border-radius: 5px;
  overflow: hidden;
  transition: width 0.25s ease;
}
.pip-fill.blue  { background: linear-gradient(90deg, rgba(116,185,255,0.55), #74b9ff); }
.pip-fill.green { background: linear-gradient(90deg, rgba(85,239,196,0.55), #55efc4); }
.pip-fill.red   { background: linear-gradient(90deg, rgba(255,118,117,0.55), #ff7675); }
.pip-leader .pip-num { color: #ffd700; font-weight: bold; }
.pip-leader .pip-name { font-weight: bold; }
/* ── Manual Setup Panel (v139) ── */
#manual-setup-panel {
  display: none;
  width: 100%;
  margin-bottom: 8px;
  padding: 10px 14px;
  background: var(--tx-bg-panel-2);
  border: 2px solid #fdcb6e;
  border-radius: 8px;
  font-size: 12px;
  font-family: 'Courier New', monospace;
}
#manual-setup-panel.active { display: block; }
#manual-setup-panel .msp-title {
  color: #fdcb6e;
  font-weight: bold;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.8px;
  margin-bottom: 8px;
}
#manual-setup-panel .msp-warning {
  color: #fdcb6e;
  font-size: 11px;
  margin-bottom: 8px;
  padding: 4px 8px;
  background: rgba(253,203,110,0.10);
  border-radius: 4px;
  border: 1px solid rgba(253,203,110,0.35);
}
#manual-setup-panel .msp-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  margin-bottom: 8px;
}
#manual-setup-panel label {
  color: #aaa;
  font-size: 11px;
}
#manual-setup-panel select,
#manual-setup-panel input[type=number] {
  background: #16213e;
  border: 1px solid #555;
  color: #ffd700;
  border-radius: 4px;
  font-family: 'Courier New', monospace;
  font-size: 12px;
  padding: 3px 6px;
}
#manual-setup-panel select { min-width: 90px; }
#manual-setup-panel input[type=number] { width: 52px; text-align: center; }
.btn-msp {
  padding: 5px 11px;
  border-radius: 5px;
  border: 1px solid #fdcb6e;
  background: var(--tx-bg-panel-2);
  color: #fdcb6e;
  cursor: pointer;
  font-size: 11px;
  font-weight: bold;
  font-family: inherit;
  transition: all 0.15s;
}
.btn-msp:hover { background: #fdcb6e; color: #0d0d1a; }
.btn-msp.danger { border-color: #ff7675; color: #ff7675; }
.btn-msp.danger:hover { background: #ff7675; color: #0d0d1a; }
.btn-msp.exit { border-color: #55efc4; color: #55efc4; }
.btn-msp.exit:hover { background: #55efc4; color: #0d0d1a; }
/* ── Dice mode selector ── */
.dice-mode-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 7px 0;
  font-size: 12px;
  border-bottom: 1px solid var(--tx-line);
  margin-bottom: 4px;
}
.dice-mode-bar label {
  color: #a29bfe;
  font-weight: bold;
  letter-spacing: 0.5px;
  white-space: nowrap;
}
.dice-mode-bar select {
  background: #10162a;
  border: 1px solid #ffd700;
  color: #f2f2f2;
  border-radius: 5px;
  padding: 4px 8px;
  font-size: 12px;
  font-family: inherit;
  cursor: pointer;
}
.dice-mode-bar select option {
  background: #10162a;
  color: #f2f2f2;
}
.dice-mode-bar select:focus {
  outline: none;
  border-color: #ffd700;
  box-shadow: 0 0 6px rgba(255,215,0,0.35);
}
.dice-mode-badge {
  padding: 3px 10px;
  border-radius: 10px;
  font-size: 11px;
  font-weight: bold;
  background: rgba(162,155,254,0.12);
  color: #a29bfe;
  border: 1px solid #a29bfe;
  white-space: nowrap;
}
.dice-mode-badge.triple {
  background: rgba(253,203,110,0.12);
  color: #fdcb6e;
  border-color: #fdcb6e;
}
/* ── v3.7.2 Task 5: prominent top-level PLAY MODE control. The real
   #play-mode-select <select> (styled by .dice-mode-bar above) still
   exists and still owns all behaviour — this is a visual layer only,
   driven via setPlayModeViaButton()/_syncPlayModeButtons()
   (05-gameplay-interaction.js). Deliberately more eye-catching than the
   Dice Mode bar so Tournament Mode reads as a real, inviting choice
   rather than a buried dropdown option (real iPad finding). ── */
.pm-prominent {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 8px 10px 10px;
  margin-bottom: 8px;
  border: 1px solid var(--tx-line);
  border-radius: 8px;
  background: rgba(162,155,254,0.06);
}
.pm-prominent-title {
  font-size: 11px;
  font-weight: bold;
  letter-spacing: 1px;
  color: #a29bfe;
}
.pm-prominent-buttons {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
.pm-prominent-btn {
  flex: 1 1 120px;
  padding: 9px 10px;
  font-size: 13px;
  font-weight: bold;
  font-family: inherit;
  border-radius: 7px;
  border: 2px solid #55606e;
  background: #10162a;
  color: #d0d3da;
  cursor: pointer;
  transition: transform 0.08s ease, filter 0.15s ease;
}
.pm-prominent-btn:hover:not(:disabled) { filter: brightness(1.12); }
.pm-prominent-btn:active:not(:disabled) { transform: scale(0.97); }
.pm-prominent-btn:disabled { opacity: 0.55; cursor: not-allowed; }
.pm-prominent-btn.pm-active {
  border-color: #a29bfe;
  color: #ffffff;
  background: rgba(162,155,254,0.22);
  box-shadow: 0 0 8px rgba(162,155,254,0.35);
}
.pm-prominent-btn.pm-btn-tournament.pm-active {
  border-color: #ffd700;
  background: rgba(255,215,0,0.16);
  color: #ffd700;
  box-shadow: 0 0 8px rgba(255,215,0,0.4);
}
.pm-prominent-lock-note {
  font-size: 11px;
  color: #fab1a0;
  font-style: italic;
}
@media (pointer: coarse) {
  .pm-prominent-btn { min-height: 46px; font-size: 14px; }
}
/* ── v300 UI compaction pass: compact dropdown selectors for Board Design
   (#board-design-select) and Full UI Theme (#ui-theme-select) in the
   TRIGAMMONX PRO panel, replacing the old button grid/row markup. Deliberately
   cloned from .dice-mode-bar/.dice-mode-bar select above so the two new
   controls look native to the existing Dice Mode / Play Mode selectors. ── */
.txpro-select-row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 6px 0;
  font-size: 12px;
}
.txpro-select-row + .txpro-select-row {
  border-top: 1px solid var(--tx-line);
  margin-top: 2px;
}
.txpro-select-row label {
  color: #a29bfe;
  font-weight: bold;
  letter-spacing: 0.5px;
  white-space: nowrap;
  min-width: 92px;
}
.txpro-select-row select {
  background: #10162a;
  border: 1px solid #ffd700;
  color: #f2f2f2;
  border-radius: 5px;
  padding: 4px 8px;
  font-size: 12px;
  font-family: inherit;
  cursor: pointer;
  flex: 1 1 auto;
  min-width: 140px;
  max-width: 220px;
}
.txpro-select-row select option {
  background: #10162a;
  color: #f2f2f2;
}
.txpro-select-row select:focus {
  outline: none;
  border-color: #ffd700;
  box-shadow: 0 0 6px rgba(255,215,0,0.35);
}
/* v3.1.2: selected Board Design thumbnail — compact visual confirmation
   beside the dropdown, using the same board image URL as the live board. */
.txpro-board-design-row {
  flex-wrap: nowrap;
}
.txpro-select-control {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 1 1 auto;
  min-width: 0;
}
.board-design-preview {
  width: 62px;
  height: 62px;
  flex: 0 0 62px;
  border: 1px solid rgba(255,215,0,0.55);
  border-radius: 7px;
  overflow: hidden;
  background: #10162a;
  box-shadow: 0 1px 5px rgba(0,0,0,0.28);
}
.board-design-preview img {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
}
@media (max-width: 480px) {
  .txpro-select-row select { max-width: none; }
  .board-design-preview { width: 52px; height: 52px; flex-basis: 52px; }
  .txpro-select-control { gap: 6px; flex-wrap: wrap; }
  .txpro-select-control label { min-width: 100%; }
}
/* ── v300: Tournament/Match panel — Tournament Mode only ──
   Named .txm-* deliberately (not .clock-*), since .clock-card/.clock-title
   are already used by the existing, unrelated Game/Turn/Real Time clock
   feature elsewhere on this page. */
.txm-panel {
  padding: 8px 10px 10px;
  margin-bottom: 4px;
  border: 1px solid #ffd700;
  border-radius: 8px;
  background: rgba(255,215,0,0.05);
}
.txm-title {
  font-size: 12px;
  font-weight: bold;
  color: #ffd700;
  letter-spacing: 0.5px;
  margin-bottom: 6px;
}
.txm-row {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  margin-bottom: 6px;
}
.txm-length-label {
  color: #a29bfe;
  font-weight: bold;
  white-space: nowrap;
}
.txm-row select {
  background: #10162a;
  border: 1px solid #ffd700;
  color: #f2f2f2;
  border-radius: 5px;
  padding: 3px 6px;
  font-size: 12px;
  font-family: inherit;
  cursor: pointer;
}
.txm-row select:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
.txm-scores {
  display: flex;
  gap: 6px;
  margin-bottom: 6px;
}
.txm-score-cell {
  flex: 1;
  text-align: center;
  padding: 5px 2px;
  border-radius: 6px;
  background: rgba(255,255,255,0.04);
  border: 1px solid var(--tx-line);
}
.txm-score-name {
  display: block;
  font-size: 10px;
  font-weight: bold;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.txm-score-value {
  display: block;
  font-size: 16px;
  font-weight: bold;
  color: #ffd700;
}
.txm-score-cell.txm-blue .txm-score-name  { color: var(--tx-blue-glow, #4aa8ff); }
.txm-score-cell.txm-red .txm-score-name   { color: #ff7675; }
.txm-score-cell.txm-green .txm-score-name { color: #55efc4; }
.txm-meta-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 11px;
  color: #ccc;
  margin-bottom: 8px;
}
.txm-status-complete {
  color: #ffd700;
  font-weight: bold;
}
.txm-new-match-btn {
  width: 100%;
  padding: 6px 8px;
  margin-bottom: 8px;
  background: transparent;
  border: 1px solid #ffd700;
  color: #ffd700;
  border-radius: 6px;
  font-size: 12px;
  font-weight: bold;
  cursor: pointer;
  transition: all 0.15s;
}
.txm-new-match-btn:hover {
  background: #ffd700;
  color: #0d0d1a;
}
.txm-placeholder-row {
  display: flex;
  gap: 6px;
}
.txm-placeholder-card {
  flex: 1;
  text-align: center;
  padding: 6px 4px;
  border-radius: 6px;
  border: 1px dashed var(--tx-line);
  opacity: 0.7;
  cursor: default;
}
.txm-placeholder-name {
  font-size: 10px;
  font-weight: bold;
  color: #aaa;
}
.txm-placeholder-soon {
  font-size: 9px;
  color: #888;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  margin-top: 2px;
}
/* v300 correction: small STATIC doubling-cube visual for the Tournament
   placeholder card. Brand-new, presentation-only — entirely separate from
   the existing Developer/Admin #dc-tray/#dc-token/.dc-* visual-test cube
   (different class names, no id, no onclick, no state). */
.txm-cube-face {
  width: 30px;
  height: 30px;
  margin: 0 auto 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 6px;
  background: linear-gradient(145deg, #fdf6e3, #e8d9ad);
  border: 1px solid #d8b46a;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.6), 0 1px 3px rgba(0,0,0,0.35);
  color: #6b4f1d;
  font-weight: bold;
  font-size: 15px;
  font-family: Georgia, 'Times New Roman', serif;
  opacity: 0.9;
}
/* ── v3.1.0: Tournament Clock (Task 1) — real match clock card, visible
   only in Tournament Mode (renderTournamentClockCards() in
   js/06-stats-history.js toggles #txm-clock-card's display). Reuses the
   gold/lavender/.txm-* design language above. Deliberately .txm-clock-*
   (not .clock-*) — see the .txm-panel comment for why this codebase keeps
   the pre-existing Game/Turn/Real Time clock and this new Tournament
   Clock visually and structurally distinct. Compact, professional, large
   monospaced digits, restrained low-reserve warning colour, no
   unnecessary animation, responsive down to narrow mobile widths. */
.txm-clock-card {
  margin-top: 8px;
  padding: 8px 10px 10px;
  border: 1px solid #ffd700;
  border-radius: 8px;
  background: rgba(255,215,0,0.04);
}
.txm-clock-header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 6px;
  margin-bottom: 6px;
  flex-wrap: wrap;
}
.txm-clock-title {
  font-size: 12px;
  font-weight: bold;
  color: #ffd700;
  letter-spacing: 0.5px;
  white-space: nowrap;
}
.txm-clock-preset-label {
  font-size: 10px;
  color: #a29bfe;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.txm-clock-settings-row {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  margin-bottom: 6px;
  flex-wrap: wrap;
}
.txm-clock-settings-label {
  color: #a29bfe;
  font-weight: bold;
  white-space: nowrap;
}
.txm-clock-settings-row select {
  background: #10162a;
  border: 1px solid #ffd700;
  color: #f2f2f2;
  border-radius: 5px;
  padding: 3px 6px;
  font-size: 11px;
  font-family: inherit;
  cursor: pointer;
}
.txm-clock-settings-row select:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* v3.7.8 Goal 4 — ALL-AI Tournament playback speed control */
.txm-clock-speed-row {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  margin: 2px 0 8px;
  flex-wrap: wrap;
}
.txm-clock-speed-btns {
  display: inline-flex;
  gap: 4px;
}
.txm-speed-btn {
  min-width: 34px;
  padding: 3px 8px;
  font-size: 11px;
  font-weight: bold;
  font-family: inherit;
  border-radius: 5px;
  border: 1px solid var(--tx-gold-dim, #8a6d2f);
  background: #10162a;
  color: #cdd3e6;
  cursor: pointer;
}
.txm-speed-btn.txm-speed-active {
  border-color: var(--tx-gold, #d8b46a);
  color: #1a1204;
  background: linear-gradient(180deg, #ffe9a8, var(--tx-gold, #d8b46a));
}
.txm-speed-btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}
.txm-clock-speed-note {
  color: #8b93a7;
  font-style: italic;
}
/* v3.7.10 Task 2 — scroll auto-pause spectator option */
.txm-clock-scrollpause-label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  color: #cdd3e6;
  cursor: pointer;
}
.txm-clock-scrollpause-label input {
  width: 15px;
  height: 15px;
  accent-color: var(--tx-gold, #d8b46a);
  cursor: pointer;
}
@media (pointer: coarse) {
  .txm-clock-scrollpause-label input { width: 20px; height: 20px; }
}
@media (pointer: coarse) {
  .txm-speed-btn { min-width: 40px; padding: 6px 10px; font-size: 12px; }
}
.txm-clock-status-banner {
  text-align: center;
  padding: 5px 6px;
  margin-bottom: 6px;
  border-radius: 6px;
  font-size: 11px;
  font-weight: bold;
  letter-spacing: 0.3px;
}
.txm-clock-status-paused {
  background: rgba(162,129,254,0.12);
  border: 1px solid #a29bfe;
  color: #a29bfe;
}
.txm-clock-status-expired {
  background: rgba(255,118,117,0.12);
  border: 1px solid #ff7675;
  color: #ff7675;
}
.txm-clock-rows {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-bottom: 8px;
}
.txm-clock-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  padding: 5px 8px;
  border-radius: 6px;
  background: rgba(255,255,255,0.04);
  border: 1px solid var(--tx-line);
}
.txm-clock-row.txm-blue  .txm-clock-name { color: var(--tx-blue-glow, #4aa8ff); }
.txm-clock-row.txm-red   .txm-clock-name { color: #ff7675; }
.txm-clock-row.txm-green .txm-clock-name { color: #55efc4; }
.txm-clock-name {
  font-size: 11px;
  font-weight: bold;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  flex: 1;
}
/* v3.7.10 Task 3 — active player's Simple Delay countdown. Compact, but
   clearly its own thing next to the (unchanged) reserve time. */
.txm-clock-delay {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 7px;
  border-radius: 999px;
  background: rgba(255,215,0,0.14);
  border: 1px solid rgba(255,215,0,0.5);
  white-space: nowrap;
}
.txm-clock-delay-label {
  font-size: 9px;
  font-weight: bold;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: #ffd27a;
}
.txm-clock-delay-num {
  font-family: 'Courier New', Consolas, monospace;
  font-size: 12px;
  font-weight: bold;
  color: #ffd700;
  min-width: 34px;
  text-align: right;
}
.txm-clock-delay-bar {
  display: inline-block;
  width: 42px;
  height: 4px;
  border-radius: 2px;
  background: rgba(255,255,255,0.15);
  overflow: hidden;
}
.txm-clock-delay-bar-fill {
  display: block;
  height: 100%;
  background: #ffd700;
  transition: width 0.12s linear;
}
.txm-clock-delay.txm-clock-delay-paused {
  opacity: 0.55;
}
.txm-clock-delay.txm-clock-delay-paused .txm-clock-delay-bar-fill {
  transition: none;
}
@media (pointer: coarse) {
  .txm-clock-delay-num { font-size: 13px; }
  .txm-clock-delay-bar { width: 52px; height: 5px; }
}
.txm-clock-time {
  font-family: 'Courier New', Consolas, monospace;
  font-size: 18px;
  font-weight: bold;
  color: #f2f2f2;
  letter-spacing: 0.5px;
  white-space: nowrap;
  min-width: 64px;
  text-align: right;
}
.txm-clock-row.txm-clock-active {
  border-color: #ffd700;
  background: rgba(255,215,0,0.08);
}
.txm-clock-row.txm-clock-active .txm-clock-time {
  color: #ffd700;
}
.txm-clock-row.txm-clock-warning .txm-clock-time {
  color: #fdcb6e;
}
.txm-clock-row.txm-clock-critical .txm-clock-time {
  color: #ff7675;
}
.txm-clock-row.txm-clock-expired-row {
  border-color: #ff7675;
  background: rgba(255,118,117,0.10);
  opacity: 0.85;
}
.txm-clock-controls {
  display: flex;
  gap: 6px;
  margin-bottom: 6px;
}
.txm-clock-btn {
  flex: 1;
  padding: 6px 8px;
  background: transparent;
  border: 1px solid #ffd700;
  color: #ffd700;
  border-radius: 6px;
  font-size: 12px;
  font-weight: bold;
  cursor: pointer;
  transition: all 0.15s;
}
.txm-clock-btn:hover {
  background: #ffd700;
  color: #0d0d1a;
}
.txm-clock-btn-resume {
  border-color: #55efc4;
  color: #55efc4;
}
.txm-clock-btn-resume:hover {
  background: #55efc4;
  color: #0d0d1a;
}
.txm-clock-stats-toggle {
  font-size: 10px;
  color: #a29bfe;
  cursor: pointer;
  user-select: none;
  text-align: center;
  padding: 2px 0;
}
.txm-clock-stats-toggle:hover {
  color: #ffd700;
}
.txm-clock-stats {
  margin-top: 4px;
  padding-top: 4px;
  border-top: 1px solid var(--tx-line);
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.txm-clock-stat-row {
  display: flex;
  flex-direction: column;
  font-size: 9px;
  color: #999;
}
.txm-clock-stat-name {
  font-weight: bold;
  font-size: 10px;
}
.txm-clock-stat-name.txm-blue  { color: var(--tx-blue-glow, #4aa8ff); }
.txm-clock-stat-name.txm-red   { color: #ff7675; }
.txm-clock-stat-name.txm-green { color: #55efc4; }
.txm-clock-stat-detail {
  color: #999;
}
@media (max-width: 480px) {
  .txm-clock-settings-row select { flex: 1; min-width: 0; }
  .txm-clock-time { font-size: 16px; min-width: 56px; }
}
/* ── Click-zone edit mode ── */
/* Draggable handle shown per zone in edit mode */
.czl-drag-handle {
  position: absolute;
  z-index: 72;
  width: 18px; height: 18px;
  background: #fdcb6e;
  border: 2px solid #fff;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  cursor: crosshair;
  pointer-events: auto;
  user-select: none;
}
.czl-drag-handle:hover { background: #ffeaa7; outline: 2px solid #fdcb6e; outline-offset: 3px; }
.czl-drag-label {
  position: absolute;
  z-index: 73;
  font-size: 10px;
  font-weight: bold;
  font-family: 'Courier New', monospace;
  color: #fdcb6e;
  background: rgba(0,0,0,0.78);
  padding: 1px 4px;
  border-radius: 3px;
  white-space: nowrap;
  pointer-events: none;
}
/* Click-zone edit hint bar */
#czl-edit-hint {
  display: none;
  max-width: 900px; width: 100%;
  margin-top: 6px;
  padding: 8px 14px;
  background: rgba(253,203,110,0.10);
  border: 1px solid #fdcb6e;
  border-radius: 6px;
  color: #fdcb6e;
  font-size: 12px;
}
#czl-edit-hint.active { display: block; }
/* Click-zone export panel */
.czl-export-panel {
  max-width: 900px; width: 100%;
  margin-top: 8px;
  background: var(--tx-bg-panel-2);
  border: 1px solid #fdcb6e;
  border-radius: 6px;
  padding: 10px 14px;
  display: none;
}
.czl-export-panel.open { display: block; }
.czl-export-panel textarea {
  width: 100%;
  min-height: 120px;
  background: #070710;
  border: 1px solid #444;
  color: #fdcb6e;
  font-family: 'Courier New', monospace;
  font-size: 11px;
  border-radius: 4px;
  padding: 6px;
  resize: vertical;
}
/* Board outline in czl-edit mode */
body.czl-edit-mode #board-wrap {
  outline: 3px solid #fdcb6e;
  outline-offset: 3px;
  border-radius: 8px;
}
/* Board highlight in setup mode */
body.manual-setup-mode #board-wrap {
  outline: 3px solid #fdcb6e;
  outline-offset: 3px;
  border-radius: 8px;
}
/* Setup-mode zone hover */
body.manual-setup-mode .pt-zone {
  cursor: crosshair !important;
}
/* ── Player Types panel (v149) ── */
.player-types-section {
  border: 1px solid var(--tx-line);
  border-radius: 6px;
  padding: 8px 10px;
  background: rgba(162,155,254,0.04);
}
.player-type-row {
  display: grid;
  grid-template-columns: 44px 1fr 1fr;
  align-items: center;
  gap: 6px;
  margin: 5px 0;
}
/* v246: Player Names — display-only text input, styled to match
   .player-type-select so the row reads as one control group. */
.player-name-input {
  background: #10162a; border: 1px solid #555; color: #f2f2f2;
  border-radius: 4px; padding: 4px 6px; font-size: 11px;
  font-family: inherit; width: 100%; box-sizing: border-box;
}
.player-name-input::placeholder { color: #555; font-style: italic; }
.player-name-input:focus {
  outline: none;
  border-color: #ffd700;
  box-shadow: 0 0 6px rgba(255,215,0,0.35);
}
.player-type-label { font-size: 11px; font-weight: bold; font-family: 'Courier New', monospace; }
.player-type-label.blue  { color: #74b9ff; }
.player-type-label.green { color: #55efc4; }
.player-type-label.red   { color: #ff7675; }
.player-type-select {
  background: #10162a; border: 1px solid #ffd700; color: #f2f2f2;
  border-radius: 4px; padding: 4px 6px; font-size: 11px;
  font-family: inherit; cursor: pointer; width: 100%;
}
.player-type-select option {
  background: #10162a;
  color: #f2f2f2;
}
.player-type-select:focus {
  outline: none;
  border-color: #ffd700;
  box-shadow: 0 0 6px rgba(255,215,0,0.35);
}
.player-types-status {
  margin-top: 7px; padding: 4px 6px; background: #070710;
  border-radius: 4px; font-size: 10px; font-family: 'Courier New', monospace;
  color: #636e72; line-height: 1.6;
}
/* ── Board rotation shell (v150) ── */
#board-rotation-shell {
  width: 100%;
  transform-origin: center center;
  transition: transform 0.35s ease;
  /* v234: Blue is at 0° in the raw board art (see PLAYER_ROTATIONS in
     the JS), so Blue-upright is simply the unrotated default — no
     transform needed here to avoid a load flash. */
}

/* ── Board stage / matte (v167; v185 gold-inlay; v186 raised plinth) ──
   Fixed, non-rotating dark stage that sits behind the rotating board.
   Prevents the transparent/white-label board art from visually
   fighting the page background while it rotates. v186 deepens the
   shadow recipe into a "raised plinth" read — a tight dark contact
   shadow at the base plus a wide soft drop shadow simulate the stage
   sitting up off the page, and a brighter top rim-light suggests a
   bevelled edge catching light. Purely shadow/border; sizing,
   overflow, and positioning are unchanged from v167. */
#board-stage {
  position: relative;
  z-index: 2;
  /* v188 safe layering hotfix: z-index bumped from 1 to 2 so
     board-stage sits above its siblings (z-index:1) as well as the
     plinth (z-index:0). Width/height/overflow/sizing unchanged. */
  width: min(72vw, 840px);
  height: min(72vw, 840px);
  max-width: 840px;
  max-height: 840px;
  margin: 0 auto;
  background: radial-gradient(circle at center,
    rgba(20,24,42,0.95) 0%,
    rgba(5,8,18,0.98) 68%,
    rgba(0,0,0,1) 100%);
  border: 1px solid var(--tx-gold-dim);
  border-radius: 14px;
  overflow: hidden;
  box-shadow:
    0 0 0 1px rgba(0,0,0,0.7),
    0 2px 0 rgba(216,180,106,0.18),
    0 22px 50px rgba(0,0,0,0.65),
    0 8px 18px rgba(0,0,0,0.5),
    0 0 32px rgba(216,180,106,0.08),
    inset 0 1px 0 rgba(216,180,106,0.30),
    inset 0 0 2px rgba(216,180,106,0.25),
    inset 0 0 44px rgba(0,0,0,0.88);
}

/* ── Board viewport clipping (v163) ──
   Contains the rotating shell inside the stage so rotation never
   spills past the matte edge. #board-wrap remains the unrotated
   coordinate reference; only this outer structure is added. */
#board-viewport {
  position: absolute;
  inset: 0;
  overflow: hidden;
}
#board-rotation-center {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 100%;
  transform: translate(-50%, -50%);
}

/* ── v243 Fix 2 / v3.7.2 tablet fix Task 1: static centre hit-zone ──
   Formerly the visible "TrigammonX / Backgammon for Three" label above
   the board — removed as a duplicate of the real page header (.tx-header).
   What remains is a transparent, text-free safe hit-zone, a direct child
   of #board-stage (a SIBLING of #board-viewport, never a descendant of
   #board-rotation-shell/#board-rotation-center) so it never rotates with
   the board and is never tied to any board/CLICK_POINTS/CHECKER_ANCHORS
   coordinate. It is a COMPACT box centred over the non-playing centre/
   logo area only — not the full-width top band it used to be. z-index 6
   keeps it BELOW .pt-zone (10) and .checker (20), and pointer-events are
   off for every mouse/desktop pointer, so it can never intercept a
   checker or point click. On a coarse (touch) pointer only it becomes a
   quick-Pause target (handleBoardBrandingTap(), which further restricts
   activation to genuine live play). */
#board-static-branding {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 22%;
  height: 16%;
  transform: translate(-50%, -50%);
  z-index: 6;
  pointer-events: none;
  user-select: none;
}

@media (pointer: coarse) {
  #board-static-branding {
    pointer-events: auto;
    cursor: pointer;
  }
  #board-static-branding:active {
    background: rgba(255,255,255,0.04);
  }
}

/* ── Admin View buttons (v150) ── */
.admin-view-btns {
  display: flex;
  flex-direction: column;
  gap: 5px;
}
.admin-view-btns button {
  width: 100%;
  text-align: left;
  padding: 6px 10px;
  font-size: 11px;
}
.btn-view-active {
  background: #a29bfe !important;
  color: #0d0d1a !important;
}
.btn-view-blue.btn-view-active  { background: #74b9ff !important; }
.btn-view-green.btn-view-active { background: #55efc4 !important; }
.btn-view-red.btn-view-active   { background: #ff7675 !important; }
.btn-view-auto.btn-view-active  { background: #ffd700 !important; }
/* ── Board view status line (v154) ── */
#board-view-status {
  margin-top: 6px;
  padding: 4px 8px;
  background: #070710;
  border-radius: 4px;
  font-size: 10px;
  font-family: 'Courier New', monospace;
  color: #a29bfe;
  border: 1px solid var(--tx-line);
  line-height: 1.5;
}
/* ── AI play note (v157) ── */
.ai-play-note {
  margin-top: 7px;
  padding: 6px 8px;
  background: #070710;
  border: 1px solid var(--tx-line);
  border-radius: 5px;
  font-size: 11px;
  font-family: 'Courier New', monospace;
  color: #ffd700;
  line-height: 1.5;
  min-height: 48px;
}
/* ── Clock panel — now centered above the board only (v176) ── */
.clock-panel {
  display: grid;
  grid-template-columns: repeat(3, minmax(160px, 1fr));
  gap: 14px;
  justify-content: center;
  width: min(100%, 620px);
}
.clock-card {
  width: 100%;
  background:
    linear-gradient(180deg, rgba(216,180,106,0.06), transparent 50%),
    var(--tx-bg-panel-2);
  border: 1px solid var(--tx-line);
  border-top-color: rgba(255,255,255,0.08);
  border-radius: 12px;
  padding: 10px 12px 12px;
  text-align: center;
  box-shadow: var(--tx-raised);
}
.clock-title {
  color: var(--tx-text);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 1.2px;
  margin-bottom: 8px;
  text-transform: uppercase;
}
.clock-face {
  width: 128px;
  height: 128px;
  margin: 0 auto;
  border-radius: 50%;
  border: 3px solid var(--tx-gold);
  background:
    radial-gradient(circle at 38% 32%, #1c2032 0%, #11141f 45%, #07080f 78%);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  position: relative;
  /* v186: deeper recessed-dial look — the wide outer glow now reads as
     a raised bezel catching light, while the inset shadow simulates a
     genuinely sunken clock face rather than a flat circle. */
  box-shadow:
    0 0 0 1px rgba(0,0,0,0.5),
    0 3px 8px rgba(0,0,0,0.5),
    0 0 18px var(--tx-gold-dim),
    inset 0 3px 10px rgba(0,0,0,0.85),
    inset 0 -2px 4px rgba(216,180,106,0.12);
}
.clock-face::before {
  content: '';
  position: absolute;
  inset: 9px;
  border-radius: 50%;
  border: 1px dashed rgba(216,180,106,0.22);
}
.clock-main {
  color: var(--tx-text);
  font-family: 'Courier New', monospace;
  font-size: 20px;
  font-weight: 900;
  line-height: 1.1;
  z-index: 1;
  text-shadow: 0 0 6px rgba(255,255,255,0.18);
}
.clock-sub {
  color: var(--tx-gold);
  font-size: 10px;
  font-family: 'Courier New', monospace;
  margin-top: 6px;
  z-index: 1;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}
@media (max-width: 760px) {
  .clock-card {
    width: 220px;
  }
}
/* ── Game stats panel (v166) ── */
.stats-panel {
  background: rgba(4, 6, 14, 0.85);
  border: 1px solid var(--tx-line);
  border-radius: var(--tx-radius-sm);
  padding: 9px;
  font-size: 11px;
  font-family: 'Courier New', monospace;
  line-height: 1.6;
  min-height: 170px;
  /* v186: a sunken "display screen" look — these data panels sit
     recessed into their raised parent console rather than also being
     raised, which keeps the depth language readable as layered. */
  box-shadow: inset 0 2px 6px rgba(0,0,0,0.5), inset 0 -1px 0 rgba(255,255,255,0.03);
}
.stats-row {
  display: grid;
  grid-template-columns: 48px 1fr;
  gap: 6px;
  margin: 3px 0;
}
.stats-name.blue  { color:#74b9ff; }
.stats-name.green { color:#55efc4; }
.stats-name.red   { color:#ff7675; }
.stats-values {
  color: var(--tx-text-dim);
}
.stats-player-block {
  border-bottom: 1px solid var(--tx-line-soft);
  padding: 4px 0 6px;
  margin-bottom: 4px;
}
.stats-player-block:last-child {
  border-bottom: none;
  margin-bottom: 0;
}

/* ── v245: Live Game Stats scoreboard table (replaces the old stacked
   per-player text blocks — same #stats-panel/.stats-panel container). ── */
.lst-highlights {
  font-size: 10px;
  color: var(--tx-text-dim);
  margin-bottom: 6px;
  letter-spacing: 0.2px;
}
.lst-table {
  display: flex;
  flex-direction: column;
}
.lst-row {
  display: grid;
  grid-template-columns: 62px repeat(3, 1fr);
  gap: 4px;
  align-items: center;
  padding: 2px 0;
  border-bottom: 1px solid rgba(255,255,255,0.04);
}
.lst-row:last-child { border-bottom: none; }
.lst-header-row {
  border-bottom: 1px solid var(--tx-line-soft);
  padding-bottom: 4px;
  margin-bottom: 2px;
}
.lst-label {
  color: var(--tx-text-faint);
  font-size: 10px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.lst-val {
  text-align: right;
  color: var(--tx-text);
  font-size: 11px;
  white-space: nowrap;
}
.lst-header-row .lst-val {
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.6px;
  font-weight: bold;
  text-align: right;
  overflow: hidden;
  text-overflow: ellipsis;
}
.lst-name-blue  { color: #74b9ff; }
.lst-name-red   { color: #ff7675; }
.lst-name-green { color: #55efc4; }
.lst-triples-row {
  color: var(--tx-text-faint);
  font-size: 10px;
}
.lst-triples-row .lst-val { font-size: 10px; color: var(--tx-text-faint); }

/* ── Borne-off display (v169 — checker trays) ── */
.borne-off-display {
  background: rgba(4, 6, 14, 0.85);
  border: 1px solid var(--tx-line);
  border-radius: var(--tx-radius-sm);
  padding: 8px;
  font-size: 11px;
  font-family: 'Courier New', monospace;
  line-height: 1.5;
}
.borne-player-box {
  margin-bottom: 9px;
  padding: 8px 9px;
  border: 1px solid var(--tx-line-soft);
  border-top-color: rgba(255,255,255,0.06);
  border-radius: var(--tx-radius-sm);
  background:
    linear-gradient(180deg, rgba(255,255,255,0.03), transparent 60%),
    rgba(0,0,0,0.30);
  box-shadow:
    0 3px 8px rgba(0,0,0,0.35),
    inset 0 1px 0 rgba(255,255,255,0.04);
}
.borne-player-box:last-child { margin-bottom: 0; }
.borne-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 6px;
}
.borne-name.blue  { color:#74b9ff; }
.borne-name.green { color:#55efc4; }
.borne-name.red   { color:#ff7675; }
.borne-count {
  color: var(--tx-text-dim);
  font-size: 11px;
}
.borne-checker-tray {
  min-height: 42px;
  border: 1px solid var(--tx-gold-dim);
  border-radius: var(--tx-radius-sm);
  background:
    linear-gradient(180deg, rgba(255,255,255,0.03), rgba(0,0,0,0.25));
  padding: 6px;
  display: flex;
  flex-wrap: wrap;
  gap: 3px;
  align-content: flex-start;
  /* v186: a genuinely sunken display-case well — wider inset shadow at
     the top, a thin highlight at the base lip, so checkers sitting in
     it read as physically resting in a recess. */
  box-shadow:
    inset 0 4px 8px rgba(0,0,0,0.6),
    inset 0 -1px 0 rgba(216,180,106,0.15);
}
.borne-mini-checker {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 1px solid rgba(255,255,255,0.45);
  box-shadow:
    inset 0 -2px 2px rgba(0,0,0,0.3),
    inset 0 1px 2px rgba(255,255,255,0.5),
    0 1px 2px rgba(0,0,0,0.6);
}
.borne-mini-checker.blue {
  background: radial-gradient(circle at 35% 30%, #8fc6ff, #2980b9 75%);
}
.borne-mini-checker.green {
  background: radial-gradient(circle at 35% 30%, #82f5d9, #00b894 75%);
}
.borne-mini-checker.red {
  background: radial-gradient(circle at 35% 30%, #ff9b9a, #c0392b 75%);
}

/* v3.7.2 Task 8: proportional fill bar — a compact, board-design-
   independent way to read borne-off progress at a glance on tablet,
   without adding vertical space (sits inside the same box, below the
   existing checker tray; never replaces the exact count/tray above). */
.borne-progress-track {
  margin-top: 6px;
  height: 5px;
  border-radius: 3px;
  background: rgba(0,0,0,0.4);
  overflow: hidden;
  border: 1px solid rgba(255,255,255,0.06);
}
.borne-progress-fill {
  height: 100%;
  border-radius: 3px;
  transition: width 0.25s ease;
}
.borne-progress-fill.blue  { background: linear-gradient(90deg, #4a90d9, #8fc6ff); }
.borne-progress-fill.green { background: linear-gradient(90deg, #00b894, #82f5d9); }
.borne-progress-fill.red   { background: linear-gradient(90deg, #c0392b, #ff9b9a); }

/* ── v3.7.2 final UI pass — horizontal BORNE OFF / BAR-CAPTURED strips ──
   One shared compact tray look. #borneoff-strip sits in the black area
   directly ABOVE #board-stage; #bar-strip directly BELOW it. Both are
   plain DOM in .board-panel — board-design-independent, no board PNG
   involvement, and the wooden playing surface carries no tray of its own.
   Three side-by-side Blue / Red / Green trays each (grid), with
   overlapping mini-checker chips + a count. The Bar trays are real
   tap/keyboard targets for legal Bar re-entry (see renderBarPieces()). */
.board-tray-strip {
  width: 100%;
  box-sizing: border-box;
  background:
    linear-gradient(180deg, rgba(216,180,106,0.05), transparent 45%),
    var(--tx-bg-panel);
  border: 1px solid var(--tx-line);
  border-top-color: rgba(255,255,255,0.07);
  border-radius: var(--tx-radius-sm);
  padding: 6px 10px 8px;
  box-shadow: var(--tx-raised);
}
.board-tray-strip-title {
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 1.5px;
  color: var(--tx-gold);
  margin-bottom: 5px;
}
.board-tray-row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
}
.board-tray {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  min-height: 30px;
  padding: 5px 8px;
  border: 1px solid var(--tx-line-soft);
  border-top-color: rgba(255,255,255,0.06);
  border-radius: var(--tx-radius-sm);
  background:
    linear-gradient(180deg, rgba(255,255,255,0.03), transparent 60%),
    rgba(0,0,0,0.30);
  box-shadow: inset 0 2px 5px rgba(0,0,0,0.4);
}
.board-tray-name {
  flex: 0 0 auto;
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}
.board-tray-name.blue  { color: #74b9ff; }
.board-tray-name.red   { color: #ff7675; }
.board-tray-name.green { color: #55efc4; }
.board-tray-icons {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  min-width: 0;
  overflow: hidden;
  padding-left: 6px;
}
.board-tray-chip {
  flex: 0 0 auto;
  width: 13px;
  height: 13px;
  border-radius: 50%;
  border: 1px solid rgba(255,255,255,0.45);
  margin-left: -5px;                 /* overlap */
  box-shadow:
    inset 0 -2px 2px rgba(0,0,0,0.3),
    inset 0 1px 2px rgba(255,255,255,0.5),
    0 1px 2px rgba(0,0,0,0.6);
}
.board-tray-chip:first-child { margin-left: 0; }
.board-tray-chip.blue  { background: radial-gradient(circle at 35% 30%, #8fc6ff, #2980b9 75%); }
.board-tray-chip.red   { background: radial-gradient(circle at 35% 30%, #ff9b9a, #c0392b 75%); }
.board-tray-chip.green { background: radial-gradient(circle at 35% 30%, #82f5d9, #00b894 75%); }
.board-tray-more {
  flex: 0 0 auto;
  margin-left: 4px;
  font-size: 9px;
  font-weight: 700;
  color: var(--tx-text-dim);
}
.board-tray-empty { font-size: 10px; color: #566; }
.board-tray-count {
  flex: 0 0 auto;
  font-size: 11px;
  font-family: 'Courier New', monospace;
  color: var(--tx-text-dim);
}
/* Borne-off tray gets a thin proportional progress bar (kept from the old
   Task 8 fill — same at-a-glance read, no extra vertical bulk). */
.board-tray-progress {
  flex: 0 0 34px;
  height: 4px;
  border-radius: 3px;
  background: rgba(0,0,0,0.45);
  border: 1px solid rgba(255,255,255,0.06);
  overflow: hidden;
}
.board-tray-progress-fill { display: block; height: 100%; border-radius: 3px; transition: width 0.25s ease; }
.board-tray-progress-fill.blue  { background: linear-gradient(90deg, #4a90d9, #8fc6ff); }
.board-tray-progress-fill.green { background: linear-gradient(90deg, #00b894, #82f5d9); }
.board-tray-progress-fill.red   { background: linear-gradient(90deg, #c0392b, #ff9b9a); }

/* Bar / Captured trays — interactive states for legal Bar re-entry. */
#bar-trays .board-tray.occupied {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.05), transparent 60%),
    rgba(0,0,0,0.42);
}
#bar-trays .board-tray.actionable { cursor: pointer; }
#bar-trays .board-tray.actionable:hover { border-color: var(--tx-gold-dim); }
#bar-trays .board-tray.selected {
  border-color: var(--tx-gold);
  box-shadow: 0 0 0 1px var(--tx-gold-dim), 0 0 10px rgba(216,180,106,0.35);
}
#bar-trays .board-tray:focus-visible {
  outline: 2px solid var(--tx-gold);
  outline-offset: 2px;
}
@media (pointer: coarse) {
  .board-tray { min-height: 40px; }
}
@media (max-width: 520px) {
  .board-tray-row { grid-template-columns: 1fr; gap: 5px; }
  .board-tray-progress { flex-basis: 28px; }
}

/* ── v4.3 (Module A) — BORNE OFF / BAR-CAPTURED strips OVERLAID INSIDE the
   board frame ────────────────────────────────────────────────────────────
   #borneoff-strip and #bar-strip are now absolutely-positioned children of
   #board-stage, sitting in the empty dark band the board art already leaves
   above and below the playable triangle field — measured at ~13.5–15 % of
   the stage height at every breakpoint AND every 0°/120°/240° board
   rotation, so a capped-height strip can never reach a playable checker.

   The board layer is NOT touched: #board-viewport / #board-rotation-* /
   .board-wrap / #board-img keep their exact size and position, and the
   CLICK_POINTS / CHECKER_ANCHORS coordinate system is untouched — this rule
   only positions two overlay panels in space the board art was already
   leaving blank.

   pointer-events: none on the strip shell so a Human drag / loupe passing
   over the band is never intercepted; only the live tray rows take pointer
   events, so Bar re-entry taps (onBarCheckerClick) work exactly as before.
   z-index 8 keeps the strips above the board image but far below the Human
   loupe / AI hand / travelling-finger (position:fixed on <body>, z 1990–
   2000), the winner banner (5000), the certificate (6000) and every other
   overlay. */
#board-stage > .board-tray-strip-inframe {
  position: absolute;
  left: 6px;
  right: 6px;
  z-index: 8;
  height: clamp(22px, 9%, 42px);
  min-height: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 2px;
  margin: 0;
  padding: 3px 8px;
  border: 1px solid rgba(216,180,106,0.22);
  border-radius: 9px;
  background:
    linear-gradient(180deg, rgba(216,180,106,0.07), rgba(4,6,14,0.34) 62%),
    rgba(4,6,14,0.60);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.06),
    0 5px 14px rgba(0,0,0,0.45);
  pointer-events: none;
}
#board-stage > #borneoff-strip { top: 6px; }
#board-stage > #bar-strip      { bottom: 6px; }

/* live tray rows stay interactive (Bar re-entry) */
#board-stage > .board-tray-strip-inframe .board-tray-row,
#board-stage > .board-tray-strip-inframe .board-tray {
  pointer-events: auto;
}

/* compact the trays to three-across in the short in-frame strip, at every
   width (override the ≤520px single-column stack + the coarse-pointer
   40px min-height, which only apply to the OLD under-board strips) */
#board-stage > .board-tray-strip-inframe .board-tray-strip-title {
  margin: 0 0 1px;
  font-size: 8px;
  letter-spacing: 1px;
  line-height: 1;
  opacity: 0.85;
}
#board-stage > .board-tray-strip-inframe .board-tray-row {
  grid-template-columns: repeat(3, 1fr);
  gap: 6px;
  align-items: stretch;
}
#board-stage > .board-tray-strip-inframe .board-tray {
  min-height: 0;
  padding: 2px 7px;
  gap: 4px;
  background: rgba(0,0,0,0.34);
  box-shadow: inset 0 1px 3px rgba(0,0,0,0.4);
}
#board-stage > .board-tray-strip-inframe .board-tray-name  { font-size: 9px; }
#board-stage > .board-tray-strip-inframe .board-tray-count { font-size: 10px; }
#board-stage > .board-tray-strip-inframe .board-tray-progress { display: none; }

/* iPad-portrait and narrower / short viewports: drop the strip title (the
   three coloured trays read for themselves) and tighten the height so the
   in-frame strips keep a comfortable gap to the nearest checker as the
   whole board scales down. */
@media (max-width: 820px), (max-height: 860px) {
  #board-stage > .board-tray-strip-inframe .board-tray-strip-title { display: none; }
  #board-stage > .board-tray-strip-inframe { height: clamp(18px, 7.5%, 32px); padding: 2px 6px; }
  #board-stage > .board-tray-strip-inframe .board-tray { padding: 1px 5px; }
}
/* phones: tighter still */
@media (max-width: 500px) {
  #board-stage > .board-tray-strip-inframe { height: clamp(16px, 7%, 26px); left: 4px; right: 4px; }
  #board-stage > #borneoff-strip { top: 4px; }
  #board-stage > #bar-strip { bottom: 4px; }
  #board-stage > .board-tray-strip-inframe .board-tray-row { gap: 4px; }
  #board-stage > .board-tray-strip-inframe .board-tray-name  { font-size: 8px; }
  #board-stage > .board-tray-strip-inframe .board-tray-count { font-size: 9px; }
}

/* ── Game report panel (v169) ── */
.game-report-panel {
  background: rgba(4, 6, 14, 0.85);
  border: 1px solid var(--tx-line);
  border-radius: var(--tx-radius-sm);
  padding: 9px;
  font-size: 11px;
  font-family: 'Courier New', monospace;
  line-height: 1.55;
  color: var(--tx-text-dim);
  min-height: 120px;
  box-shadow: inset 0 2px 6px rgba(0,0,0,0.5), inset 0 -1px 0 rgba(255,255,255,0.03);
}
.game-report-panel .winner {
  color: var(--tx-gold);
  font-weight: bold;
}

/* ── Match / Balance Log panel (v179) ── */
/* ── Match Summary panel (v181) ── */
.match-summary-panel {
  background: rgba(4, 6, 14, 0.85);
  border: 1px solid var(--tx-line);
  border-radius: var(--tx-radius-sm);
  padding: 9px;
  font-size: 11px;
  font-family: 'Courier New', monospace;
  line-height: 1.55;
  color: var(--tx-text-dim);
  min-height: 130px;
  box-shadow: inset 0 2px 6px rgba(0,0,0,0.5), inset 0 -1px 0 rgba(255,255,255,0.03);
}
.match-summary-panel .summary-title {
  color: var(--tx-gold);
  font-weight: bold;
}
.match-summary-panel .summary-blue {
  color: #74b9ff;
}
.match-summary-panel .summary-green {
  color: #55efc4;
}
.match-summary-panel .summary-red {
  color: #ff7675;
}
.match-summary-panel .summary-small {
  color: var(--tx-text-faint);
  font-size: 10px;
}

