/* 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;
}

.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; }
}

/* ── 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;
}
/* ════════════════════════════════════════════════════════════════════
   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 {
  font-size: 9px;
  letter-spacing: 3px;
  margin-top: 3px;
}
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;
}
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); }

/* 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 medallion — large and prominent, per spec §2 ── */
.goc-medallion { text-align: center; }
.goc-medallion-ring {
  width: 110px; height: 110px; margin: 0 auto;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: radial-gradient(circle at 35% 30%, #f0cf8c, #d8b46a 55%, #9a7a3c 100%);
  border: 3px solid var(--tx-gold-bright, #f0cf8c);
  box-shadow:
    0 0 0 3px rgba(5,7,13,0.9),
    0 0 0 6px var(--medallion-accent, var(--tx-gold, #d8b46a)),
    0 6px 18px rgba(0,0,0,0.5);
}
.goc-medallion-trophy { font-size: 48px; line-height: 1; filter: drop-shadow(0 2px 2px rgba(0,0,0,0.35)); }
.goc-medallion-label {
  margin-top: 8px; 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 ── */
.goc-brand {
  text-align: center; font-size: 12px; font-weight: bold; letter-spacing: 3.5px;
  color: var(--tx-gold, #d8b46a); text-transform: uppercase;
}
.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; }

/* ── 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); }
}
@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; }
  .goc-medallion-ring { width: 88px; height: 88px; }
  .goc-medallion-trophy { font-size: 38px; }
  .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; }
}
@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; }
}
@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); }
