/* TrigammonX v2.2.0 — 03-components-features.css
 * Auto-extracted verbatim from TrigammonX-v2.1.9.html's single <style> block
 * as part of the v2.2.0 modularisation pass (components/features panels (modals, dialogs, feature cards)).
 * See README-ARCHITECTURE.md for exact cascade/load order.
 */
.match-log-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);
  max-height: 220px;
  min-height: 220px;
  overflow-y: auto;
  box-shadow: inset 0 2px 6px rgba(0,0,0,0.5), inset 0 -1px 0 rgba(255,255,255,0.03);
}
.match-log-panel .ml-winner {
  color: var(--tx-gold);
  font-weight: bold;
}

/* ── v246: Commentary controls + Table Talk panel ──────────────────── */
.commentary-controls {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;   /* v249: Narrator Voice row adds more controls than fit in one line on narrow panels */
}
.commentary-control-label {
  flex: 1 1 50%;
  font-size: 10px;
  color: var(--tx-text-faint);
  line-height: 1.6;
}
.commentary-control-label select {
  margin-top: 2px;
}
.commentary-pack-status {
  margin-top: 6px;
  font-size: 10px;
  color: var(--tx-text-dim);   /* v253 readability pass — was #636e72 */
  line-height: 1.4;
}
.commentary-pack-status.ok    { color: #55efc4; }
.commentary-pack-status.error { color: #fdcb6e; }

/* ── v249: Narrator Voice selector + tuning sliders ─────────────────── */
.voice-tuning-value {
  color: var(--tx-gold);
  font-weight: bold;
  margin-left: 4px;
}
.commentary-control-label input[type="range"].voice-tuning-slider {
  width: 100%;
  margin-top: 4px;
  accent-color: #ffd700;
  box-sizing: border-box;
}
.test-voice-btn {
  font-size: 11px;
  padding: 6px 10px;
  border-color: #55efc4;
  color: #55efc4;
}

/* ── v2.3.0: Voice Speed + Volume — Scotty MP3 commentary playback
   controls only (see playCommentaryAudioFile(), 07-commentary.js).
   Compact preset-button row + slider, styled consistently with the
   existing .ui-theme-btn/.ui-theme-selected pattern so it reads as part
   of the same control language rather than a new component. ── */
.voice-speed-btn-row {
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
  margin-top: 3px;
}
.voice-speed-btn {
  padding: 4px 7px;
  border: 1px solid var(--tx-line);
  border-radius: 6px;
  background: var(--tx-bg-panel-2);
  color: var(--tx-text-dim);
  font-size: 10px;
  font-family: inherit;
  cursor: pointer;
}
.voice-speed-btn:hover {
  border-color: var(--tx-gold-dim);
}
.voice-speed-btn.voice-speed-selected {
  border-color: var(--tx-gold-bright);
  box-shadow: 0 0 0 1px var(--tx-gold-dim);
  color: var(--tx-text);
  font-weight: 600;
}

/* ── v3.6.0: Background Music controls — cloned from .commentary-controls/
   .commentary-control-label above (own class names so this card can be
   restyled independently of Table Talk/Commentary later without risk). ── */
.music-controls {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
.music-controls:not(:last-child) {
  margin-bottom: 8px;
}
.music-control-label {
  flex: 1 1 50%;
  font-size: 10px;
  color: var(--tx-text-faint);
  line-height: 1.6;
}
.music-control-label select {
  margin-top: 2px;
}
.music-status {
  margin-top: 6px;
  font-size: 10px;
  color: var(--tx-text-dim);
  line-height: 1.4;
  min-height: 13px;
}

.table-talk-panel {
  background: rgba(4, 6, 14, 0.85);
  border: 1px solid var(--tx-line);
  border-radius: var(--tx-radius-sm);
  padding: 9px 10px;
  font-size: 11px;
  font-family: 'Segoe UI', sans-serif;
  line-height: 1.5;
  color: var(--tx-text-dim);
  min-height: 90px;
  max-height: 260px;
  overflow-y: auto;
  box-shadow: inset 0 2px 6px rgba(0,0,0,0.5), inset 0 -1px 0 rgba(255,255,255,0.03);
}
.table-talk-panel .tt-empty {
  color: var(--tx-text-faint);   /* v253 readability pass — was #555 */
  font-style: italic;
}
.tt-entry {
  padding: 5px 0;
  border-bottom: 1px solid rgba(255,255,255,0.05);
  opacity: 0.55;
  transform-origin: left center;
}
.tt-entry:last-child { border-bottom: none; }
/* Newest entry is visually strongest; older entries fade/shrink slightly
   as they recede — .tt-age-0 is newest, higher ages are older. */
.tt-entry.tt-age-0 { opacity: 1;   font-size: 12px; font-weight: 600; color: var(--tx-text); }
.tt-entry.tt-age-1 { opacity: 0.85; font-size: 11.5px; }
.tt-entry.tt-age-2 { opacity: 0.7; }
.tt-entry.tt-age-3 { opacity: 0.55; }
.tt-entry.tt-age-4 { opacity: 0.42; }
.tt-entry.tt-age-5 { opacity: 0.32; }
.tt-entry-player {
  font-weight: bold;
}
.tt-entry-player.blue  { color: #74b9ff; }
.tt-entry-player.green { color: #55efc4; }
.tt-entry-player.red   { color: #ff7675; }
/* Debug-only tag ("EventID | PhraseID | Tone") — only rendered at all
   when Commentary Debug is checked in Admin; never shown otherwise. */
.tt-debug-tag {
  display: block;
  margin-top: 2px;
  font-size: 9px;
  font-family: 'Courier New', monospace;
  color: #636e72;
  letter-spacing: 0.3px;
}

/* ── v247: commentary toast — always-visible, non-blocking notification.
   pointer-events:none top to bottom so it can NEVER intercept a
   checker/point click, no matter where it's positioned or animating. ── */
#commentary-toast-container {
  position: fixed;
  top: 14px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 9999;
  pointer-events: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  width: min(92vw, 440px);
}
.commentary-toast {
  pointer-events: none;
  width: 100%;
  box-sizing: border-box;
  background: rgba(8, 10, 20, 0.95);
  border: 1px solid rgba(255,255,255,0.08);
  border-left: 4px solid #a29bfe;
  border-radius: 10px;
  padding: 10px 14px;
  box-shadow: 0 10px 28px rgba(0,0,0,0.5), 0 1px 0 rgba(255,255,255,0.04) inset;
  font-family: 'Segoe UI', sans-serif;
  opacity: 0;
  transform: translateY(-16px) scale(0.97);
  transition: opacity 0.4s ease, transform 0.4s ease;
}
.commentary-toast.show {
  opacity: 1;
  transform: translateY(0) scale(1);
}
.commentary-toast.hide {
  opacity: 0;
  transform: translateY(-10px) scale(0.98);
}
.commentary-toast .ct-badge {
  font-size: 10px;
  letter-spacing: 0.8px;
  text-transform: uppercase;
  color: #a29bfe;
  font-weight: 700;
  margin-bottom: 3px;
}
.commentary-toast .ct-player {
  font-weight: 700;
  font-size: 12px;
  margin-bottom: 3px;
  color: var(--tx-text, #eee);
}
.commentary-toast .ct-player.blue  { color: #74b9ff; }
.commentary-toast .ct-player.green { color: #55efc4; }
.commentary-toast .ct-player.red   { color: #ff7675; }
.commentary-toast .ct-text {
  font-size: 13px;
  line-height: 1.45;
  color: #f1f1f1;
}
@media (max-width: 640px) {
  #commentary-toast-container { top: 8px; width: 94vw; }
  .commentary-toast { padding: 9px 12px; border-radius: 9px; }
  .commentary-toast .ct-text { font-size: 12.5px; }
}

/* ══════════════════════════════════════════════════════════════════
   v3.5.0 Part C — SMART "NEW VERSION AVAILABLE" NOTICE
   Fixed, non-blocking toast in the bottom-right corner — deliberately
   NOT a modal/backdrop, so it never intercepts board clicks and never
   interrupts a game in progress. Hidden (display:none) until JS adds
   .show, which only happens once latest-version.json reports a
   genuinely newer version than TRIGAMMONX_CURRENT_VERSION — see
   initUpdateChecker()/tgxCheckForUpdate() in 10-clocks-themes-ui.js and
   the #tgx-update-toast markup near the top of <body>. Styled to match
   the existing .commentary-toast/.beta-banner visual language (same
   panel/shadow treatment, gold accent) rather than inventing a new look.
   ══════════════════════════════════════════════════════════════════ */
.tgx-update-toast {
  display: none;
  position: fixed;
  right: 16px;
  bottom: 16px;
  z-index: 9500;
  width: min(92vw, 320px);
  box-sizing: border-box;
  background: rgba(8, 10, 20, 0.97);
  border: 1px solid var(--tx-gold-dim, rgba(216,180,106,0.35));
  border-left: 4px solid var(--tx-gold, #d8b46a);
  border-radius: 10px;
  padding: 14px 16px;
  box-shadow: 0 10px 28px rgba(0,0,0,0.5), 0 1px 0 rgba(255,255,255,0.04) inset;
  font-family: 'Segoe UI', sans-serif;
  opacity: 0;
  transform: translateY(12px) scale(0.98);
  transition: opacity 0.35s ease, transform 0.35s ease;
  pointer-events: none;
}
.tgx-update-toast.show {
  display: block;
  opacity: 1;
  transform: translateY(0) scale(1);
  pointer-events: auto;
}
.tgx-update-title {
  font-family: Georgia, 'Times New Roman', serif;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.5px;
  color: var(--tx-gold-bright, #f0cf8c);
  margin-bottom: 4px;
}
.tgx-update-text {
  font-size: 12px;
  line-height: 1.45;
  color: var(--tx-text, #eee);
  margin-bottom: 8px;
}
.tgx-update-versions {
  font-family: 'Courier New', monospace;
  font-size: 10.5px;
  line-height: 1.6;
  color: var(--tx-text-dim, #a6a9b8);
  margin-bottom: 8px;
}
.tgx-update-note {
  font-size: 10px;
  line-height: 1.4;
  color: var(--tx-text-faint, #7d8190);
  margin-bottom: 10px;
}
.tgx-update-btns {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
.tgx-update-btn {
  flex: 1 1 auto;
  font-family: 'Courier New', monospace;
  font-size: 11px;
  font-weight: bold;
  letter-spacing: 0.3px;
  padding: 7px 10px;
  border-radius: 6px;
  cursor: pointer;
  white-space: nowrap;
}
.tgx-update-btn-primary {
  border: 1px solid var(--tx-gold, #d8b46a);
  background: rgba(216,180,106,0.14);
  color: var(--tx-gold-bright, #f0cf8c);
}
.tgx-update-btn-primary:hover {
  background: rgba(216,180,106,0.24);
}
.tgx-update-btn-later {
  border: 1px solid rgba(255,255,255,0.12);
  background: transparent;
  color: var(--tx-text-dim, #a6a9b8);
}
.tgx-update-btn-later:hover {
  background: rgba(255,255,255,0.06);
}
@media (max-width: 480px) {
  .tgx-update-toast { right: 8px; bottom: 8px; left: 8px; width: auto; }
}

/* ── v245 (large-charts-rng pass): Dice RNG Test — isolated admin tool ── */
.rng-test-btns {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
.rng-test-btns button {
  flex: 1 1 160px;
  width: auto;
  text-align: center;
}
.rng-test-btns button:disabled {
  opacity: 0.45;
  cursor: default;
}
.rng-test-results {
  margin-top: 6px;
}
.rng-test-results:empty {
  display: none;
}
.rng-test-results .rtr-box {
  background: rgba(4, 6, 14, 0.85);
  border: 1px solid var(--tx-line);
  border-radius: var(--tx-radius-sm);
  padding: 9px 12px;
  font-size: 11px;
  font-family: 'Courier New', monospace;
  line-height: 1.6;
  color: var(--tx-text-dim);
  box-shadow: inset 0 2px 6px rgba(0,0,0,0.5), inset 0 -1px 0 rgba(255,255,255,0.03);
}
.rng-test-results .rtr-title {
  color: var(--tx-gold);
  font-weight: bold;
  margin-bottom: 6px;
}
.rng-test-results .rtr-face-row {
  display: grid;
  grid-template-columns: 60px 1fr 90px;
  gap: 8px;
  align-items: center;
  margin: 2px 0;
}
.rng-test-results .rtr-face-track {
  height: 10px;
  background: #1a1a2a;
  border-radius: 5px;
  overflow: hidden;
  border: 1px solid #333;
}
.rng-test-results .rtr-face-fill {
  height: 100%;
  background: linear-gradient(90deg, rgba(255,215,0,0.5), #ffd700);
  border-radius: 5px;
}
.rng-test-results .rtr-summary {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px dashed var(--tx-line);
}
.rng-test-results .rtr-verdict.ok   { color: #55efc4; font-weight: bold; }
.rng-test-results .rtr-verdict.warn { color: #fdcb6e; font-weight: bold; }
.match-log-panel .ml-small {
  color: var(--tx-text-faint);
  font-size: 10px;
}

/* ════════════════════════════════════════════════════════════════════
   v187 — 3D ANIMATED DICE (merged from trigammonx-dice-lab-v1.html)
   ════════════════════════════════════════════════════════════════════
   This block is the dice-lab's reusable CSS, copied in essentially
   unchanged (classes kept under the "dice-lab-" prefix exactly as in
   the source file so it never collides with the existing flat
   "die-chip" classes still used for dice-exp-row). Only additions here
   are the --die-size default tuned to fit the compact under-board
   panel, and the player-colour theming layer at the end (dice-owner-*).

   Nothing about the cube geometry, face rotation math, or pip layout
   was changed from the dice lab — see FACE_ROTATIONS / PIP_LAYOUTS in
   the script below for the JS half of this component.

   One thing the dice lab had that needed adding here: the dice lab set
   `perspective` on its outer `.dice-stage` demo container so the cubes'
   3D transforms render with actual depth/foreshortening rather than
   flatly. TrigammonX has no equivalent wrapper around #dice-raw-row, so
   perspective is set directly on it below — without this, the dice
   would still rotate to the correct face but the tumble would look
   flat/orthographic instead of genuinely three-dimensional. */

#dice-raw-row {
  perspective: 480px;
}

:root {
  /* v187: sized for the compact under-board dice strip — smaller than
     the dice lab's 64px demo default so 2-3 dice sit comfortably next
     to Current Turn / Bar / Pips without dominating that row. */
  --die-size: 48px;
}

.dice-lab-die {
  width: var(--die-size);
  height: var(--die-size);
  position: relative;
  /* Soft contact + ambient shadow — a physical die resting on the table. */
  filter: drop-shadow(0 10px 10px rgba(0,0,0,0.55));
}

.dice-lab-die-inner {
  width: 100%;
  height: 100%;
  position: relative;
  transform-style: preserve-3d;
  /* Starting orientation shows face 1 square-on; rollDieTo() overrides
     this transform during/after a roll. */
  transform: rotateX(0deg) rotateY(0deg) rotateZ(0deg);
}

/* All six faces share size/position/face styling; each is rotated and
   pushed out along Z by half the cube's width to form a cube.
   Face color/pip color come from --die-face-a/b/c and --die-pip, which
   default to the ivory/espresso palette below and are overridden per
   current player by the .dice-owner-* classes further down. */
.dice-lab-face {
  position: absolute;
  width: var(--die-size);
  height: var(--die-size);
  left: 0;
  top: 0;
  border-radius: calc(var(--die-size) * 0.17);
  background:
    linear-gradient(155deg, var(--die-face-a, #f5ecd8) 0%, var(--die-face-b, #e8d9b8) 55%, var(--die-face-c, #d8c39a) 100%);
  border: 1px solid rgba(120,90,40,0.35);
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 1fr);
  padding: calc(var(--die-size) * 0.14);
  gap: calc(var(--die-size) * 0.03);
  /* Beveled-tile depth: bright top edge, shaded base, soft drop shadow
     so each face reads as a slightly domed, lacquered tile. */
  box-shadow:
    inset 0 2px 0 rgba(255,255,255,0.6),
    inset 0 -4px 8px rgba(120,95,55,0.25),
    0 2px 6px rgba(0,0,0,0.35);
  backface-visibility: hidden;
}

/* Face placement — six faces of a cube, each sitting half the cube's
   width out from its center along its own axis. */
.dice-lab-face-1 { transform: rotateY(   0deg) translateZ(calc(var(--die-size) / 2)); }
.dice-lab-face-2 { transform: rotateY(  90deg) translateZ(calc(var(--die-size) / 2)); }
.dice-lab-face-3 { transform: rotateX( -90deg) translateZ(calc(var(--die-size) / 2)); }
.dice-lab-face-4 { transform: rotateX(  90deg) translateZ(calc(var(--die-size) / 2)); }
.dice-lab-face-5 { transform: rotateY( -90deg) translateZ(calc(var(--die-size) / 2)); }
.dice-lab-face-6 { transform: rotateY( 180deg) translateZ(calc(var(--die-size) / 2)); }

/* ── Pips ── a 3x3 grid per face; each pip is placed into one of nine
   grid cells via row/column utility classes, so any 1-6 pip pattern
   can be expressed by combining classes on the pip <span>s below. */
.dice-lab-pip {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  align-self: center;
  justify-self: center;
  /* Physical pip: domed, with a small glossy highlight catching light
     from the upper-left. Color comes from --die-pip (defaults to a
     dark espresso tone on ivory; overridden to a light/high-contrast
     tone on the darker player-colour dice below so pips always stay
     readable regardless of face color). */
  background: radial-gradient(circle at 32% 28%, var(--die-pip, #4a3420) 0%, var(--die-pip-mid, #2a1c10) 55%, var(--die-pip-dark, #160e07) 100%);
  box-shadow:
    inset 0 1px 1px rgba(255,255,255,0.25),
    inset 0 -1px 2px rgba(0,0,0,0.5),
    0 1px 1px rgba(0,0,0,0.4);
  aspect-ratio: 1 / 1;
  max-width: calc(var(--die-size) * 0.17);
  max-height: calc(var(--die-size) * 0.17);
}

.pip-r1 { grid-row: 1; }
.pip-r2 { grid-row: 2; }
.pip-r3 { grid-row: 3; }
.pip-c1 { grid-column: 1; }
.pip-c2 { grid-column: 2; }
.pip-c3 { grid-column: 3; }

/* ── Tumble animation ── applied to .dice-lab-die-inner while rolling.
   Pure visual spin; rollDieTo() swaps this out for the exact landing
   transform once the tumble duration elapses, so the die always ends
   precisely on the requested face regardless of how this animation's
   keyframes land. */
@keyframes dlTumble {
  0%   { transform: rotateX(0deg)    rotateY(0deg)    rotateZ(0deg); }
  20%  { transform: rotateX(220deg)  rotateY(160deg)  rotateZ(40deg); }
  40%  { transform: rotateX(380deg)  rotateY(340deg)  rotateZ(-30deg); }
  60%  { transform: rotateX(560deg)  rotateY(480deg)  rotateZ(70deg); }
  80%  { transform: rotateX(700deg)  rotateY(610deg)  rotateZ(-15deg); }
  100% { transform: rotateX(860deg)  rotateY(760deg)  rotateZ(0deg); }
}
.dice-lab-die-inner.dl-rolling {
  animation: dlTumble 0.42s cubic-bezier(.45,.05,.55,.95) infinite;
}

/* Smooth settle once the tumble ends and the final transform is applied
   directly (see rollDieTo() — it removes dl-rolling and sets an inline
   transform with this transition active). */
.dice-lab-die-inner.dl-settling {
  transition: transform 0.45s cubic-bezier(.2,.8,.3,1.05);
}

/* ── Player-colour dice (v187) ──
   Applied to the #dice-raw-row container as dice-owner-blue/green/red/
   neutral, set whenever the dice are (re)rendered for the current
   player. Each palette only overrides the face-color and pip-color
   custom properties consumed above — the cube geometry, bevel shadows,
   and tumble animation are completely shared and untouched.

   Readability: blue and red dice keep a light, slightly desaturated
   face tone with dark pips (same contrast logic as the ivory default).
   Green dice use a brighter, lighter face for the same reason — a
   saturated mid-green with dark pips reads poorly, so the face is
   lightened while the pip stays dark. All three remain easily legible
   at a glance, matching the readability requirement. */
#dice-raw-row.dice-owner-neutral,
.dice-roll-stage-mini.dice-owner-neutral,
.drs-traveller.dice-owner-neutral {
  /* Ivory default — explicit no-op override, matches the base
     --die-face-a/b/c / --die-pip fallback values used above. */
  --die-face-a: #f5ecd8;
  --die-face-b: #e8d9b8;
  --die-face-c: #d8c39a;
  --die-pip:      #4a3420;
  --die-pip-mid:  #2a1c10;
  --die-pip-dark: #160e07;
}

#dice-raw-row.dice-owner-blue,
.dice-roll-stage-mini.dice-owner-blue,
.drs-traveller.dice-owner-blue {
  /* Matches the Blue checker colour family (#8fc6ff/#4a90d9/#1d5f99). */
  --die-face-a: #cfe6ff;
  --die-face-b: #8fc6ff;
  --die-face-c: #4a90d9;
  --die-pip:      #0c2236;
  --die-pip-mid:  #081826;
  --die-pip-dark: #050f18;
}

#dice-raw-row.dice-owner-green,
.dice-roll-stage-mini.dice-owner-green,
.drs-traveller.dice-owner-green {
  /* Matches the Green checker colour family (#82f5d9/#2cd9a8/#009873).
     Lightened relative to the checker tone so dark pips stay readable —
     a saturated mid-green face with dark pips loses contrast quickly. */
  --die-face-a: #d8fcef;
  --die-face-b: #9ff2d9;
  --die-face-c: #4fd9b3;
  --die-pip:      #04362a;
  --die-pip-mid:  #02261c;
  --die-pip-dark: #011a13;
}

#dice-raw-row.dice-owner-red,
.dice-roll-stage-mini.dice-owner-red,
.drs-traveller.dice-owner-red {
  /* Matches the Red checker colour family (#ff9b9a/#ec5e5d/#b8332f). */
  --die-face-a: #ffd9d8;
  --die-face-b: #ff9b9a;
  --die-face-c: #ec5e5d;
  --die-pip:      #3a0c0a;
  --die-pip-mid:  #270706;
  --die-pip-dark: #1a0403;
}

/* ── v3.7.2 Task 1: Triple Dice opening ceremony — animated coloured
   dice, near the board's centre/logo area. Reuses the exact same
   .dice-lab-die/.dice-lab-die-inner/.dice-lab-face/.dice-lab-pip markup
   and rollDieTo()/dl-rolling/dl-settling animation as the main Rolled
   Dice display (see createDieElement(), 05-gameplay-interaction.js) —
   only the container, size, position, and fixed per-colour palette
   below are new. Deliberately its own self-contained colour palette
   (duplicated from .dice-owner-blue/red/green above, not a shared
   selector) so it can never be affected by — or accidentally affect —
   the main dice-raw-row's per-current-player colouring. Sits inside
   #board-stage's matte area, well above where the Bar/Borne-Off zones
   (Task 7/8) or any point/checker sit, so it can never obscure a legal
   move or collide with them. ── */
#td3-opening-dice-stage {
  position: absolute;
  /* v3.7.2 tablet fix — Task 2: landing row pulled down from the old 13%
     (near the top edge) to just above the board's centre/logo, and kept
     clear of the Bar bays (which start at ~49% — see renderBarZones()). */
  top: 36%;
  left: 50%;
  transform: translateX(-50%);
  z-index: 6;
  display: none;
  gap: 26px;
  pointer-events: none;
  --die-size: 34px;
}
#td3-opening-dice-stage.td3-active {
  display: flex;
}
.td3-opening-die-slot {
  width: var(--die-size);
  height: var(--die-size);
  perspective: 300px;
  filter: drop-shadow(0 4px 7px rgba(0,0,0,0.6));
}
/* v3.7.2 tablet fix — Task 2: each coloured die visibly travels/tumbles
   in from off the top of the board to its own fixed landing slot. Purely
   decorative — td3StartOpeningDieSpin() toggles the class, no RNG/state/
   timing is touched, and the display order stays Blue -> Red -> Green.
   Three fixed horizontal offsets so the dice fan into place rather than
   dropping on one spot. Honoured only when the viewer allows motion. */
#td3-opening-die-blue  { --td3-travel-x: -46px; }
#td3-opening-die-red   { --td3-travel-x: 0px; }
#td3-opening-die-green { --td3-travel-x: 46px; }
@media (prefers-reduced-motion: no-preference) {
  .td3-opening-die-slot.td3-travelling {
    animation: td3OpeningDieTravel 640ms cubic-bezier(0.2, 0.75, 0.25, 1) both;
  }
  @keyframes td3OpeningDieTravel {
    0%   { opacity: 0; transform: translate(var(--td3-travel-x, 0px), -150px) rotate(-24deg) scale(0.72); }
    60%  { opacity: 1; }
    82%  { transform: translate(0px, 6px) rotate(3deg) scale(1.05); }
    100% { opacity: 1; transform: translate(0px, 0px) rotate(0deg) scale(1); }
  }
}
.td3-die-blue {
  --die-face-a: #cfe6ff;
  --die-face-b: #8fc6ff;
  --die-face-c: #4a90d9;
  --die-pip:      #0c2236;
  --die-pip-mid:  #081826;
  --die-pip-dark: #050f18;
}
.td3-die-red {
  --die-face-a: #ffd9d8;
  --die-face-b: #ff9b9a;
  --die-face-c: #ec5e5d;
  --die-pip:      #3a0c0a;
  --die-pip-mid:  #270706;
  --die-pip-dark: #1a0403;
}
.td3-die-green {
  --die-face-a: #d8fcef;
  --die-face-b: #9ff2d9;
  --die-face-c: #4fd9b3;
  --die-pip:      #04362a;
  --die-pip-mid:  #02261c;
  --die-pip-dark: #011a13;
}
/* ════════════════════════════════════════════════════════════════════
   v190 — DEVICE PREVIEW MODES (polished mobile/tablet layouts)
   ════════════════════════════════════════════════════════════════════
   Body classes narrow the page container so existing responsive CSS
   rules activate naturally. Board safety: nothing here touches
   board-stage, board-wrap, board-img, board-viewport, or any
   board-rotation-* element. The board scales via its existing
   `width: min(72vw, 840px)` rule; getScale() reads live dimensions
   at click-time so checker positions always auto-correct. */

/* ── Active preview button highlight ── */
button.dp-btn-active {
  opacity: 1 !important;
  filter: brightness(1.3);
  box-shadow:
    inset 0 0 0 1px rgba(255,255,255,0.18),
    0 0 12px rgba(255,255,255,0.14) !important;
}

/* ── Preview badge ── */
.preview-badge {
  display: none;
  position: fixed;
  top: 10px;
  right: 14px;
  z-index: 8000;
  background: rgba(14,11,5,0.92);
  color: var(--tx-gold-bright, #f0cf8c);
  border: 1px solid var(--tx-gold, #d8b46a);
  border-radius: 6px;
  padding: 4px 10px;
  font-size: 10px;
  font-family: 'Courier New', monospace;
  letter-spacing: 0.8px;
  text-transform: uppercase;
  pointer-events: none;
}
body.preview-desktop .preview-badge,
body.preview-tablet .preview-badge,
body.preview-mobile-landscape .preview-badge,
body.preview-mobile-portrait .preview-badge {
  display: block;
}
/* v2.1: belt-and-braces public-build safety net — the JS guard on
   loadDevicePreviewMode() (see near PRODUCT_TIER) already stops the
   public build from ever auto-restoring a preview-mode body class, but
   this rule guarantees the leftover Developer/Admin "PREVIEW:" badge
   can never render outside an internal developer build even so. Only
   affects this one badge; the rest of Device Preview is untouched. */
body:not(.tier-developer) .preview-badge {
  display: none !important;
}

/* ── Status line inside admin group ── */
.device-preview-status {
  font-size: 10px;
  color: var(--tx-text-dim, #a6a9b8);
  font-family: 'Courier New', monospace;
}

/* v266: compact Device Preview primary row (Desktop | Tablet | Mobile)
   and the Mobile-only Portrait/Landscape sub-row — same .admin-group
   button visual language, laid out side-by-side instead of the old
   full-width stacked list. Full Width/Exit Preview is deliberately
   styled smaller/dimmer (.dp-secondary-btn) so it reads as a secondary
   escape hatch, not a fourth primary choice. */
.dp-compact-row {
  display: flex;
  gap: 6px;
}
.dp-compact-row button {
  flex: 1 1 0;
  width: auto;
  text-align: center;
}
.dp-orientation-row {
  margin-top: -2px;
  padding-left: 14px;
}
.dp-orientation-row button {
  font-size: 10px;
  padding: 5px 8px;
  opacity: 0.85;
}
.dp-secondary-btn {
  width: 100% !important;
  text-align: center !important;
  font-size: 10px !important;
  padding: 5px 8px !important;
  opacity: 0.7;
}
.dp-secondary-btn:hover {
  opacity: 1;
}

/* ══════════════════════════════════════════════════════════════════
   DESKTOP — minor max-width cap only, layout otherwise unchanged
   ══════════════════════════════════════════════════════════════════ */
body.preview-desktop .page-layout {
  max-width: 1440px;
}

/* ══════════════════════════════════════════════════════════════════
   TABLET / IPAD — 900px single column, right panel below board
   ══════════════════════════════════════════════════════════════════ */
body.preview-tablet .page-layout {
  max-width: 900px;
  grid-template-columns: 1fr;
  gap: 14px;
}
body.preview-tablet .right-panel {
  position: static;
  width: 100%;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  align-items: start;
}
body.preview-tablet .right-panel .panel-title,
body.preview-tablet .right-panel .panel-section-title {
  grid-column: 1 / -1;
}
body.preview-tablet .clock-panel {
  width: 100%;
}
body.preview-tablet .under-board-controls {
  padding: 10px 12px;
}
body.preview-tablet .under-board-row {
  gap: 8px;
}

/* ══════════════════════════════════════════════════════════════════
   MOBILE LANDSCAPE — 680px single column, compact but readable
   ══════════════════════════════════════════════════════════════════ */
body.preview-mobile-landscape .page-layout {
  max-width: 680px;
  grid-template-columns: 1fr;
  gap: 10px;
}
body.preview-mobile-landscape {
  padding: 10px 12px 20px;
}
body.preview-mobile-landscape .tx-header {
  margin-bottom: 10px;
}
body.preview-mobile-landscape .tx-header-mark {
  font-size: clamp(18px, 4.5vw, 22px);
  letter-spacing: 4px;
}
body.preview-mobile-landscape .tx-header-tagline {
  /* v300: proportionate bump to match the desktop prominence increase.
     v5.1.3: margin-top removed — lives in .tx-header-meta-row now (see
     .tx-header-meta-row's own override below), same reasoning as the
     base (non-preview) rule. */
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 3px;
  margin-top: 0;
}
/* v5.1.3: compact Beta-subtitle + the badge/tagline row, sized down to
   match this preview's already-reduced header scale. */
body.preview-mobile-landscape .tx-header-subtitle {
  font-size: 10px;
  margin-top: 4px;
  padding: 0 8px;
}
body.preview-mobile-landscape .tx-header-meta-row {
  margin-top: 5px;
  gap: 7px;
}
body.preview-mobile-landscape .tx-header-rule {
  margin-top: 8px;
}
body.preview-mobile-landscape .clock-panel {
  gap: 8px;
}
body.preview-mobile-landscape .clock-card {
  padding: 6px 8px 8px;
}
body.preview-mobile-landscape .clock-face {
  width: 80px;
  height: 80px;
}
body.preview-mobile-landscape .clock-face::before {
  inset: 7px;
}
body.preview-mobile-landscape .clock-main {
  font-size: 14px;
}
body.preview-mobile-landscape .clock-sub {
  font-size: 9px;
}
body.preview-mobile-landscape .clock-title {
  font-size: 11px;
  margin-bottom: 6px;
}
body.preview-mobile-landscape .right-panel {
  position: static;
  width: 100%;
}
body.preview-mobile-landscape .under-board-controls,
body.preview-mobile-landscape .under-board-actions {
  padding: 8px 10px;
}
body.preview-mobile-landscape .under-board-row {
  flex-wrap: wrap;
  gap: 6px;
}
body.preview-mobile-landscape .under-board-controls button,
body.preview-mobile-landscape .under-board-actions button {
  flex: 1 1 auto;
  min-width: 100px;
}
body.preview-mobile-landscape .under-board-dice-panel {
  padding: 8px 10px;
  gap: 8px;
}

/* ══════════════════════════════════════════════════════════════════
   MOBILE PORTRAIT — 420px, stacked, tap-friendly control pad
   ══════════════════════════════════════════════════════════════════ */
body.preview-mobile-portrait .page-layout {
  max-width: 420px;
  grid-template-columns: 1fr;
  gap: 7px;
}
body.preview-mobile-portrait {
  padding: 8px 8px 20px;
}
body.preview-mobile-portrait .tx-header {
  margin-bottom: 8px;
}
body.preview-mobile-portrait .tx-header-mark {
  font-size: clamp(18px, 6.5vw, 22px);
  letter-spacing: 3px;
}
body.preview-mobile-portrait .tx-header-tagline {
  display: none;
}
/* v5.1.3: keep the subtitle (unlike the tagline, this is the requested
   "Public Beta • All Pro Features Unlocked" line and stays visible at
   every size) but shrink it and the meta row for this narrowest preview. */
body.preview-mobile-portrait .tx-header-subtitle {
  font-size: 10px;
  margin-top: 4px;
  padding: 0 6px;
}
body.preview-mobile-portrait .tx-header-meta-row {
  margin-top: 5px;
  gap: 6px;
}
body.preview-mobile-portrait .tx-header-rule {
  margin-top: 6px;
  width: 50%;
}
body.preview-mobile-portrait .page-title {
  display: none;
}
/* Clocks: three compact dials in a row */
body.preview-mobile-portrait .clock-panel-wrap {
  margin-bottom: 7px;
}
body.preview-mobile-portrait .clock-panel {
  width: 100%;
  grid-template-columns: repeat(3, 1fr);
  gap: 5px;
}
body.preview-mobile-portrait .clock-card {
  padding: 5px 3px 7px;
  border-radius: 8px;
}
body.preview-mobile-portrait .clock-title {
  font-size: 9px;
  letter-spacing: 0.8px;
  margin-bottom: 5px;
}
body.preview-mobile-portrait .clock-face {
  width: 66px;
  height: 66px;
}
body.preview-mobile-portrait .clock-face::before {
  inset: 5px;
}
body.preview-mobile-portrait .clock-main {
  font-size: 12px;
  font-weight: 900;
}
body.preview-mobile-portrait .clock-sub {
  font-size: 8px;
  margin-top: 2px;
}
/* Dice / status: stacked vertically */
body.preview-mobile-portrait .under-board-dice-panel {
  flex-direction: column;
  padding: 8px 10px;
  gap: 6px;
}
body.preview-mobile-portrait .udp-col-rolled,
body.preview-mobile-portrait .udp-col-available {
  border-left: none;
  padding-left: 0;
}
body.preview-mobile-portrait .udp-col-turn {
  flex-direction: row;
  align-items: center;
  gap: 10px;
}
/* Info bar */
body.preview-mobile-portrait .info-bar {
  font-size: 11px;
  padding: 6px 10px;
}
/* Action pad (Player Actions + Game Flow now in .under-board-actions) */
body.preview-mobile-portrait .under-board-actions {
  padding: 8px 10px;
  gap: 6px;
}
/* Control pad (Save/Undo now in .under-board-controls) */
body.preview-mobile-portrait .under-board-controls {
  padding: 8px 10px;
  gap: 6px;
}
body.preview-mobile-portrait .under-board-row {
  padding-bottom: 6px;
  gap: 5px;
}
body.preview-mobile-portrait .under-board-row-title {
  display: none;
}
/* Player Actions row: Roll Dice + End Turn as large paired buttons */
body.preview-mobile-portrait .under-board-actions .under-board-row:nth-child(1) {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
}
body.preview-mobile-portrait .under-board-actions .under-board-row:nth-child(1) .btn-roll-dice,
body.preview-mobile-portrait .under-board-actions .under-board-row:nth-child(1) .btn-end-turn {
  padding: 12px 8px;
  font-size: 13px;
  text-align: center;
  min-width: 0;
  width: 100%;
}
body.preview-mobile-portrait .under-board-actions .under-board-row:nth-child(1) button:not(.btn-roll-dice):not(.btn-end-turn) {
  padding: 6px 5px;
  font-size: 10px;
  opacity: 0.65;
}
/* Game Flow row: v236 Fix 3 — single consolidated Start/Pause/Resume button */
body.preview-mobile-portrait .under-board-actions .under-board-row:nth-child(2) {
  display: grid;
  grid-template-columns: 1fr;
  gap: 5px;
}
body.preview-mobile-portrait .under-board-actions .under-board-row:nth-child(2) button {
  padding: 9px 4px;
  font-size: 11px;
  text-align: center;
  min-width: 0;
  width: 100%;
}
/* Save / Undo: smaller, wrap freely */
body.preview-mobile-portrait .under-board-controls .under-board-row:nth-child(1),
body.preview-mobile-portrait .under-board-controls .under-board-row:nth-child(2) {
  flex-wrap: wrap;
  gap: 4px;
}
body.preview-mobile-portrait .under-board-controls .under-board-row:nth-child(1) button,
body.preview-mobile-portrait .under-board-controls .under-board-row:nth-child(2) button {
  padding: 5px 7px;
  font-size: 10px;
  min-width: 0;
  flex: 1 1 auto;
}
body.preview-mobile-portrait .small-status,
body.preview-mobile-portrait .under-board-inline-label {
  font-size: 9px;
  width: 100%;
}
/* Borne Off: single column on portrait */
body.preview-mobile-portrait .under-board-borne-off {
  padding: 8px 10px;
}
body.preview-mobile-portrait .borne-off-display {
  grid-template-columns: 1fr;
  gap: 5px;
}
/* Right panel */
body.preview-mobile-portrait .right-panel {
  position: static;
  width: 100%;
  font-size: 12px;
  padding: 10px;
}
/* Admin */
body.preview-mobile-portrait .admin-toggle-btn {
  font-size: 9px;
  padding: 7px 10px;
}
body.preview-mobile-portrait .bottom-admin-grid {
  grid-template-columns: 1fr;
}


/* v190d hotfix — remove the tall empty space under Rolled/Available Moves.
   In stacked/mobile layouts, .udp-col-dice-combo was using a 420px flex-basis;
   because the parent becomes column-based, that flex-basis became height.
   Force the dice combo and the two dice cards to size to their content. */
.udp-col-dice-combo {
  flex-grow: 1;
  flex-shrink: 1;
  flex-basis: auto;
}

.under-board-dice-panel,
.udp-col-dice-combo,
.udp-dice-grid,
.dice-col-rolled,
.dice-col-available {
  min-height: 0;
}

.dice-col-rolled,
.dice-col-available {
  align-self: start;
}

@media (max-width: 760px) {
  .udp-col-dice-combo {
    flex: 0 1 auto;
    min-width: 0;
  }
}

body.preview-mobile-portrait .udp-col-dice-combo,
body.preview-mobile-landscape .udp-col-dice-combo,
body.preview-tablet .udp-col-dice-combo {
  flex: 0 1 auto;
  min-width: 0;
}

/* ════════════════════════════════════════════════════════════════════
   v195 — GAME OVER CELEBRATION MODAL
   Shown only for real completed games, never during Auto Match /
   headless / batch runs, never for stalled games (winner === null).
   Pure CSS + a tiny inline canvas sparkle — no external libraries.
   ════════════════════════════════════════════════════════════════════ */

/* Fullscreen backdrop */
#goc-backdrop {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 6000;
  background: rgba(2,4,10,0.82);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  align-items: center;
  justify-content: center;
  padding: 20px;
}
#goc-backdrop.visible {
  display: flex;
}

/* Glass card
   v2.1.6: widened into a scrollable dashboard shell (was a fixed 480px
   "toast"-style card). max-height/overflow-y are new — the card can now
   exceed the viewport (three player cards + two charts + highlights +
   full stats + tips row) and scrolls internally instead of ever running
   off-screen, per the v2.1.6 responsive requirement. */
#goc-card {
  position: relative;
  max-width: 1180px;
  width: 100%;
  max-height: 94vh;
  overflow-y: auto;
  overflow-x: hidden;
  background:
    linear-gradient(170deg, rgba(216,180,106,0.07), transparent 44%),
    #0c1120;
  border: 1px solid rgba(216,180,106,0.35);
  border-radius: 16px;
  padding: 0 26px 20px;
  box-shadow:
    0 0 0 1px rgba(0,0,0,0.7),
    0 24px 60px rgba(0,0,0,0.65),
    0 8px 20px rgba(0,0,0,0.45),
    inset 0 1px 0 rgba(255,255,255,0.06);
  animation: gocCardIn 0.36s cubic-bezier(.18,.82,.28,1.06) both;
  scrollbar-width: thin;
  scrollbar-color: rgba(216,180,106,0.4) transparent;
}
#goc-card::-webkit-scrollbar { width: 9px; }
#goc-card::-webkit-scrollbar-thumb { background: rgba(216,180,106,0.35); border-radius: 5px; }
@keyframes gocCardIn {
  from { opacity: 0; transform: translateY(16px) scale(0.97); }
  to   { opacity: 1; transform: translateY(0)    scale(1);    }
}

/* Player-colour border glow variants */
#goc-card.goc-blue  {
  border-color: rgba(116,185,255,0.55);
  box-shadow: 0 0 0 1px rgba(0,0,0,0.7), 0 24px 60px rgba(0,0,0,0.65),
              0 0 44px rgba(116,185,255,0.16), inset 0 1px 0 rgba(255,255,255,0.06);
}
#goc-card.goc-green {
  border-color: rgba(85,239,196,0.55);
  box-shadow: 0 0 0 1px rgba(0,0,0,0.7), 0 24px 60px rgba(0,0,0,0.65),
              0 0 44px rgba(85,239,196,0.16), inset 0 1px 0 rgba(255,255,255,0.06);
}
#goc-card.goc-red {
  border-color: rgba(255,118,117,0.55);
  box-shadow: 0 0 0 1px rgba(0,0,0,0.7), 0 24px 60px rgba(0,0,0,0.65),
              0 0 44px rgba(255,118,117,0.16), inset 0 1px 0 rgba(255,255,255,0.06);
}

/* Sparkle canvas — absolute, pointer-events:none, doesn't affect layout */
#goc-sparkle-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  border-radius: 16px;
}

/* v2.2.6: winner headline with slow pulse glow — the trophy/subtitle
   lines that used to sit here were moved into .goc-medallion and
   retired respectively (see the WINNER CERTIFICATE block below); the
   glow animation and per-colour treatment are unchanged. */
.goc-winner {
  text-align: center;
  font-family: Georgia, 'Times New Roman', serif;
  font-size: clamp(26px, 5.4vw, 38px);
  font-weight: 700;
  letter-spacing: 1.5px;
  margin-bottom: 3px;
  animation: gocPulse 2.6s ease-in-out infinite;
}
.goc-winner.blue  { color: #74b9ff; text-shadow: 0 0 20px rgba(116,185,255,0.5); }
.goc-winner.green { color: #55efc4; text-shadow: 0 0 20px rgba(85,239,196,0.5);  }
.goc-winner.red   { color: #ff7675; text-shadow: 0 0 20px rgba(255,118,117,0.5); }
@keyframes gocPulse {
  0%, 100% { opacity: 1; }
  50%       { opacity: 0.8; }
}

.goc-rule {
  height: 1px;
  background: linear-gradient(90deg, transparent,
    rgba(216,180,106,0.35) 25%, rgba(216,180,106,0.35) 75%, transparent);
  margin: 14px 0;
}

/* v2.2.6: #goc-stats is now a simple vertical stack of .goc-cert-row
   blocks (each row defines its own internal grid) rather than the old
   generic 2-column grid — see the WINNER CERTIFICATE block below for
   .goc-cert-row/.goc-cert-row-details/.goc-cert-row-mid/
   .goc-cert-row-table. .goc-cl-* colour helpers are still used by the
   Player Results table. */
.goc-stats { display: block; }
.goc-cl-blue  { color: #74b9ff; }
.goc-cl-green { color: #55efc4; }
.goc-cl-red   { color: #ff7675; }

/* Button row */
.goc-buttons {
  display: flex;
  gap: 7px;
  flex-wrap: wrap;
}
.goc-buttons button {
  flex: 1 1 110px;
  padding: 9px 12px;
  border-radius: var(--tx-radius-sm, 7px);
  font-size: 12px;
  font-weight: bold;
  font-family: inherit;
  cursor: pointer;
  transition: background 0.12s, color 0.12s, transform 0.07s;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.07), 0 2px 0 rgba(0,0,0,0.7);
}
.goc-buttons button:active { transform: translateY(1px); }

.goc-btn-new {
  background: rgba(216,180,106,0.1);
  border: 1px solid var(--tx-gold, #d8b46a);
  color: var(--tx-gold-bright, #f0cf8c);
}
.goc-btn-new:hover { background: var(--tx-gold, #d8b46a); color: #14110a; }

.goc-btn-copy {
  background: var(--tx-bg-panel-2, #0a0e1a);
  border: 1px solid var(--tx-blue-glow, #6fa8d8);
  color: var(--tx-blue-glow, #6fa8d8);
}
.goc-btn-copy:hover { background: var(--tx-blue-glow, #6fa8d8); color: #080e18; }

.goc-btn-close {
  background: transparent;
  border: 1px solid var(--tx-line, #232c47);
  color: var(--tx-text-faint, #6c7186);
  flex: 0 0 auto;
}
.goc-btn-close:hover { border-color: var(--tx-text-dim, #a6a9b8); color: var(--tx-text-dim, #a6a9b8); }

/* ════════════════════════════════════════════════════════════════════
   v2.1.6 — WINNER RESULTS DASHBOARD
   Expands the same #goc-backdrop/#goc-card system above into a full
   responsive dashboard. Every value rendered into these containers is
   computed at runtime by showGameOverCelebration() (and its helpers)
   from real playerStats/liveGameHistory/borneOffState — nothing here
   is a hard-coded sample number; the CSS below only lays out shapes.
   ════════════════════════════════════════════════════════════════════ */

/* Sticky top bar — Share/New Game/Close stay reachable while the card
   scrolls internally (required: reachable through scrolling on mobile). */
.goc-topbar {
  position: sticky;
  top: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
  padding: 14px 0 10px;
  margin: 0 -26px;
  padding-left: 26px;
  padding-right: 26px;
  background: linear-gradient(180deg, #0d1222 0%, #0d1222 78%, rgba(13,18,34,0));
}
.goc-topbar-info {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 16px;
  font-family: 'Courier New', monospace;
}
.goc-ti-item { display: flex; flex-direction: column; line-height: 1.25; }
.goc-ti-label {
  font-size: 8.5px; text-transform: uppercase; letter-spacing: 1px;
  color: var(--tx-text-faint, #6c7186);
}
.goc-ti-value { font-size: 12px; color: var(--tx-text, #e9e6db); font-weight: bold; }
.goc-topbar-actions { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.goc-topbar-actions button {
  padding: 7px 11px;
  border-radius: var(--tx-radius-sm, 7px);
  font-size: 11.5px;
  font-weight: bold;
  font-family: inherit;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.12s, color 0.12s, transform 0.07s;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.07), 0 2px 0 rgba(0,0,0,0.7);
}
.goc-topbar-actions button:active { transform: translateY(1px); }
.goc-btn-share {
  background: rgba(216,180,106,0.1);
  border: 1px solid var(--tx-gold, #d8b46a);
  color: var(--tx-gold-bright, #f0cf8c);
}
.goc-btn-share:hover { background: var(--tx-gold, #d8b46a); color: #14110a; }
.goc-x-close {
  background: transparent;
  border: 1px solid var(--tx-line, #232c47);
  color: var(--tx-text-faint, #6c7186);
  width: 30px; height: 30px; padding: 0 !important;
  display: flex; align-items: center; justify-content: center;
  font-size: 13px;
}
.goc-x-close:hover { border-color: var(--tx-text-dim, #a6a9b8); color: var(--tx-text-dim, #a6a9b8); }

/* v2.4.4: explicit social share row — Email/Facebook/X/Instagram/Copy,
   secondary to .goc-btn-share above. Deliberately smaller/lighter than
   .goc-topbar-actions buttons so it doesn't compete with Share Results/
   New Game/Close, per spec: "not overpower New Game / Close". Text-only
   labels (no icon set/third-party library), flex-wrap for narrow widths. */
.goc-social-row {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  padding: 0 0 10px;
}
.goc-social-label {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--tx-text-faint, #6c7186);
  margin-right: 2px;
}
.goc-social-btn {
  padding: 5px 10px;
  border-radius: var(--tx-radius-sm, 7px);
  font-size: 11px;
  font-weight: bold;
  font-family: inherit;
  cursor: pointer;
  white-space: nowrap;
  background: var(--tx-bg-panel-2, #0a0e1a);
  border: 1px solid var(--tx-line, #232c47);
  color: var(--tx-text-dim, #a6a9b8);
  transition: background 0.12s, color 0.12s, transform 0.07s;
}
.goc-social-btn:hover { border-color: var(--tx-gold, #d8b46a); color: var(--tx-gold-bright, #f0cf8c); }
.goc-social-btn:active { transform: translateY(1px); }
.goc-social-btn:disabled { opacity: .5; cursor: wait; }

/* v3.4.0: Winner Archive / Career Stats quick-access row. Deliberately its
   own class (goc-archive-btn), NOT goc-social-btn, so it never collides
   with existing selectors/tests that count exactly 5 .goc-social-btn share
   buttons (Email/Facebook/X/Instagram/Copy). Visually identical styling to
   .goc-social-btn, kept as a separate ruleset so future edits to the share
   row can't accidentally affect this row (and vice versa). */
.goc-archive-btn {
  padding: 5px 10px;
  border-radius: var(--tx-radius-sm, 7px);
  font-size: 11px;
  font-weight: bold;
  font-family: inherit;
  cursor: pointer;
  white-space: nowrap;
  background: var(--tx-bg-panel-2, #0a0e1a);
  border: 1px solid var(--tx-line, #232c47);
  color: var(--tx-text-dim, #a6a9b8);
  transition: background 0.12s, color 0.12s, transform 0.07s;
}
.goc-archive-btn:hover { border-color: var(--tx-gold, #d8b46a); color: var(--tx-gold-bright, #f0cf8c); }
.goc-archive-btn:active { transform: translateY(1px); }
.goc-archive-btn:disabled { opacity: .5; cursor: wait; }

/* Hero (trophy/winner/subtitle) — sparkles are bounded to just this
   section, not the whole tall scrollable dashboard, so the effect stays
   a tasteful flourish and never has to animate across thousands of
   pixels of stats content below it. */
.goc-hero { position: relative; padding: 6px 0 4px; overflow: hidden; }
#goc-sparkle-canvas { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }

/* v2.2.6: the old three-column .goc-cards-row/.goc-pcard vertical player
   cards (flagged by the visual-parity spec as "giant empty vertical
   player cards") are retired — replaced by the compact .goc-ptable
   certificate table in the WINNER CERTIFICATE block below. The old
   .goc-main-grid 2-column charts/highlights layout is likewise retired
   — Pip Race, Dice Fortune, the Official Result seal, Game Highlights,
   and Personal Record are now siblings inside one .goc-cert-row-mid
   grid (WINNER CERTIFICATE block below), so they share one consistent
   certificate-panel treatment instead of two different layouts. */
.goc-chart-card, .goc-highlights-card, .goc-fullstats-card, .goc-dyk-card, .goc-beta-card {
  background: var(--tx-bg-panel-2, #0a0e1a);
  border: 1px solid var(--tx-line, #232c47);
  border-radius: var(--tx-radius, 10px);
  padding: 12px 14px;
  min-width: 0;
}
/* v2.2.6: inside the certificate specifically, chart/highlights panels
   get a light parchment/cream inset (per spec §7 "light/cream chart
   background or well-framed inset") instead of the app's normal dark
   panel — everywhere else (e.g. live Game Trends during play) keeps the
   dark styling above untouched. */
#goc-cert-capture .goc-chart-card,
#goc-cert-capture .goc-highlights-card {
  background: linear-gradient(180deg, #f4ecd8 0%, #ece0c4 100%);
  border: 1px solid var(--tx-gold, #d8b46a);
  box-shadow: inset 0 0 0 1px rgba(216,180,106,0.25);
}
#goc-cert-capture .goc-chart-card-title { color: #6b4f1f; }
#goc-cert-capture .goc-chart-card-sub { color: #8a7550; }
#goc-cert-capture .goc-fact-pill {
  background: rgba(107,79,31,0.08); border: 1px solid rgba(107,79,31,0.25); color: #6b4f1f;
}
#goc-cert-capture .goc-fact-pill b { color: #4a3512; }
#goc-cert-capture .goc-dice-fact-cell { background: rgba(255,255,255,0.35); border: 1px solid rgba(107,79,31,0.2); }
#goc-cert-capture .goc-dice-fact-cell .goc-df-name { color: #6b4f1f; }
#goc-cert-capture .goc-dice-fact-cell .goc-df-avg  { color: #4a3512; }
#goc-cert-capture .goc-dice-fact-cell .goc-df-sub  { color: #8a7550; }
#goc-cert-capture .goc-highlight-row { border-bottom-color: rgba(107,79,31,0.15); }
#goc-cert-capture .goc-hl-label { color: #6b4f1f; }
#goc-cert-capture .goc-hl-value { color: #2c2008; }

.goc-chart-card-title {
  font-size: 12.5px; font-weight: bold; color: var(--tx-gold, #d8b46a);
  margin-bottom: 6px; display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
}
.goc-chart-card-sub { font-size: 9.5px; font-weight: normal; color: var(--tx-text-faint, #6c7186); }
.goc-chart-svg-wrap svg { width: 100%; height: auto; display: block; }
.goc-chart-facts { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.goc-fact-pill {
  font-size: 10px; font-family: 'Courier New', monospace;
  padding: 4px 8px; border-radius: 20px;
  background: rgba(216,180,106,0.08); border: 1px solid rgba(216,180,106,0.28);
  color: var(--tx-text-dim, #a6a9b8);
}
.goc-fact-pill b { color: var(--tx-gold-bright, #f0cf8c); }
.goc-dice-facts {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-top: 8px;
}
.goc-dice-fact-cell {
  text-align: center; padding: 6px 4px; border-radius: 7px;
  background: rgba(255,255,255,0.02); border: 1px solid var(--tx-line, #232c47);
}
.goc-dice-fact-cell .goc-df-name { font-size: 9.5px; font-family: 'Courier New', monospace; margin-bottom: 3px; }
.goc-dice-fact-cell .goc-df-avg { font-size: 15px; font-weight: bold; font-family: 'Courier New', monospace; }
.goc-dice-fact-cell .goc-df-sub { font-size: 8.5px; color: var(--tx-text-faint, #6c7186); margin-top: 1px; }

.goc-highlights-card .goc-chart-card-title { margin-bottom: 8px; }
.goc-highlight-row {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 6px 0; border-bottom: 1px solid rgba(120,140,200,0.08);
  font-size: 11.5px;
}
.goc-highlight-row:last-child { border-bottom: none; }
.goc-hl-label { color: var(--tx-text-dim, #a6a9b8); }
.goc-hl-value { font-family: 'Courier New', monospace; font-weight: bold; color: var(--tx-text, #e9e6db); white-space: nowrap; }

/* Full Game Stats — collapsible */
.goc-fullstats-card { margin-bottom: 14px; padding: 0; overflow: hidden; }
.goc-fullstats-toggle {
  width: 100%; display: flex; align-items: center; justify-content: space-between;
  background: none; border: none; cursor: pointer;
  padding: 12px 14px; font-family: inherit;
  font-size: 12.5px; font-weight: bold; color: var(--tx-gold, #d8b46a);
}
.goc-fullstats-chevron { transition: transform 0.15s; color: var(--tx-text-faint, #6c7186); }
.goc-fullstats-card.goc-open .goc-fullstats-chevron { transform: rotate(180deg); }
.goc-fullstats-body { display: none; padding: 0 14px 14px; }
.goc-fullstats-card.goc-open .goc-fullstats-body { display: block; }
.goc-fs-table { display: grid; grid-template-columns: 1fr repeat(3, minmax(0,1fr)); gap: 5px 8px; font-size: 11px; }
.goc-fs-head { font-family: 'Courier New', monospace; font-weight: bold; font-size: 10px; padding-bottom: 4px; border-bottom: 1px solid var(--tx-line, #232c47); }
.goc-fs-row-label { color: var(--tx-text-faint, #6c7186); font-size: 10.5px; align-self: center; }
.goc-fs-val { font-family: 'Courier New', monospace; text-align: right; align-self: center; }
.goc-pro-teaser {
  font-size: 10.5px; color: var(--tx-text-faint, #6c7186); font-style: italic;
  padding: 8px 14px 12px; border-top: 1px solid rgba(120,140,200,0.08); margin-top: 4px;
}

/* ════════════════════════════════════════════════════════════════════
   v2.2.6 — WINNER CERTIFICATE (visual parity / presentation pass)
   Replaces v2.2.5's dark-dashboard composition with a collectible
   certificate composition, per an explicit task spec: an ornate gold
   outer frame, a large champion medallion, a dominant central masthead,
   a large framed board-design panel, an Official Result seal, and a
   compact Blue/Green/Red player-results table (instead of three tall
   vertical cards). Every VALUE still comes from the exact same
   showGameOverCelebration()/gocCompute*()/playerStats data as v2.2.5 —
   this block is presentation only. #goc-cert-capture remains the exact
   region gocDownloadJPG()/gocDownloadPNG()/gocShareResults() (image
   path) capture — it still deliberately excludes .goc-topbar/.goc-buttons.
   ════════════════════════════════════════════════════════════════════ */
#goc-cert-capture {
  background: var(--tx-bg-deep, #05070d);
  border-radius: var(--tx-radius, 10px);
  padding: 2px 2px 4px;
}

/* Ornate outer certificate frame — gradients/borders/pseudo-element
   corner motifs only, no image dependency, per spec §1. */
.goc-cert-frame {
  position: relative;
  margin: 4px;
  padding: 20px 20px 16px;
  border-radius: 14px;
  background:
    radial-gradient(circle at 12% 8%, rgba(216,180,106,0.10), transparent 40%),
    radial-gradient(circle at 88% 92%, rgba(216,180,106,0.08), transparent 42%),
    linear-gradient(170deg, #0a0d18 0%, #05070d 60%, #05070d 100%);
  border: 2px solid var(--tx-gold, #d8b46a);
  box-shadow:
    0 0 0 1px rgba(216,180,106,0.35),
    inset 0 0 0 5px rgba(5,7,13,0.9),
    inset 0 0 0 6px rgba(216,180,106,0.28),
    0 10px 30px rgba(0,0,0,0.5);
}
/* Small gold corner motifs — pure CSS, no image asset. Four real (empty,
   aria-hidden) elements rather than ::before/::after so all four corners
   can be styled independently from one shared .goc-cert-corner rule. */
.goc-cert-corner {
  position: absolute; width: 22px; height: 22px; pointer-events: none;
  border: 2px solid var(--tx-gold-bright, #f0cf8c);
  opacity: 0.75;
}
.goc-cert-corner-tl { top: 8px;    left: 8px;  border-right: none; border-bottom: none; }
.goc-cert-corner-tr { top: 8px;    right: 8px; border-left: none;  border-bottom: none; }
.goc-cert-corner-bl { bottom: 8px; left: 8px;  border-right: none; border-top: none; }
.goc-cert-corner-br { bottom: 8px; right: 8px; border-left: none;  border-top: none; }

/* Hero row: champion medallion | central masthead | board-design panel */
.goc-cert-hero-row {
  display: grid;
  grid-template-columns: 132px 1fr 176px;
  align-items: center;
  gap: 14px;
}

/* ── Champion trophy presentation — v3.4.0 STANDALONE REDESIGN ──
   Per the v3.4.0 spec ("replace the left circular medallion treatment
   with a larger standalone trophy presentation on the dark certificate
   background"): the v2.2.x-v3.3.3 .goc-medallion-ring (a gold radial-
   filled circle with a 3px border + double box-shadow ring, which
   capped the visible trophy well below its own box because a portrait
   image only fills a square box's height, not its width — see the
   v3.3.3 change report) is REMOVED entirely. The trophy artwork now
   sits directly on the certificate's own dark background (no ring, no
   circular clip, no gold disc backdrop), sized far larger than any
   previous version, with a soft two-layer drop-shadow standing in for
   the "tasteful framing" the spec allows: an ambient gold-ish glow
   (16px blur, low opacity — reads as a premium halo, not a hard edge)
   plus a grounding dark shadow beneath (for depth/legibility against
   the busy certificate background), rather than any drawn border. The
   OFFICIAL WINNER / CHAMPION labels stay exactly where they were,
   directly below the trophy — only the container above them changed. */
.goc-medallion { text-align: center; }
/* v3.4.0: height set directly (no square/ring box to letterbox inside),
   width derived from the real trophy.png ratio via aspect-ratio (same
   technique introduced in v3.3.3, just no longer constrained by a ring).
   150px is a deliberate, unmistakable jump from v3.3.3's 94px (+59.6%)
   — comfortably inside the 132px hero-row column (desktop) with ~16px
   of clearance on each side, so it never brushes the central masthead
   text next to it. object-fit:contain kept as a defensive fallback. */
.goc-medallion-trophy {
  height: 150px; width: auto; aspect-ratio: 1024 / 1536; object-fit: contain;
  filter:
    drop-shadow(0 0 16px var(--medallion-accent, var(--tx-gold, #d8b46a)))
    drop-shadow(0 6px 10px rgba(0,0,0,0.55));
}
/* v3.3.1: hidden by default; revealed only if the trophy image's onerror
   fires (see Play-TrigammonX.html), so it degrades gracefully rather
   than showing a broken-image icon. v3.4.0: sized up to match the new
   standalone trophy's much larger footprint (was 48px, ring-era). */
.goc-medallion-trophy-fallback {
  display: none; font-size: 96px; line-height: 1;
  filter:
    drop-shadow(0 0 16px var(--medallion-accent, var(--tx-gold, #d8b46a)))
    drop-shadow(0 6px 10px rgba(0,0,0,0.55));
}
.goc-medallion-label {
  margin-top: 10px; font-size: 10px; font-weight: bold; letter-spacing: 2px;
  text-transform: uppercase; color: var(--tx-gold-bright, #f0cf8c);
}
.goc-medallion-sub {
  font-size: 9px; letter-spacing: 3px; text-transform: uppercase;
  color: var(--medallion-accent, var(--tx-gold, #d8b46a)); margin-top: 2px; font-weight: bold;
}
/* Winner-colour ribbon accent — driven purely by #goc-card's existing
   goc-blue/goc-green/goc-red class (set in showGameOverCelebration(),
   unchanged); no new JS needed for this. */
#goc-card.goc-blue  .goc-medallion { --medallion-accent: #74b9ff; }
#goc-card.goc-green .goc-medallion { --medallion-accent: #55efc4; }
#goc-card.goc-red   .goc-medallion { --medallion-accent: #ff7675; }

/* ── Central masthead, per spec §3 ──
   v3.5.0 Part B: brand line changed from all-caps "TRIGAMMONX™" to a
   compact, refined title-case "TrigammonX™" wordmark treatment. No
   approved TrigammonX logo image asset exists anywhere in this package
   (only board-design background art and the certificate trophy image —
   see the v3.5.0 change report for the confirmed inspection), so per
   spec this reuses the same serif family as the page's own header
   wordmark (.tx-header-mark) at a deliberately small size — a
   typographic "wordmark" rather than a plain caption — while staying
   well below .goc-winner in size/weight so the winner name remains the
   dominant focal point of the certificate. text-transform: uppercase is
   removed so the title-case text actually renders as written.
   v3.5.1: an approved logo asset now exists (trigammonx-v3.5.1/img/
   trigammonx-logo.png — see Play-TrigammonX.html and the v3.5.1 change
   report), so .goc-brand-logo sits directly above this same .goc-brand
   text wordmark rather than replacing it — deliberately kept small
   (44px tall desktop) so it reads as a compact mark, not a redesign,
   and stays well clear of .goc-winner below in the same visual
   hierarchy this wordmark itself already respects. */
.goc-brand-logo {
  display: block; height: 44px; width: auto; max-width: 70%;
  margin: 0 auto 4px; object-fit: contain;
  filter: drop-shadow(0 0 8px rgba(216,180,106,0.25));
}
.goc-brand {
  text-align: center; font-size: 13px; font-weight: bold; letter-spacing: 1.5px;
  color: var(--tx-gold, #d8b46a); font-family: Georgia, 'Times New Roman', serif;
  text-shadow: 0 0 10px rgba(216,180,106,0.25);
}
.goc-cert-label {
  text-align: center; font-size: 10px; letter-spacing: 4px; text-transform: uppercase;
  color: var(--tx-gold-dim, rgba(216,180,106,0.35)); margin-top: 2px; font-weight: bold;
}
.goc-congrats {
  text-align: center; font-size: 10.5px; letter-spacing: 1.5px; text-transform: uppercase;
  color: var(--tx-text-dim, #a6a9b8); margin-top: 12px; font-family: 'Courier New', monospace;
}
.goc-cert-title {
  text-align: center; font-size: 16px; font-weight: bold; margin-top: 8px;
  color: var(--tx-gold-bright, #f0cf8c); letter-spacing: 0.5px;
}
.goc-cert-summary {
  text-align: center; font-size: 11.5px; color: var(--tx-text-dim, #a6a9b8);
  margin-top: 3px; padding: 0 20px; line-height: 1.4;
}

/* ── Board-design panel — large framed miniature, per spec §4 (NOT a
   tiny circular icon) ── */
.goc-badge-row { display: flex; justify-content: center; }
.goc-board-badge {
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  padding: 10px 12px 12px;
  background: linear-gradient(180deg, rgba(216,180,106,0.10), rgba(216,180,106,0.03));
  border: 1px solid var(--tx-gold, #d8b46a);
  border-radius: 12px;
  width: 100%;
}
.goc-board-badge img {
  width: 100%; max-width: 148px; aspect-ratio: 1 / 1; object-fit: cover;
  border-radius: 8px;
  border: 2px solid var(--tx-gold-bright, #f0cf8c);
  box-shadow: 0 4px 12px rgba(0,0,0,0.4);
}
.goc-board-badge-text { text-align: center; }
.goc-board-badge-label { font-size: 8.5px; letter-spacing: 1.5px; color: var(--tx-text-faint, #6c7186); text-transform: uppercase; }
.goc-board-badge-value { font-size: 13px; font-weight: bold; color: var(--tx-gold-bright, #f0cf8c); }

/* ── Details + Featured stats row ── */
.goc-cert-row { margin-top: 14px; }
.goc-cert-row-details {
  display: grid;
  grid-template-columns: 260px 1fr;
  gap: 12px;
  align-items: stretch;
}
.goc-feature-tiles {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px;
}
.goc-feature-tile {
  background: var(--tx-bg-panel, #0c1120); border: 1px solid var(--tx-gold-dim, rgba(216,180,106,0.35));
  border-radius: var(--tx-radius-sm, 7px); padding: 9px 6px; text-align: center;
}
.goc-ft-label { font-size: 8.5px; letter-spacing: 0.5px; color: var(--tx-text-faint, #6c7186); text-transform: uppercase; }
.goc-ft-value { font-size: 16px; font-weight: bold; color: var(--tx-gold-bright, #f0cf8c); font-family: 'Courier New', monospace; margin-top: 3px; }
.goc-ft-sub { font-size: 8px; color: var(--tx-text-faint, #6c7186); margin-top: 1px; }

.goc-pcard-type {
  font-size: 8.5px; font-weight: normal; color: var(--tx-text-faint, #6c7186);
  margin-left: 6px; text-transform: uppercase; letter-spacing: 0.5px;
}

.goc-details-card {
  background: var(--tx-bg-panel, #0c1120); border: 1px solid var(--tx-line, #232c47);
  border-radius: var(--tx-radius, 10px); padding: 12px 14px;
}
.goc-details-grid { display: grid; grid-template-columns: 1fr; gap: 6px 16px; margin-top: 6px; }
.goc-details-row { display: flex; justify-content: space-between; gap: 8px; font-size: 11px; }
.goc-details-label { color: var(--tx-text-faint, #6c7186); }
.goc-details-value { color: var(--tx-text, #e9e6db); font-weight: bold; text-align: right; }
.goc-details-roster {
  display: flex; flex-direction: column; gap: 6px; margin-top: 10px; padding-top: 8px;
  border-top: 1px solid rgba(120,140,200,0.08); font-size: 11px;
}
.goc-details-roster-row { display: flex; align-items: center; gap: 6px; color: var(--tx-text-dim, #a6a9b8); }
.goc-details-roster-type { font-size: 9px; color: var(--tx-text-faint, #6c7186); text-transform: uppercase; }
.goc-dot-blue  { width: 9px; height: 9px; border-radius: 50%; background: #74b9ff; display: inline-block; }
.goc-dot-green { width: 9px; height: 9px; border-radius: 50%; background: #55efc4; display: inline-block; }
.goc-dot-red   { width: 9px; height: 9px; border-radius: 50%; background: #ff7675; display: inline-block; }

/* ── Middle row: Official Seal + Game Highlights (stacked, one column)
   | Pip Race | Dice Fortune | Personal Record — per spec's ASCII layout
   §"REQUIRED VISUAL COMPOSITION" ── */
.goc-cert-row-mid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
  align-items: start;
}
.goc-seal-col { display: flex; flex-direction: column; gap: 10px; min-width: 0; }

/* v3.2.1: Borne-Off Race | Hit Battle — placed below the existing mid row
   (Pip Race/Dice Fortune/Game Highlights/Personal Record), per spec.
   Reuses .goc-chart-card as-is; only this row's own 2-column grid is new. */
.goc-cert-row-charts2 {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px;
  align-items: start;
}
/* v3.2.1: Dice Face Distribution, inside the collapsible Full Player
   Stats body, above the existing .goc-fs-table — reuses .goc-chart-card
   as-is, just needs its own bottom margin to separate it from the table
   that follows. */
.goc-dicefaces-card { margin-bottom: 12px; }

/* ── Official Result seal, per spec §10 — presentation only, no legal
   certification implied. ── */
.goc-seal-card {
  background: linear-gradient(180deg, #f4ecd8 0%, #ece0c4 100%);
  border: 1px solid var(--tx-gold, #d8b46a);
  border-radius: var(--tx-radius, 10px);
  padding: 14px 12px;
  text-align: center;
}
.goc-seal-motif { display: flex; justify-content: center; margin-bottom: 6px; }
.goc-seal-ring {
  width: 46px; height: 46px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: radial-gradient(circle at 35% 30%, #f0cf8c, #b8903f 70%);
  border: 2px solid #6b4f1f;
  color: #3a2a0d; font-size: 20px; box-shadow: 0 3px 8px rgba(0,0,0,0.25);
}
.goc-seal-title { font-size: 11.5px; font-weight: bold; letter-spacing: 1px; color: #4a3512; text-transform: uppercase; }
.goc-seal-body { font-size: 10.5px; color: #6b4f1f; margin-top: 6px; line-height: 1.4; }
.goc-seal-date { font-size: 9px; color: #8a7550; margin-top: 6px; font-family: 'Courier New', monospace; }
.goc-seal-sig {
  font-family: Georgia, 'Times New Roman', serif; font-style: italic;
  font-size: 13px; color: #4a3512; margin-top: 8px; letter-spacing: 0.5px;
}

.goc-pr-card {
  background: var(--tx-bg-panel, #0c1120); border: 1px solid var(--tx-gold-dim, rgba(216,180,106,0.35));
  border-radius: var(--tx-radius, 10px); padding: 12px 14px;
}
.goc-pr-card-empty { display: flex; flex-direction: column; justify-content: center; }
.goc-pr-empty-note { font-size: 10.5px; color: var(--tx-text-faint, #6c7186); font-style: italic; margin-top: 8px; line-height: 1.4; }
.goc-pr-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; margin-top: 8px; }
.goc-pr-tile { text-align: center; padding: 6px 4px; }
.goc-pr-label { font-size: 8px; letter-spacing: 0.5px; color: var(--tx-text-faint, #6c7186); text-transform: uppercase; }
.goc-pr-value { font-size: 14px; font-weight: bold; color: var(--tx-text, #e9e6db); font-family: 'Courier New', monospace; margin-top: 2px; }

/* ── Player Results — compact certificate table, per spec §8 (replaces
   the old three tall vertical goc-pcard columns) ── */
.goc-cert-row-table { margin-top: 4px; }
.goc-ptable-card {
  background: var(--tx-bg-panel, #0c1120); border: 1px solid var(--tx-line, #232c47);
  border-radius: var(--tx-radius, 10px); padding: 12px 14px;
}
.goc-ptable { display: flex; flex-direction: column; margin-top: 6px; }
.goc-pt-row {
  display: grid; grid-template-columns: 120px repeat(3, 1fr);
  gap: 8px; align-items: center;
  padding: 6px 0; border-bottom: 1px solid rgba(120,140,200,0.08);
}
.goc-pt-row:last-child { border-bottom: none; }
.goc-pt-rowlabel { font-size: 10.5px; color: var(--tx-text-faint, #6c7186); }
.goc-pt-cell { font-size: 13px; font-weight: bold; font-family: 'Courier New', monospace; text-align: center; }
.goc-pt-head { padding-bottom: 10px; border-bottom: 1px solid var(--tx-gold-dim, rgba(216,180,106,0.35)); }
.goc-pt-colhead {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  padding: 4px 4px 0; border-radius: 8px 8px 0 0;
}
.goc-pt-head-winner { background: rgba(216,180,106,0.08); }
.goc-pt-badge { font-size: 15px; line-height: 1.1; min-height: 17px; }
.goc-pt-name { font-size: 12px; font-weight: bold; }
.goc-pt-head-blue  .goc-pt-name { color: #74b9ff; }
.goc-pt-head-green .goc-pt-name { color: #55efc4; }
.goc-pt-head-red   .goc-pt-name { color: #ff7675; }

.goc-btn-jpg, .goc-btn-png {
  background: var(--tx-bg-panel-2, #0a0e1a); border: 1px solid var(--tx-gold-dim, rgba(216,180,106,0.35));
  color: var(--tx-text-dim, #a6a9b8);
}
.goc-btn-jpg:hover, .goc-btn-png:hover { background: var(--tx-gold, #d8b46a); color: #14110a; }

/* Responsive — 1300/1024/980/768/430/390 per spec's explicit test list.
   Certificate hierarchy: hero row stays 3-across down to ~980px, then
   the board panel drops below the masthead; the mid row (seal/pip/
   dice/personal) goes 4→2→1 columns; the details+features row and the
   player table always stay legible, never overflowing horizontally. */
@media (max-width: 1024px) {
  .goc-cert-hero-row { grid-template-columns: 110px 1fr 150px; }
  .goc-cert-row-mid { grid-template-columns: repeat(2, 1fr); }
  /* v3.4.0: the 110px medallion column at this breakpoint is narrower
     than desktop's 132px, so the trophy is scaled down proportionally
     (height derived so its aspect-ratio width still clears the column
     with margin — 130px tall -> ~86.7px wide inside a 110px column). */
  .goc-medallion-trophy { height: 130px; }
  /* v3.5.1: the centre masthead column also narrows at this breakpoint,
     so the logo scales down a step with it (matches the trophy's own
     proportional-shrink treatment immediately above). */
  .goc-brand-logo { height: 36px; }
}
@media (max-width: 980px) {
  .goc-cert-row-details { grid-template-columns: 1fr; }
}
@media (max-width: 768px) {
  .goc-cert-hero-row { grid-template-columns: 1fr; text-align: center; }
  /* v3.4.0: stacked single-column layout gives the trophy the full
     certificate width to work with, so it can stay large (140px tall,
     up from v3.3.3's 74px tablet value) while remaining comfortably
     balanced above the OFFICIAL WINNER/CHAMPION labels. */
  .goc-medallion-trophy { height: 140px; width: auto; aspect-ratio: 1024 / 1536; }
  .goc-medallion-trophy-fallback { font-size: 88px; }
  /* v3.5.1: stacked single-column layout gives the masthead the full
     certificate width too, but the logo stays modest (30px) so it never
     crowds the wordmark/winner name beneath it on narrow phones — see
     Task 4's "logo remains readable but not oversized" requirement. */
  .goc-brand-logo { height: 30px; margin-bottom: 3px; }
  .goc-board-badge { flex-direction: row; }
  .goc-board-badge img { max-width: 64px; }
  .goc-feature-tiles { grid-template-columns: repeat(3, 1fr); }
  .goc-pt-row { grid-template-columns: 90px repeat(3, 1fr); }
  .goc-buttons { flex-wrap: wrap; }
  .goc-cert-row-charts2 { grid-template-columns: 1fr; }
}
@media (max-width: 430px) {
  .goc-cert-frame { padding: 14px 12px 12px; margin: 2px; }
  .goc-cert-row-mid { grid-template-columns: 1fr; }
  .goc-feature-tiles { grid-template-columns: repeat(2, 1fr); }
  .goc-pr-grid { grid-template-columns: repeat(2, 1fr); }
  .goc-cert-summary { padding: 0 4px; }
  .goc-board-badge img { max-width: 52px; }
  .goc-pt-row { grid-template-columns: 74px repeat(3, 1fr); gap: 4px; }
  .goc-pt-name { font-size: 10.5px; }
  .goc-pt-cell { font-size: 11.5px; }
}

/* Did You Know / Beta Updates — shared visual language, used BOTH on
   the main page (always-present, ungated) and reused inside this
   dashboard's lower row from the exact same render functions/data. */
.goc-lower-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 4px; }
.tx-tip-title, .tx-beta-title {
  font-size: 12px; font-weight: bold; color: var(--tx-gold, #d8b46a);
  display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px;
}
.tx-tip-body { font-size: 12px; line-height: 1.5; color: var(--tx-text-dim, #a6a9b8); min-height: 34px; }
.tx-tip-nav { display: flex; align-items: center; justify-content: flex-end; gap: 6px; margin-top: 8px; }
.tx-tip-nav button {
  width: 24px; height: 24px; border-radius: 6px; cursor: pointer;
  background: var(--tx-bg-panel, #0c1120); border: 1px solid var(--tx-line, #232c47);
  color: var(--tx-text-dim, #a6a9b8); font-size: 12px; line-height: 1;
}
.tx-tip-nav button:hover { border-color: var(--tx-gold, #d8b46a); color: var(--tx-gold-bright, #f0cf8c); }
.tx-tip-counter { font-size: 9.5px; color: var(--tx-text-faint, #6c7186); font-family: 'Courier New', monospace; margin-right: 4px; }
.tx-beta-list { max-height: 132px; overflow-y: auto; padding-right: 2px; }
.tx-beta-item { display: flex; align-items: baseline; gap: 6px; font-size: 11px; padding: 4px 0; border-bottom: 1px solid rgba(120,140,200,0.08); }
.tx-beta-item:last-child { border-bottom: none; }
.tx-beta-ver { color: var(--tx-gold, #d8b46a); font-family: 'Courier New', monospace; font-weight: bold; flex: 0 0 auto; }
.tx-beta-text { color: var(--tx-text-dim, #a6a9b8); flex: 1 1 auto; min-width: 0; }
.tx-beta-credit { color: var(--tx-blue-glow, #6fa8d8); font-size: 10px; flex: 0 0 auto; white-space: nowrap; }
.tx-beta-link { margin-top: 8px; font-size: 10.5px; text-align: right; }
.tx-beta-link a { color: var(--tx-blue-glow, #6fa8d8); text-decoration: none; }
.tx-beta-link a:hover { text-decoration: underline; }

/* Responsive — matches this file's established breakpoints (1024/760/520).
   v2.2.6: .goc-main-grid/.goc-cards-row/.goc-pcard-metrics no longer
   exist (see the WINNER CERTIFICATE block above for their v2.2.6
   replacements and that block's own 1024/980/768/430 responsive rules);
   removed here rather than left as dead selectors. */
@media (max-width: 760px) {
  #goc-card { padding: 0 14px 16px; max-height: 96vh; }
  .goc-topbar { margin: 0 -14px; padding-left: 14px; padding-right: 14px; }
  .goc-lower-row { grid-template-columns: 1fr; }
  .goc-dice-facts { grid-template-columns: repeat(3, 1fr); }
  .goc-topbar-actions .goc-btn-text { display: none; }
  .goc-topbar-actions button { padding: 7px 9px; }
  .goc-social-btn { padding: 5px 8px; font-size: 10.5px; }
  .goc-archive-btn { padding: 5px 8px; font-size: 10.5px; }
}
@media (max-width: 520px) {
  .goc-winner { letter-spacing: 1px; }
  .goc-fs-table { grid-template-columns: 1fr repeat(3, minmax(0,1fr)); font-size: 10px; }
  .goc-ti-label { font-size: 8px; }
}

/* ════════════════════════════════════════════════════════════════════
   v196 — COMPACT DICE ROLL STAGE
   A subtle tray indicator + corridor space wrapping #dice-raw-row.
   Travelling dice (.drs-traveller) are absolutely positioned inside
   .dice-roll-stage-mini and always pointer-events:none so they can
   never block board clicks or button presses.
   ════════════════════════════════════════════════════════════════════ */

/* Outer wrapper: becomes the coordinate system for absolute travellers */
.dice-roll-stage-mini {
  position: relative;
  display: flex;
  align-items: center;
  gap: 4px;
  /* overflow visible so dice can travel outside their own box during
     the animation — the containing under-board-dice-panel is what
     actually clips; that panel has no overflow:hidden so this is safe */
  overflow: visible;
}

/* Mini tray — tiny visual origin indicator, no larger than 2 die-heights */
.dice-tray-mini {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: 4px;
  align-items: center;
  justify-content: center;
  min-width: 14px;
  padding: 3px;
}
.dice-tray-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: rgba(216,180,106,0.25);
  transition: background 0.2s, box-shadow 0.2s;
}
.dice-tray-mini.tray-active .dice-tray-dot {
  background: rgba(216,180,106,0.7);
  box-shadow: 0 0 6px rgba(216,180,106,0.4);
}

/* The landing zone: dice-raw-row sits here as a normal flex item */
.dice-landing-mini {
  flex: 1 1 auto;
  min-width: 0;
  overflow: visible;
}

/* Travelling die — absolutely positioned over .dice-roll-stage-mini
   during the roll animation; removed as soon as dice land.
   perspective here keeps preserve-3d on .dice-lab-die-inner working
   while this wrapper transitions its position. */
.drs-traveller {
  position: absolute;
  pointer-events: none;   /* NEVER blocks board clicks or buttons */
  perspective: var(--die-size, 48px);
  z-index: 30;
}

@keyframes drsBounce {
  0%   { transform: scale(1);    }
  35%  { transform: scale(1.15) translateY(-3px); }
  65%  { transform: scale(0.93); }
  85%  { transform: scale(1.05); }
  100% { transform: scale(1);    }
}
.drs-traveller.drs-bouncing {
  animation: drsBounce 0.3s cubic-bezier(.3,.7,.4,1) both;
}
/* ════════════════════════════════════════════════════════════════════
   v197 — HOW TO PLAY MODAL
   ════════════════════════════════════════════════════════════════════ */

/* "How to Play" button in the right panel */
.htp-btn {
  width: 100%;
  padding: 8px 12px;
  border-radius: var(--tx-radius-sm);
  border: 1px solid rgba(216,180,106,0.35);
  background: rgba(216,180,106,0.06);
  color: var(--tx-gold);
  cursor: pointer;
  font-size: 11px;
  font-family: inherit;
  font-weight: bold;
  letter-spacing: 0.3px;
  text-align: center;
  transition: background 0.12s, border-color 0.12s, color 0.12s;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.06), 0 1px 0 rgba(0,0,0,0.5);
}
.htp-btn:hover {
  background: rgba(216,180,106,0.13);
  border-color: var(--tx-gold);
  color: var(--tx-gold-bright);
}

/* Modal backdrop */
#htp-backdrop {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 7000;
  background: rgba(2,4,10,0.80);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  align-items: center;
  justify-content: center;
  padding: 16px;
}
#htp-backdrop.visible { display: flex; }



/* v2.3.2: compact player-facing Scotty speed audition button. */
.voice-sample-btn {
  margin-top: 8px;
  min-height: 32px;
  padding: 6px 12px;
  border-radius: 8px;
  border: 1px solid var(--tx-border);
  background: var(--tx-surface-2);
  color: var(--tx-text);
  font: inherit;
  font-size: 12px;
  font-weight: 700;
  cursor: pointer;
}
.voice-sample-btn:hover { filter: brightness(1.08); }


/* v2.3.5 — Winner Certificate export feedback, visible inside modal. */
.goc-export-status {
  min-height: 18px;
  margin: 5px 8px 0;
  text-align: center;
  font-size: 11px;
  line-height: 1.35;
  color: var(--tx-text-faint);
}
.goc-export-status[data-kind="working"] { color: #e7c65a; }
.goc-export-status[data-kind="success"] { color: #8fd8a7; }
.goc-export-status[data-kind="error"] { color: #ff9b91; }
.goc-buttons button:disabled { opacity: .6; cursor: wait; }

/* ════════════════════════════════════════════════════════════════════
   v3.7.1 (Issue 5 — iPad auto-lock / Safari background interruption
   protection). #interruption-overlay is a dedicated, always-highest-
   z-index full-screen backdrop shown ONLY by showInterruptionOverlay()
   (10-clocks-themes-ui.js) after a live real game auto-pauses because
   the page was hidden/backgrounded. Deliberately separate from
   #goc-backdrop and every other modal — its whole job is to prevent the
   player studying the board after an involuntary interruption, so it
   must be able to sit on top of anything else already open, and it
   never opens/closes any other way than that one function pair
   (show/hide) + the Resume Play button's resumeFromInterruption() call.
   ════════════════════════════════════════════════════════════════════ */
#interruption-overlay {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 9000;
  background: rgba(2,4,10,0.94);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  align-items: center;
  justify-content: center;
  padding: 20px;
}
#interruption-overlay.visible {
  display: flex;
}
#interruption-card {
  max-width: 440px;
  width: 100%;
  text-align: center;
  background:
    linear-gradient(170deg, rgba(216,180,106,0.09), transparent 50%),
    #0c1120;
  border: 1px solid rgba(216,180,106,0.4);
  border-radius: 18px;
  padding: 36px 28px 32px;
  box-shadow:
    0 0 0 1px rgba(0,0,0,0.7),
    0 24px 70px rgba(0,0,0,0.7),
    inset 0 1px 0 rgba(255,255,255,0.06);
}
.interruption-icon {
  font-size: 44px;
  line-height: 1;
  margin-bottom: 14px;
  opacity: 0.9;
}
.interruption-title {
  font-size: 22px;
  font-weight: 800;
  letter-spacing: 1.5px;
  color: #ffd700;
  margin-bottom: 12px;
}
.interruption-body {
  font-size: 15px;
  line-height: 1.5;
  color: #d8d8e0;
  margin-bottom: 26px;
}
/* Touch-friendly on iPad: generous tap target, no reliance on hover. */
.interruption-resume-btn {
  display: inline-block;
  width: 100%;
  padding: 16px 20px;
  font-size: 17px;
  font-weight: 800;
  letter-spacing: 0.5px;
  color: #0c1120;
  background: linear-gradient(180deg, #ffe27a, #d8b46a);
  border: 2px solid #ffd700;
  border-radius: 12px;
  cursor: pointer;
  box-shadow: 0 6px 18px rgba(216,180,106,0.35);
}
.interruption-resume-btn:active {
  transform: scale(0.98);
}
@media (max-width: 480px) {
  #interruption-card { padding: 28px 20px 24px; }
  .interruption-title { font-size: 19px; }
}

/* ════════════════════════════════════════════════════════════════════
   v4.2 — MODULE D: End-of-game banner + persistent "Stay on Board" bar
   A compact celebratory beat shown OVER the frozen final board (the
   board stays visible around/behind it), with three explicit choices.
   Deliberately NOT a full-screen backdrop like #goc-backdrop — this sits
   below it (z-index 5000 vs 6000) so "View Winner Certificate" cleanly
   covers it. Fades in over ~450ms (Module G: brief, bounded, non-abrupt;
   never gates on or interrupts SCOTTY's winner audio).
   ════════════════════════════════════════════════════════════════════ */
#tgx-endgame-banner {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 5000;
  align-items: flex-start;
  justify-content: center;
  padding: 7vh 16px 16px;
  background: rgba(2, 4, 10, 0.28);
  pointer-events: none;   /* board behind stays inert anyway (gameOver) — clicks pass through */
}
#tgx-endgame-banner.visible { display: flex; }

#tgx-endgame-card {
  pointer-events: auto;
  max-width: 460px;
  width: 100%;
  text-align: center;
  background:
    linear-gradient(170deg, rgba(216,180,106,0.12), transparent 55%),
    #0c1120;
  border: 1px solid rgba(216,180,106,0.45);
  border-radius: 16px;
  padding: 22px 22px 20px;
  box-shadow:
    0 0 0 1px rgba(0,0,0,0.7),
    0 22px 60px rgba(0,0,0,0.62),
    inset 0 1px 0 rgba(255,255,255,0.06);
  animation: tgxEndgameIn 0.45s cubic-bezier(.18,.82,.28,1.06) both;
}
@keyframes tgxEndgameIn {
  from { opacity: 0; transform: translateY(-14px) scale(0.97); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  #tgx-endgame-card { animation-duration: 0.01s; }
}

.tgx-endgame-headline {
  font-size: 22px;
  font-weight: 800;
  letter-spacing: 0.6px;
  color: #ffd700;
  margin-bottom: 8px;
  line-height: 1.2;
}
.tgx-endgame-headline.tgx-eg-blue  { color: #74b9ff; }
.tgx-endgame-headline.tgx-eg-red   { color: #ff7675; }
.tgx-endgame-headline.tgx-eg-green { color: #55efc4; }

.tgx-endgame-stats {
  font-size: 12.5px;
  line-height: 1.5;
  color: #c8c8d2;
  margin-bottom: 6px;
}
.tgx-endgame-matchnote {
  font-size: 11.5px;
  line-height: 1.45;
  color: #f0cf8c;
  margin-bottom: 6px;
}
.tgx-endgame-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: center;
  margin-top: 12px;
}
.tgx-endgame-btn {
  flex: 1 1 auto;
  min-width: 128px;
  padding: 11px 14px;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.3px;
  color: #e8e8ee;
  background: #141a2b;
  border: 1px solid rgba(216,180,106,0.35);
  border-radius: 10px;
  cursor: pointer;
}
.tgx-endgame-btn:hover  { background: #1b2237; }
.tgx-endgame-btn:active { transform: scale(0.98); }
.tgx-endgame-btn-primary {
  color: #0c1120;
  background: linear-gradient(180deg, #ffe27a, #d8b46a);
  border-color: #ffd700;
}
.tgx-endgame-btn-ghost {
  background: transparent;
  color: #9aa0b4;
}

/* Persistent post-game bar — appears after "Stay on Board" (or after the
   player closes the certificate dashboard while the game is still over),
   keeping the certificate and a new game one tap away. */
#tgx-postgame-bar {
  display: none;
  position: fixed;
  left: 50%;
  bottom: 14px;
  transform: translateX(-50%);
  z-index: 5000;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  background: rgba(12, 17, 32, 0.96);
  border: 1px solid rgba(216,180,106,0.4);
  border-radius: 12px;
  box-shadow: 0 10px 30px rgba(0,0,0,0.5);
  max-width: calc(100vw - 24px);
  flex-wrap: wrap;
  justify-content: center;
}
#tgx-postgame-bar.visible { display: flex; }
.tgx-postgame-label {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.4px;
  color: #f0cf8c;
}
.tgx-postgame-btn {
  padding: 8px 12px;
  font-size: 12px;
  font-weight: 700;
  color: #e8e8ee;
  background: #141a2b;
  border: 1px solid rgba(216,180,106,0.35);
  border-radius: 9px;
  cursor: pointer;
}
.tgx-postgame-btn:hover  { background: #1b2237; }
.tgx-postgame-btn:active { transform: scale(0.98); }

@media (max-width: 480px) {
  #tgx-endgame-banner { padding-top: 4vh; }
  #tgx-endgame-card { padding: 18px 16px 16px; }
  .tgx-endgame-headline { font-size: 19px; }
  .tgx-endgame-btn { min-width: 0; flex-basis: 100%; }
}

/* ════════════════════════════════════════════════════════════════════
   v5.0 — TRIGAMMONX ACADEMY (Modules A / C / D / E / F)
   Presentation only. The Academy identity card, the Position Lab panel,
   and the practice-completion card. None of this touches the board layer
   or any gameplay state.
   ════════════════════════════════════════════════════════════════════ */
.academy-identity {
  margin: 8px 0 4px;
  padding: 10px 14px;
  text-align: center;
  border: 1px solid rgba(162,155,254,0.5);
  border-radius: 12px;
  background:
    linear-gradient(170deg, rgba(162,155,254,0.14), transparent 60%),
    #10132a;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.05), 0 6px 16px rgba(0,0,0,0.4);
}
.academy-identity-title {
  font-size: 15px;
  font-weight: 800;
  letter-spacing: 2px;
  color: #c9c4ff;
}
.academy-identity-sub {
  font-size: 11px;
  letter-spacing: 1.5px;
  color: #9a94c8;
  margin-top: 2px;
}
.academy-identity-badge {
  display: inline-block;
  margin-top: 7px;
  padding: 2px 10px;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 1.5px;
  color: #0d0d1a;
  background: linear-gradient(180deg, #b9b2ff, #8f86e0);
  border-radius: 6px;
}

.academy-lab {
  margin: 8px 0;
  padding: 12px 14px;
  border: 1px solid rgba(162,155,254,0.45);
  border-radius: 12px;
  background:
    linear-gradient(180deg, rgba(162,155,254,0.08), transparent 45%),
    #0d1022;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.05);
}
.academy-lab-title {
  font-size: 13px;
  font-weight: 800;
  letter-spacing: 2px;
  color: #ffd700;
}
.academy-lab-hint {
  font-size: 11px;
  line-height: 1.5;
  color: #b7b2d6;
  margin: 4px 0 8px;
}
/* v5.0.2 (Module C): desktop-only "you can also drag" note. js/15-academy.js
   sets display:none on tap-only / iPad layouts; this is the desktop look. */
.academy-lab-hint-desktop {
  margin-top: -4px;
  font-style: italic;
  color: #8f8ab0;
}
/* v5.0.2 (Module D): the in-practice "Edit Position" bar. */
.academy-practice-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin: 8px 0 4px;
  padding: 8px 10px;
  border: 1px solid #3a3560;
  border-radius: 8px;
  background: #14172b;
}
.academy-practice-bar-label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.6px;
  color: #b7b2d6;
}
.academy-practice-bar .academy-lab-btn { margin-left: auto; }
.academy-pickup-note {
  font-size: 11px;
  color: #82f5d9;
  min-height: 1em;
  margin-bottom: 6px;
}
.academy-valid-status {
  font-size: 12px;
  font-weight: 700;
  padding: 7px 10px;
  border-radius: 8px;
  margin-bottom: 10px;
  border: 1px solid transparent;
}
.academy-valid-status.ok        { color: #55efc4; background: rgba(0,184,148,0.12);  border-color: rgba(0,184,148,0.4); }
.academy-valid-status.invalid   { color: #ff9b8f; background: rgba(192,57,43,0.12);  border-color: rgba(192,57,43,0.4); }
.academy-valid-status.completed { color: #ffd27a; background: rgba(216,180,106,0.12); border-color: rgba(216,180,106,0.45); }

.academy-lab-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin: 6px 0;
}
.academy-lab-label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 1px;
  color: #a29bfe;
}
.academy-lab-note {
  font-size: 10px;
  color: #7d78a0;
  margin: 2px 0 6px;
}
.academy-next-row { display: inline-flex; gap: 6px; }
.acq-next-btn {
  padding: 5px 12px;
  font-size: 12px;
  font-weight: 700;
  border-radius: 8px;
  border: 1px solid rgba(255,255,255,0.18);
  background: #141a2b;
  color: #c8c8d2;
  cursor: pointer;
}
.acq-next-btn.acq-blue.acq-next-active  { background: #2c6fb0; color: #fff; border-color: #74b9ff; }
.acq-next-btn.acq-red.acq-next-active   { background: #b0392f; color: #fff; border-color: #ff7675; }
.acq-next-btn.acq-green.acq-next-active { background: #0f8f74; color: #fff; border-color: #55efc4; }

.academy-lab-btns { margin-top: 10px; }
.academy-lab-btn {
  flex: 1 1 auto;
  min-width: 120px;
  padding: 10px 12px;
  font-size: 12px;
  font-weight: 700;
  color: #e8e8ee;
  background: #141a2b;
  border: 1px solid rgba(162,155,254,0.4);
  border-radius: 10px;
  cursor: pointer;
}
.academy-lab-btn:hover:not(:disabled)  { background: #1b2237; }
.academy-lab-btn:disabled { opacity: 0.45; cursor: not-allowed; }
.academy-lab-btn-primary {
  color: #0c1120;
  background: linear-gradient(180deg, #b9b2ff, #8f86e0);
  border-color: #b9b2ff;
}

/* practice-complete card */
.academy-complete {
  margin: 8px 0;
  padding: 16px 16px 14px;
  text-align: center;
  border: 1px solid rgba(162,155,254,0.5);
  border-radius: 14px;
  background:
    linear-gradient(170deg, rgba(162,155,254,0.14), transparent 55%),
    #10132a;
  box-shadow: 0 10px 28px rgba(0,0,0,0.5);
}
.academy-complete-kicker {
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 2px;
  color: #a29bfe;
}
.academy-complete-head {
  font-size: 22px;
  font-weight: 800;
  letter-spacing: 1px;
  margin: 6px 0;
  color: #ffd700;
}
.academy-complete-head.acq-blue  { color: #74b9ff; }
.academy-complete-head.acq-red   { color: #ff7675; }
.academy-complete-head.acq-green { color: #55efc4; }
.academy-complete-note {
  font-size: 11px;
  line-height: 1.5;
  color: #9a94c8;
  margin-bottom: 12px;
}
.academy-complete-btns {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: center;
}

/* Academy body-state hooks (kept minimal — the board itself is untouched).
   v5.1.1: drag is removed, so the checker cursor is a plain pointer, not
   the "grab hand" that implied dragging. */
body.academy-setup #board-wrap .checker { cursor: pointer; }
body.academy-setup.academy-has-pickup #board-wrap { cursor: copy; }

.pm-prominent-btn.pm-btn-academy.pm-active {
  background: linear-gradient(180deg, #b9b2ff, #8f86e0);
  color: #0c1120;
  border-color: #b9b2ff;
}

@media (max-width: 480px) {
  .academy-lab-btn { flex-basis: 100%; }
  .academy-identity-title { font-size: 13px; letter-spacing: 1.5px; }
}

/* ════════════════════════════════════════════════════════════════════
   v5.0.1 — Academy Position Lab interaction fix (Tasks 5 & 6)
   Scoped ENTIRELY to body.academy-setup — nothing here affects Regular /
   Tournament play or the rest of the app.
   ════════════════════════════════════════════════════════════════════ */

/* Task 5 — stop iPad/Safari native selection, Copy/Translate callout and
   native image drag on the Academy editor surfaces only. */
body.academy-setup #board-wrap,
body.academy-setup #board-wrap *,
body.academy-setup #borneoff-strip,
body.academy-setup #borneoff-strip *,
body.academy-setup #bar-strip,
body.academy-setup #bar-strip * {
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  -webkit-user-drag: none;
}

/* touch-action:none ONLY on the actual draggable targets — the checkers
   and the in-frame trays — so an Academy drag never scrolls the page,
   while touching the board background / matte / page still scrolls
   normally (Task: "do not make the iPad page impossible to scroll"). */
body.academy-setup #board-wrap .checker,
body.academy-setup #board-stage > .board-tray-strip-inframe .board-tray {
  touch-action: none;
}

/* Task 6 — clear Academy selection ring on the held source. Deliberately
   distinct from the game's legal-move rings (this is setup, not a legal
   move): a bright dashed violet halo + soft glow. v5.1.1: applied to
   EVERY checker in a held stack/group selection (handoff §4 — "all
   selected checkers should highlight together"), not just one. */
body.academy-setup #board-wrap .checker.academy-selected {
  box-shadow:
    0 0 0 3px rgba(162,155,254,0.95),
    0 0 14px 3px rgba(162,155,254,0.7),
    inset 0 0 0 2px rgba(255,255,255,0.5);
  outline: 2px dashed rgba(201,196,255,0.9);
  outline-offset: 2px;
  z-index: 30;
}
body.academy-setup .board-tray.academy-selected {
  border-color: #b9b2ff !important;
  box-shadow:
    0 0 0 2px rgba(162,155,254,0.9),
    0 0 12px rgba(162,155,254,0.6) !important;
}

/* ══════════════════════════════════════════════════════════════════
   v5.0.3 — Players / Seats, Academy pre-play confirm, Danger Zone,
   destructive-data modal, non-interactive Practice badge.
   ══════════════════════════════════════════════════════════════════ */

/* Part 5 — Practice Mode is a STATUS badge, not a control. */
.academy-status-badge {
  background: transparent;
  color: #b9b2ff;
  border: 1px solid #4b4483;
  letter-spacing: 2px;
  cursor: default;
  user-select: none;
  pointer-events: none;
}

/* Part 3/6/13 — Players / Seats panel */
.px-seats-panel { margin: 10px 0 4px; }
.px-seats-body { display: flex; flex-direction: column; gap: 6px; }
.px-seat-row {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  padding: 6px 8px; border: 1px solid #302b52; border-radius: 8px; background: #14172b;
}
.px-seat-color { font-weight: 700; font-size: 12px; min-width: 42px; }
.px-seat-row .player-type-select { font-size: 11px; padding: 3px 6px; }
.px-dot { width: 10px; height: 10px; border-radius: 50%; display: inline-block; flex: 0 0 auto; }
.px-dot.px-blue { background: #4aa3ff; }
.px-dot.px-red { background: #ff6b6b; }
.px-dot.px-green { background: #4ad991; }
.px-seat-queued { font-size: 10px; color: #ffd479; font-weight: 700; }
.px-seats-actions { display: flex; gap: 6px; margin-top: 8px; flex-wrap: wrap; }
.px-seats-actions .player-name-input { flex: 1 1 130px; min-width: 120px; }
.px-seats-note { margin-top: 6px; font-size: 10px; color: #8f8ab0; font-style: italic; }

/* Part 4 — Academy pre-play seat confirmation */
.px-academy-confirm {
  margin: 8px 0; padding: 12px; border: 1px solid #4b4483; border-radius: 10px;
  background: #16182e;
}
.px-academy-confirm-kicker { font-size: 11px; font-weight: 800; letter-spacing: 2px; color: #ffd700; }
.px-academy-confirm-body { margin: 8px 0; font-size: 12px; }
.px-confirm-row { display: flex; align-items: center; gap: 8px; padding: 3px 0; }
.px-confirm-who { margin-left: auto; color: #cfcbe8; }
.px-confirm-meta { font-size: 12px; color: #b7b2d6; margin-top: 4px; }
.px-academy-confirm-btns { display: flex; gap: 8px; margin-top: 8px; }

/* Part 12B — Danger Zone controls + modal */
.px-danger-note { font-size: 10px; color: #ff9d9d; margin: 4px 0 8px; line-height: 1.4; }
.px-danger-btn {
  width: 100%; margin-bottom: 6px; padding: 7px 10px;
  border: 1px dashed #c0392b; border-radius: 6px;
  background: #241012; color: #ff8f8f; font: inherit; font-size: 12px; cursor: pointer;
}
.px-danger-btn:hover { background: #2e1416; }
.px-danger-btn-final {
  border-style: solid; background: #c0392b; color: #fff; font-weight: 700;
  width: auto; margin: 0;
}
.px-danger-btn-final:disabled { opacity: 0.4; cursor: not-allowed; }
.px-dx-modal {
  position: fixed; inset: 0; z-index: 6200;
  display: flex; align-items: center; justify-content: center;
  background: rgba(4,4,12,0.72); padding: 16px;
}
.px-dx-card {
  max-width: 440px; width: 100%; background: #16182e;
  border: 1px solid #c0392b; border-radius: 12px; padding: 18px;
  box-shadow: 0 20px 60px rgba(0,0,0,0.6);
}
.px-dx-title { font-size: 15px; font-weight: 800; color: #ff8f8f; margin-bottom: 8px; }
.px-dx-body { font-size: 12px; line-height: 1.5; color: #d7d3ec; }
.px-dx-typelabel { display: block; margin: 12px 0 4px; font-size: 12px; font-weight: 700; color: #ffd479; }
.px-dx-card .player-name-input { width: 100%; }
.px-dx-btns { display: flex; gap: 8px; justify-content: flex-end; margin-top: 14px; }

/* ══════════════════════════════════════════════════════════════════
   v5.0.5 — Expand All / Collapse All control (Issue 5) +
   subdued Advanced / Data Management (Danger Zone) card (Issue 3).
   ══════════════════════════════════════════════════════════════════ */
.tx-expand-all-row {
  display: flex;
  justify-content: flex-end;
  margin: 2px 0 6px;
}
.tx-expand-all-btn {
  font: inherit;
  font-size: 11px;
  padding: 4px 10px;
  border-radius: 6px;
  border: 1px solid var(--tx-border, #3a3560);
  background: transparent;
  color: var(--tx-text-faint, #9a94c0);
  cursor: pointer;
  letter-spacing: 0.3px;
}
.tx-expand-all-btn:hover { color: var(--tx-text, #cfcbe8); border-color: #5a5490; }

/* Issue 3: the Danger Zone card reads as clearly secondary — muted
   heading, no bright/red block. The destructive BUTTONS keep their
   warning styling (.px-danger-btn, defined earlier) once revealed. */
.pro-card-advanced > .panel-title {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.4px;
  color: var(--tx-text-faint, #8f8ab0);
  opacity: 0.85;
}
.pro-card-advanced {
  border-color: var(--tx-border, #302b52);
  background: transparent;
}
.pro-card-advanced-body { margin-top: 8px; }
.pro-card-advanced-body .px-danger-note { margin-top: 0; }

/* ══════════════════════════════════════════════════════════════════
   v5.0.6 (public §2) — Official 2 Dice informational notice.
   Neutral / informational styling (NOT a red warning). Shown at most
   once per session on a deliberate switch into Official 2 Dice.
   ══════════════════════════════════════════════════════════════════ */
.o2-dice-notice {
  position: fixed;
  inset: 0;
  z-index: 6100;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(4, 4, 12, 0.66);
  padding: 16px;
}
.o2-dice-notice-card {
  max-width: 440px;
  width: 100%;
  background: var(--tx-bg-panel, #16182e);
  border: 1px solid var(--tx-line, #3a3560);
  border-radius: 12px;
  padding: 20px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.55);
}
.o2-dice-notice-kicker {
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 2px;
  color: var(--tx-gold, #fdcb6e);
  margin-bottom: 10px;
}
.o2-dice-notice-body {
  font-size: 13px;
  line-height: 1.55;
  color: var(--tx-text, #d7d3ec);
}
.o2-dice-notice-body p { margin: 0 0 10px; }
.o2-dice-notice-btns {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
  flex-wrap: wrap;
  margin-top: 16px;
}
.o2-dice-notice-btn {
  font: inherit;
  font-size: 12px;
  padding: 8px 14px;
  border-radius: 7px;
  border: 1px solid var(--tx-line, #4b4483);
  background: transparent;
  color: var(--tx-text, #cfcbe8);
  cursor: pointer;
}
.o2-dice-notice-btn:hover { background: rgba(255, 255, 255, 0.05); }
.o2-dice-notice-btn.primary {
  border-color: var(--tx-gold, #fdcb6e);
  color: var(--tx-gold, #fdcb6e);
  font-weight: 700;
}

/* ══════════════════════════════════════════════════════════════════
   v5.1 — TrigammonX Academy: Saved Positions library, Save/Rename
   modal, Try Again, and first-visit Welcome popout. Local-only feature;
   styling matches the existing .academy-lab / .px-academy-confirm look.
   ══════════════════════════════════════════════════════════════════ */
.academy-modal {
  position: fixed; inset: 0; z-index: 6150;
  display: none; align-items: center; justify-content: center;
  background: rgba(4, 4, 12, 0.66); padding: 16px;
}
.academy-modal-card {
  max-width: 460px; width: 100%;
  background: #16182e; border: 1px solid #4b4483; border-radius: 12px;
  padding: 18px; box-shadow: 0 20px 60px rgba(0, 0, 0, 0.55);
  max-height: 88vh; overflow-y: auto;
}
.academy-modal-kicker {
  font-size: 11px; font-weight: 800; letter-spacing: 2px; color: #ffd700;
  text-transform: uppercase; margin-bottom: 4px;
}
.academy-modal-title { font-size: 15px; font-weight: 700; color: #efe9ff; margin-bottom: 10px; }
.academy-modal-sub { font-size: 11px; color: #9a94c0; margin-bottom: 12px; }
.academy-field-label {
  display: block; font-size: 11px; font-weight: 700; color: #b7b2d6;
  text-transform: uppercase; letter-spacing: 1px; margin: 10px 0 4px;
}
.academy-modal input[type="text"],
.academy-modal textarea {
  width: 100%; box-sizing: border-box; font: inherit; font-size: 13px;
  background: #10111f; border: 1px solid #3a3560; border-radius: 7px;
  color: #e7e3ff; padding: 8px 10px;
}
.academy-modal textarea { resize: vertical; min-height: 54px; }
.academy-modal-btns { display: flex; gap: 8px; justify-content: flex-end; flex-wrap: wrap; margin-top: 16px; }
.academy-modal-dup {
  display: none; margin-top: 10px; padding: 8px 10px;
  border: 1px solid #c9a13a; border-radius: 7px;
  background: rgba(201, 161, 58, 0.12); color: #f4d58c; font-size: 12px;
}

/* library list */
.academy-lib-empty { font-size: 12px; color: #9a94c0; line-height: 1.6; padding: 14px 4px; text-align: center; }
.academy-lib-row {
  display: flex; gap: 10px; align-items: flex-start;
  padding: 10px 0; border-bottom: 1px solid #2b2850;
}
.academy-lib-row:last-child { border-bottom: 0; }
.academy-lib-main { flex: 1 1 auto; min-width: 0; }
.academy-lib-name { font-size: 13px; font-weight: 700; color: #efe9ff; }
.academy-lib-meta { font-size: 10px; color: #9a94c0; margin-top: 2px; }
.academy-lib-note { font-size: 11px; color: #c4bfe4; margin-top: 4px; font-style: italic; word-break: break-word; }
.academy-lib-actions { display: flex; flex-direction: column; gap: 4px; flex-shrink: 0; }
.academy-lib-actions .academy-lab-btn { padding: 5px 10px; font-size: 11px; }
.academy-lib-del { border-color: #7a2e2e !important; color: #ff9d9d !important; }
.academy-lib-del:hover:not(:disabled) { background: #2e1416 !important; }

/* Try Again button sits alongside Edit Position in the practice bar */
.academy-practice-bar .academy-try-again-btn { margin-left: 6px; }

/* Welcome popout */
.academy-welcome-card { max-width: 480px; }
/* v5.1.1 — the new challenge-focused lead line under the title. */
.academy-welcome-lead { font-size: 13px; font-weight: 700; color: #efe9ff; margin: 8px 0 10px; }
.academy-welcome-list { margin: 4px 0 0 18px; padding: 0; font-size: 12px; line-height: 1.7; color: #d7d3ec; }
.academy-welcome-list li { margin: 6px 0; }
.academy-welcome-list li b { color: #c9c4ff; }
.academy-welcome-foot { font-size: 11px; color: #9a94c0; margin-top: 12px; }
.academy-welcome-note { font-size: 12px; color: #c4bfe4; margin: 10px 0 0; }

/* ══════════════════════════════════════════════════════════════════
   v5.1.1 — Hint / Suggested Play: dialog text + board-side markers.
   ══════════════════════════════════════════════════════════════════ */
.academy-hint-card { max-width: 440px; }
.academy-hint-step {
  background: var(--tx-bg-panel-2, #1b1d33);
  border: 1px solid #3a3560;
  border-radius: 10px;
  padding: 10px 12px;
  margin-bottom: 8px;
}
.academy-hint-step-strong { border-color: #a29bfe; box-shadow: 0 0 0 1px rgba(162,155,254,0.4); }
.academy-hint-step-label {
  font-size: 10px; text-transform: uppercase; letter-spacing: 1px;
  color: #ffd479; font-weight: 800; margin-bottom: 4px;
}
.academy-hint-step-arrow { font-size: 16px; font-weight: 700; color: #efe9ff; }
.academy-hint-step-note { font-size: 11px; color: #ff9d9d; margin-top: 4px; }
.academy-hint-nav { display: flex; gap: 8px; justify-content: space-between; margin-top: 6px; }
.academy-hint-nav .academy-lab-btn { flex: 1 1 auto; }
.academy-hint-disclaimer { font-size: 10px; color: #9a94c0; font-style: italic; margin-top: 10px; text-align: center; }

/* Board-side numbered source/destination markers — entirely separate
   from the real legal-move highlight system (.dest-hint/.legal-dest/
   .dest-ring-num are untouched). Positioned the same way as those
   (absolute, relative to #board-wrap, via bToS()). */
.academy-hint-marker {
  position: absolute;
  transform: translate(-50%, -50%);
  width: 26px; height: 26px;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font: 800 13px/1 inherit;
  pointer-events: none;
  z-index: 35;
}
.academy-hint-marker-strong {
  background: #ffd479;
  color: #16182e;
  box-shadow: 0 0 0 2px rgba(255,212,121,0.9), 0 0 14px rgba(255,212,121,0.6);
}
.academy-hint-marker-dim {
  background: rgba(255,212,121,0.28);
  color: rgba(22,24,46,0.85);
  box-shadow: 0 0 0 1px rgba(255,212,121,0.4);
}
.academy-hint-marker-to.academy-hint-marker-strong { background: #8fd8a7; box-shadow: 0 0 0 2px rgba(143,216,167,0.9), 0 0 14px rgba(143,216,167,0.6); }
.academy-hint-marker-to.academy-hint-marker-dim { background: rgba(143,216,167,0.28); box-shadow: 0 0 0 1px rgba(143,216,167,0.4); }

/* Bar / Borne Off tray glow for a suggested move touching the Bar or
   bearing off — same strong/dim distinction, no numbered badge (trays
   have no stable per-checker anchor point). */
.board-tray.academy-hint-tray-strong { box-shadow: 0 0 0 2px rgba(255,212,121,0.9), 0 0 14px rgba(255,212,121,0.6) !important; }
.board-tray.academy-hint-tray-dim { box-shadow: 0 0 0 1px rgba(255,212,121,0.4) !important; }

/* "What can I do here?" reopen link */
.academy-help-link {
  display: inline-block; margin-top: 6px;
  background: none; border: 0; padding: 0;
  font: inherit; font-size: 11px; color: #a29bfe;
  text-decoration: underline; cursor: pointer;
}
.academy-help-link:hover { color: #c9c4ff; }

@media (max-width: 520px) {
  .academy-lib-row { flex-wrap: wrap; }
  .academy-lib-actions { flex-direction: row; width: 100%; }
  .academy-lib-actions .academy-lab-btn { flex: 1 1 auto; }
}
