/* ════════════════════════════════════════════════════════════════════════
 * moyako-shell.css — canonical gameplay-shell CSS.
 * ────────────────────────────────────────────────────────────────────────
 * Single source of truth for the rules that today are DUPLICATED INLINE
 * in every game's <style> block. Extracted 2026-05-20 per the cross-game
 * alignment audit (dim 2 + the "what we call shared isn't truly shared"
 * finding). Sudoku's `.number-pad--triple` recipe is the canonical
 * source; this file lifts it intact.
 *
 * Coverage (Round 1 — verbatim duplicates, zero-risk):
 *   • Body layout (flex column + min-height 100vh) + universal reset
 *   • `.number-pad--triple` triple-split recipe (info | keys | numbers)
 *   • `.board-lower-*` stat + diff-pill + matchup typography
 *   • `.btn` / `.btn-primary` / `.btn-secondary` base
 *   • `.control-btn-badge` (corner notification dot)
 *   • `.hidden { display: none !important }`
 *   • `@supports (height: 100dvh)` viewport lock
 *   • `@keyframes slideUp` (overlay-content entry animation)
 *
 * Coverage (Round 2 — to extract next):
 *   • `.overlay` + `.overlay-content` + `.overlay-{title,subtitle,stats,*}`
 *   • `.board-lower` / `.board-lower-actions` / `.board-lower-action-btn`
 *     + `--primary` + `--rewarded` + `--danger` modifiers
 *   • Mobile drawer-hide + stats-panel-inline (currently scoped per game
 *     via `body[data-page-brand-label="<X>"]`)
 *
 * Load order: AFTER moyako-layout.css + moyako-components.css.
 * Specificity matches inline `<style>` rules in the games; identical
 * inline blocks remain in place during the migration window — the
 * later-in-document inline rules win the cascade so existing games
 * behave identically. Per-game cleanup deletes the now-redundant
 * inline blocks one game at a time (separate commits, bisectable).
 *
 * The template (_template.html) loads this file and ONLY this file for
 * shell CSS — no inline shell rules. New games copying the template
 * inherit the canonical shell for free.
 * ════════════════════════════════════════════════════════════════════════ */


/* ─── Universal reset + body shell ───────────────────────────────────── */

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html, body {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
}

body {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

/* Mobile viewport lock — sticks .page to the dvh-aware viewport so cap
 * shells don't get the address-bar collapse jitter. */
@supports (height: 100dvh) {
  html, body {
    height: 100dvh;
    max-height: 100dvh;
  }
}


/* ─── Shared utility classes ─────────────────────────────────────────── */

.hidden { display: none !important; }


/* ─── Standard buttons (`.btn` family) ───────────────────────────────── */

.btn {
  padding: 0 18px;
  min-height: var(--tap-target-md, 44px);
  border-radius: 8px;
  font-weight: 700;
  font-size: 14px;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  border: 0;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  transition: filter 0.12s ease, transform 0.12s ease;
}
.btn:hover { filter: brightness(1.1); }
.btn:active { transform: translateY(1px); }

.btn-primary {
  background: linear-gradient(180deg, #4CAF50 0%, #43A047 100%);
  color: #FFFFFF;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.20),
    0 1px 2px rgba(0, 0, 0, 0.25);
}

.btn-secondary {
  background: var(--card-bg, rgba(255, 255, 255, 0.08));
  color: var(--text-light, #ECEFF4);
  border: 1px solid rgba(255, 255, 255, 0.14);
}

.btn-tertiary {
  background: transparent;
  color: var(--text-muted, #B0B0B0);
  border: 1px solid rgba(255, 255, 255, 0.10);
}


/* ─── Swap button — flip board ↔ controls columns ────────────────────
 * Slim vertical rail that sits between the board and controls panels
 * on landscape (>= 600px). Same indigo metallic gradient as
 * .board-lower-matchup + .pane-left-head so the gameplay shell reads
 * as one brand surface. Sudoku has a `body.sudoku-legacy-rail`-gated
 * variant inline; this is the canonical version every game (+ the
 * template) inherits. Authors don't need to wire anything — the click
 * handler in each game toggles `body.moyako-swapped`. */
.moyako-swap-btn,
.sudoku-swap-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  min-width: 18px;
  align-self: stretch;
  padding: 0;
  background: linear-gradient(135deg, #3F4878 0%, #1F2A5C 100%);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: 6px;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.10),
    0 2px 6px rgba(0, 0, 0, 0.20);
  color: #FFFFFF;
  cursor: pointer;
  touch-action: manipulation;
  font-size: 0;
  transition: transform 0.12s ease, filter 0.12s ease;
}
/* Wooden — swap button = walnut + brass icon (Owner 2026-06-05), matching the
   maze disc / card backs instead of the navy Core default. */
[data-theme="wooden"] .moyako-swap-btn,
[data-theme="wooden"] .sudoku-swap-btn {
  background: linear-gradient(180deg, #3A220F 0%, #241208 100%);
  border: 1px solid #5A3A1A;
  color: #EBC974;
}
.moyako-swap-btn:hover,
.sudoku-swap-btn:hover { filter: brightness(1.1); }
.moyako-swap-btn:active,
.sudoku-swap-btn:active { transform: translateY(1px); }
.moyako-swap-btn::before,
.sudoku-swap-btn::before {
  content: "‹";
  display: block;
  font-size: 16px;
  line-height: 1;
  font-weight: 900;
  color: #FFFFFF;
  text-shadow: 0 1px 1px rgba(0, 0, 0, 0.30);
}
/* v449c (2026-05-21): both .moyako-swapped AND .sudoku-swapped body
 * classes flip the arrow on EITHER button class. Was only the same-name
 * pairing (moyako↔moyako, sudoku↔sudoku) — but most games use the
 * .sudoku-swap-btn button while toggling body.moyako-swapped (because
 * the engagement.js handler writes the moyako class globally). Result:
 * arrow stayed `‹` after swap. Per Owner "when control panel on the
 * left the arrow should show the right". */
body.moyako-swapped .moyako-swap-btn::before,
body.moyako-swapped .sudoku-swap-btn::before,
body.sudoku-swapped .moyako-swap-btn::before,
body.sudoku-swapped .sudoku-swap-btn::before {
  content: "›";
}


/* ─── Notification badge on control buttons ──────────────────────────── */

.control-btn-badge {
  position: absolute;
  top: -4px;
  right: -4px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: #4CAF50;
  color: #FFFFFF;
  font-size: 9px;
  font-weight: 800;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.4);
}


/* ─── Overlay entry animation ───────────────────────────────────────── */

@keyframes slideUp {
  from { transform: translateY(20px); opacity: 0; }
  to   { transform: translateY(0);    opacity: 1; }
}


/* ════════════════════════════════════════════════════════════════════════
 * `.number-pad--triple` — the canonical 3-column control row.
 *
 * LEFT  = info column     (matchup + diff-pill + time/errors/score stats)
 * MID   = keys column     (control buttons stacked vertically)
 * RIGHT = numbers column  (3×3 numpad / d-pad / per-game grid)
 *
 * Lifted verbatim from sudoku.html lines 280–443 (the comment in that
 * file says "the de-facto canonical recipe"). Memory uses a slightly
 * different info-column flex ratio (1.1 vs 2) — keep the sudoku default
 * here; memory's local override still wins via document order until
 * memory's inline block is cleaned up.
 * ════════════════════════════════════════════════════════════════════════ */

/* Desktop-only — mobile (@media max-width: 1024px in moyako-layout.css)
 * sets `display: contents` to flatten children into .moyako-board-center's
 * grid so the board / info / controls / actions stack vertically. The
 * @media min-width here scopes the flex-row layout to desktop so it
 * doesn't override the mobile flatten. */
@media (min-width: 1025px) {
  .number-pad--triple {
    display: flex;
    flex-direction: row;
    gap: 8px;
    align-items: stretch;
    width: 100%;
    height: 100%;
    min-height: 0;
  }
}

/* .board-upper flex-grows to fill available vertical space inside
 * .moyako-board-center on both desktop and mobile. The board plug-in
 * (or real board canvas) sits inside and gets the full surface — no
 * tiny-box rendering. */
.board-upper {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  justify-content: stretch;
}

.number-pad--triple > div {
  background: linear-gradient(160deg, #3A4258 0%, #1F2433 100%);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 10px;
  padding: 6px;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.16),
    inset 0 -1px 0 rgba(0, 0, 0, 0.30),
    0 2px 6px rgba(0, 0, 0, 0.25);
  min-height: 0;
  overflow: hidden;
}

[data-theme="light"] .number-pad--triple > div {
  background: linear-gradient(160deg, #F4F6FB 0%, #D7DEEC 100%);
  border: 1px solid rgba(15, 23, 42, 0.14);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.85),
    inset 0 -1px 0 rgba(15, 23, 42, 0.08),
    0 2px 6px rgba(15, 23, 42, 0.12);
}

/* ── Info column (left) ───────────────────────────────────────────── */

.number-pad--triple .number-pad-info {
  display: flex;
  flex-direction: column;
  gap: 4px;
  flex: 2 1 0;
  min-width: 0;
  min-height: 0;
  align-items: stretch;
  justify-content: stretch;
}

.number-pad--triple .number-pad-info .board-lower-matchup {
  align-self: stretch;
  justify-content: center;
  flex: 1 1 0;
  min-width: 0;
  min-height: 0;
  padding: 2px 6px;
  font-size: 9px;
  line-height: 1.1;
}

.number-pad--triple .number-pad-info .board-lower-stats-pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 4px;
  flex: 1.2 1 0;
  min-height: 0;
}

.number-pad--triple .number-pad-info .board-lower-stats-pair .board-lower-diff-pill {
  align-self: stretch;
  justify-content: center;
  width: 100%;
  min-width: 0;
  min-height: 0;
  padding: 1px 6px;
  font-size: 9px;
  line-height: 1;
  letter-spacing: 0.4px;
  border-radius: 8px;
}

[data-moyako-v2] .page .number-pad--triple .number-pad-info .board-lower-stats-pair .board-lower-stat {
  display: flex;
  flex-direction: column !important;
  align-items: center;
  justify-content: center;
  min-width: 0;
  min-height: 0;
  padding: 2px 6px;
  width: 100%;
  border-radius: 8px;
  gap: 0;
}
[data-moyako-v2] .page .number-pad--triple .number-pad-info .board-lower-stats-pair .board-lower-stat-label {
  font-size: 9px;
  letter-spacing: 0.5px;
  line-height: 1.1;
}
[data-moyako-v2] .page .number-pad--triple .number-pad-info .board-lower-stats-pair .board-lower-stat-value {
  font-size: 13px;
  font-weight: 800;
  line-height: 1.15;
}

/* Hero stat — bigger font, row layout for prominence (Time goes here). */
[data-moyako-v2] .page .number-pad--triple .number-pad-info .board-lower-stats-pair .board-lower-stat--hero {
  flex-direction: row !important;
  justify-content: space-between;
  align-items: center;
  padding: 3px 8px;
  gap: 6px;
  border-radius: 10px;
}
[data-moyako-v2] .page .number-pad--triple .number-pad-info .board-lower-stats-pair .board-lower-stat--hero .board-lower-stat-label {
  font-size: 9px;
  flex: 0 0 auto;
}
[data-moyako-v2] .page .number-pad--triple .number-pad-info .board-lower-stats-pair .board-lower-stat--hero .board-lower-stat-value {
  font-size: 16px;
  font-weight: 800;
  line-height: 1;
  flex: 0 0 auto;
}

/* ── Keys column (middle) ─────────────────────────────────────────── */

.number-pad--triple .number-pad-keys {
  display: flex;
  flex-direction: column;
  flex: 1 1 0;
  min-width: 0;
  min-height: 0;
  justify-content: space-between;
  align-items: stretch;
}

.number-pad--triple .number-pad-keys .control-btn {
  flex: 0 0 auto;
  width: 100%;
  aspect-ratio: 5 / 1;
  min-height: 0;
  padding: 0 8px;
  font-size: 11px;
  border-radius: 8px;
}

/* ── Numbers column (right) ───────────────────────────────────────── */

.number-pad--triple .number-pad-numbers {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 1fr;
  gap: 4px;
  flex: 3 1 0;
  min-width: 0;
  min-height: 0;
}

.number-pad--triple .number-pad-numbers .number-btn {
  max-width: none;
  width: 100%;
  height: 100%;
  min-height: 0;
  aspect-ratio: auto;
  padding: 0;
  border-radius: 8px;
  font-size: clamp(12px, 1.6vw, 16px);
}

/* ════════════════════════════════════════════════════════════════════════
 * §RESULTS-PANE — Game-end SCREEN (not overlay)
 * ════════════════════════════════════════════════════════════════════════
 * Sibling of `.difficulty-pane`. Sandwiched between TopBar + BottomNav,
 * never covers gameplay. Body data-state machine controls visibility:
 *   data-state="picker"  → #pickerState  visible, others hidden
 *   data-state="play"    → #playState    visible, others hidden
 *   data-state="results" → #resultsState visible, others hidden
 *
 * Markup contract (every game embeds this empty mount target):
 *   <section class="results-pane" data-state="results" id="resultsState"
 *            data-result="win|lose|timeout|draw|level" hidden>
 *   </section>
 *
 * The shared component `MoyakoComponents.GameEndScreen.mount(opts, host)`
 * renders into the section. data-result drives outcome theming (hero
 * icon, accent colour, copy variant) without changing the layout.
 *
 * Owned by ADR docs/adr/2026-05-game-end-screen-v2.md.
 * Sprint A (2026-05-21): canonical block landed.
 * ════════════════════════════════════════════════════════════════════════ */

/* Base — pane is a 2-column flex row (left celebration + right action),
 * exactly like .difficulty-pane. Default hidden via [hidden] attribute;
 * shown by the state machine.
 *
 * v449e (2026-05-21): max-width cap so the cards don't stretch
 * full-viewport on desktop (was reading as empty wide panes per Owner
 * "container shouldn't stretch that much, align with picker screen").
 * 760 px matches the picker's `.overlay-content--compact` desktop max
 * (§3767 max-width: 720 + padding). Auto-centered horizontally;
 * vertically aligned to the top so chrome stays compact. */
/* v449w (2026-05-21): .results-pane base/landscape/portrait rules now
 * sourced from the canonical `.difficulty-pane` group in moyako-
 * layout.css §1977 / §2015 / §2070. One source of truth — picker +
 * results consume the same grid/gap/padding/responsive variants.
 * Per Owner "don't we have a standard shared rule for them, are they
 * not consuming it?". Only results-specific layout extras stay here. */
/* v450f (2026-05-22): softer light-mode app background per Owner
 * "page background looks close to pure white ... use #F4F7FB so the
 * cards feel integrated and less like they float on a blank canvas".
 * Scoped to v2 game pages; loaded last so it wins over the white base. */
html[data-theme="light"] body[data-moyako-v2],
html[data-theme="light"] body[data-moyako-v2] .page {
  background-color: #F4F7FB !important;
}

.results-pane[hidden] { display: none; }

/* v455: View peek pill — a floating "Results" button shown while the player
 * peeks at the board via View (opt-in). Tapping it re-shows the results
 * screen. Lives on <body> (position:fixed) so it survives the state machine
 * hiding #resultsState. */
.results-peek-pill {
  position: fixed;
  left: 50%;
  bottom: calc(env(safe-area-inset-bottom, 0px) + var(--footer-h, 56px) + 16px);
  transform: translateX(-50%);
  z-index: 1300;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 10px 18px;
  border-radius: 999px;
  border: 1px solid var(--border-strong, #334155);
  background: var(--bg-surface, #1E293B);
  color: var(--text-primary, #F8FAFC);
  font-size: 14px;
  font-weight: 700;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.4);
  cursor: pointer;
}
.results-peek-pill[hidden] { display: none; }

/* v503 (2026-06-05) — Owner: centre the game-end cards (was top-anchored by
 * v450f "content starts too low"). With the taller framed cards + the portrait
 * cap-nav reserve below, centring now reads balanced like the picker / sign-in.
 * `safe center` falls back to start if the content ever overflows, so the top
 * (celebration) card is never clipped on a short viewport. */
@media (orientation: portrait) {
  body[data-moyako-v2][data-state="results"] .results-pane {
    align-content: safe center;
  }
  /* Portrait cap-nav clearance — the reserve at moyako-layout.css §2141 sits
   * inside the landscape media query only, so a tall 2nd (action) card ran
   * under the fixed cap-nav in portrait. Mirror it here for results. */
  body.has-cap-nav[data-moyako-v2][data-state="results"] .results-pane {
    padding-bottom: calc(var(--space-3) + 56px + env(safe-area-inset-bottom, 0px)) !important;
  }
}

/* v519 (2026-06-05) — game-end LANDSCAPE spacing (Owner walk-through): edge
 * margins set equal to the 14px between-container gap (uniform framing), and the
 * sound/settings rail pinned 1px below the card top. NB: in the cap-shell the
 * HEADER has no settings icon (the sys-info area occupies that corner), so this
 * action-card rail is the ONLY settings access on game-end — it must stay. */
@media (orientation: landscape) {
  body[data-moyako-v2][data-state="results"] .results-pane {
    padding: 14px !important;
  }
  body[data-moyako-v2][data-state="results"] .results-card--action .cap-settings-anchor {
    top: 1px !important;
  }
}

/* Two top-level cards inside the pane — same recipe as the picker's
 * .game-info-card + .difficulty-card. Inherit surface tokens from
 * moyako-components.css's .difficulty-card rule (no duplication). */
/* v449p (2026-05-21): .results-card surface tokens (background,
 * border, padding, radius, gap, overflow) are now sourced from the
 * canonical picker-container rule at moyako-layout.css §2088 (the
 * same selector group as .game-info-card + .difficulty-card). One
 * source of truth across picker + results screens. Only the layout
 * extras unique to results live here. */

/* Card identifiers — left (celebration) + right (action). */
.results-pane .results-card--celebration {
  /* v449i (2026-05-21): celebration content centered both axes per
   * Owner "left container object not centralized, align vertically
   * and horizontally". */
  align-items: center;
  justify-content: center;
  text-align: center;
}
.results-pane .results-card--action {
  /* Right card hosts sound/settings rail per global landscape pattern.
   * `.cap-settings-anchor` already absolutes itself top-right via the
   * shared rule at moyako-layout.css §6963; same hook works here.
   *
   * v449g (2026-05-21): centre content vertically + tighter button
   * group per Owner "centrally align the right container, view and
   * close button group close to each other". */
  justify-content: center;
}
/* v449g (2026-05-21): action card title "RECAP" header — more
 * dominant per Owner. */
.results-pane .results-card-title {
  font-size: 14px;
  font-weight: 800;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  opacity: 0.95;
  text-align: left;
  padding: 4px 2px 6px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.12);
  line-height: 1.4;
}
[data-theme="light"] .results-pane .results-card-title {
  border-bottom-color: rgba(15, 23, 42, 0.10);
}

/* v449f (2026-05-21): desktop responsive scale-up. Per Owner "for
 * desktop object size can be increased retrospectively to a max
 * level". Mobile sizes stay; desktop bumps hero/title/score/
 * stats/buttons all proportionally. Max cap at 960 px container. */
@media (min-width: 1025px) {
  .results-pane {
    max-width: 920px;
    gap: 16px;
    padding: 12px;
  }
  .results-pane .results-card {
    padding: 18px 20px;
    gap: 14px;
  }
  .results-pane .results-hero-icon { font-size: 52px; }
  .results-pane .results-hero-logo { width: 72px; height: 72px; }
  .results-pane .results-panda { width: 80px; height: 80px; }
  .results-pane .results-title { font-size: 28px; }
  .results-pane .results-subtitle { font-size: 16px; }
  .results-pane .results-badges { gap: 16px; }
  .results-pane .results-badge { font-size: 15px; padding: 6px 14px; }
  .results-pane .results-card-title { font-size: 13px; letter-spacing: 1.4px; }
  .results-pane .results-score-cell { padding: 12px 14px; }
  .results-pane .results-score-label { font-size: 13px; }
  .results-pane .results-score-value { font-size: 40px; }
  .results-pane .results-score-delta { font-size: 13px; }
  .results-pane .results-top5-cell { padding: 12px 14px; }
  .results-pane .results-top5-title { font-size: 13px; }
  .results-pane .results-top5-list { font-size: 14px; gap: 4px; }
  .results-pane .results-stat { padding: 8px 10px; }
  .results-pane .results-stat-label { font-size: 11px; }
  .results-pane .results-stat-value { font-size: 20px; }
  .results-pane .results-btn { font-size: 14px; min-height: 44px; padding: 10px 12px; gap: 6px; }
}

/* Left card content stack.
 * v449b (2026-05-21 Sprint A fix): game logo + panda side-by-side in
 * a single horizontal row per Owner — was stacked vertically. */
.results-pane .results-hero-row {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: center;
  gap: 16px;
  width: 100%;
}
/* v450f (2026-05-22): larger, more celebratory hero per Owner. */
.results-pane .results-hero-icon {
  font-size: 52px;
  line-height: 1;
  flex: 0 0 auto;
}
.results-pane .results-panda {
  width: 68px;
  height: 68px;
  flex: 0 0 auto;
}
.results-pane .results-panda img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}
/* v455c: game-logo variant of the hero icon — an <img> (assets/games/<slug>.png)
 * sized to sit beside the panda. Per Owner "near the panda, display the game
 * logo". */
.results-pane .results-hero-logo {
  width: 60px;
  height: 60px;
  flex: 0 0 auto;
}
.results-pane .results-hero-logo img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}
.results-pane .results-title {
  font-size: 24px;
  font-weight: 900;
  margin: 0;
  line-height: 1.1;
  letter-spacing: -0.01em;
}
.results-pane .results-subtitle {
  font-size: 14px;
  line-height: 1.3;
  opacity: 0.85;
  margin: 0;
  max-width: 32ch;
}
.results-pane .results-badges {
  display: flex;
  gap: 12px;
  justify-content: center;
  align-items: center;
  flex-wrap: wrap;
}
.results-pane .results-badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 14px;
  font-weight: 700;
  padding: 6px 14px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.12);
}
[data-theme="light"] .results-pane .results-badge {
  background: #F1F5F9;
  border-color: #D7E0EA;
  color: #1F2937;
}

/* v449h (2026-05-21): grouped containers per Owner — score+top5+stats
 * share one stats-block; both button rows share one buttons-block. */
.results-pane .results-stats-block {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 8px;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: 10px;
}
.results-pane .results-buttons-block {
  display: flex;
  flex-direction: column;
  gap: 0;
  /* v449l (2026-05-21): removed margin-top: auto so the action card's
   * justify-content: center actually centres the content vertically
   * (previously the auto-margin pinned buttons to the bottom, leaving
   * the stats-block top-aligned). Per Owner "centralized vertically". */
}
[data-theme="light"] .results-pane .results-stats-block {
  background: rgba(15, 23, 42, 0.03);
  border-color: rgba(15, 23, 42, 0.08);
}

/* Right card row 1 — Score + TOP 5 (2 sub-cells).
 * v450c (2026-05-22): TOP 5 needs room for its 5-entry list, which the
 * compact SCORE cell didn't leave. Give the row a min-height that fits
 * the title + 5 ranked rows, and a bit more width to the TOP 5 column.
 * Per Owner "leave space for top 5 entry". */
.results-pane .results-row-1 {
  display: grid;
  grid-template-columns: 0.85fr 1.15fr;
  gap: 8px;
  min-height: 132px;   /* v450f: room for the larger 13px TOP 5 rows */
}
/* v449g (2026-05-21): score + top5 share the SAME subtle green tint
 * per Owner "align score background colors to top 5". Cohesive look;
 * neither tile overwhelms the other. */
.results-pane .results-score-cell,
.results-pane .results-top5-cell {
  background: linear-gradient(160deg, rgba(76, 175, 80, 0.18) 0%, rgba(46, 125, 50, 0.18) 100%);
  border: 1px solid rgba(76, 175, 80, 0.32);
  border-radius: 10px;
  padding: 8px 10px;
  display: flex;
  flex-direction: column;
  min-height: 0;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.10),
    inset 0 -1px 0 rgba(0, 0, 0, 0.20),
    0 2px 6px rgba(0, 0, 0, 0.20);
}
.results-pane .results-score-cell {
  align-items: center;
  justify-content: center;
}
[data-theme="light"] .results-pane .results-score-cell,
[data-theme="light"] .results-pane .results-top5-cell {
  background: linear-gradient(160deg, rgba(76, 175, 80, 0.12) 0%, rgba(46, 125, 50, 0.12) 100%);
  border-color: rgba(46, 125, 50, 0.28);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.65),
    inset 0 -1px 0 rgba(15, 23, 42, 0.06),
    0 2px 6px rgba(15, 23, 42, 0.08);
}
[data-theme="light"] .results-pane .results-top5-cell {
  background: linear-gradient(160deg, rgba(76, 175, 80, 0.12) 0%, rgba(46, 125, 50, 0.12) 100%);
  border-color: rgba(46, 125, 50, 0.28);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.65),
    inset 0 -1px 0 rgba(15, 23, 42, 0.06),
    0 2px 6px rgba(15, 23, 42, 0.08);
}
.results-pane .results-score-cell {
  align-items: center;
  justify-content: center;
}
/* v449g (2026-05-21): titles more dominant per Owner "make the
 * titles a bit more dominant and increase the height a bit to be
 * more dominant". Bigger, bolder, higher contrast, more line-height. */
.results-pane .results-score-label {
  font-size: 13px;
  font-weight: 800;
  letter-spacing: normal;
  text-transform: none;   /* v455: "Score" not "SCORE" — sentence case per Owner */
  opacity: 0.9;
  line-height: 1.5;
  margin-bottom: 2px;
}
.results-pane .results-score-value {
  font-size: 28px;
  font-weight: 800;
  line-height: 1;
}
.results-pane .results-score-delta {
  font-size: 11px;
  opacity: 0.75;
  margin-top: 2px;
}
.results-pane .results-top5-title {
  font-size: 13px;
  font-weight: 800;
  letter-spacing: 0.8px;
  text-transform: uppercase;
  opacity: 0.9;
  line-height: 1.5;
  text-align: center;
  margin-bottom: 6px;
}
.results-pane .results-top5-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
  /* v450f (2026-05-22): bigger leaderboard text for mobile readability
   * per Owner "ranking rows are tiny". */
  font-size: 13px;
  line-height: 1.4;
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}
/* Mobile landscape — the end-screen action card is height-squeezed, so
   compact the Score + TOP 5 block to avoid an internal scrollbar. TOP 5
   becomes 2 columns and the score shrinks; scoped to phone landscape
   (max-height 480) — portrait / tablet / desktop keep the 1-column layout. */
@media (orientation: landscape) and (max-height: 480px) {
  .results-pane .results-top5-list {
    display: grid; grid-auto-flow: column; grid-template-rows: repeat(3, auto);
    grid-template-columns: 1fr 1fr; column-gap: 12px; row-gap: 2px; overflow: visible;
  }
  .results-pane .results-score-value { font-size: 22px; }
  .results-pane .results-score-cell,
  .results-pane .results-top5-cell { padding: 6px 10px; }
  .results-pane .results-top5-title { margin-bottom: 2px; }
  /* Trim the sound/settings rail reserve + tighten the action buttons so
     the card content clears the card height without an internal scrollbar. */
  [data-moyako-v2] .page .results-pane .results-card--action {
    padding-top: 37px; padding-bottom: 4px;
    overflow: visible;              /* remove the internal scrollbar — content compacted to fit */
  }
  /* lift the sound/settings rail up — less dead margin above the icons */
  .results-pane .results-card--action .cap-settings-anchor { top: 4px; }
  .results-pane .results-buttons-block { gap: 4px; }
  .results-pane .results-btn { min-height: 24px; font-size: 12px; padding: 2px 8px; gap: 4px; }
}
/* v451 (2026-05-22): TOP 5 skeleton — 5 shimmer rows while scores load,
 * per Owner "replace Top 5 loading text with skeleton". */
.results-pane .results-top5-list.is-loading { gap: 7px; justify-content: center; }
.results-pane .results-top5-skel-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.results-pane .results-top5-skel-bar {
  height: 9px;
  border-radius: 4px;
  background: linear-gradient(90deg,
    rgba(255, 255, 255, 0.06) 25%,
    rgba(255, 255, 255, 0.16) 37%,
    rgba(255, 255, 255, 0.06) 63%);
  background-size: 280% 100%;
  animation: resultsTop5Shimmer 1.3s ease-in-out infinite;
}
.results-pane .results-top5-skel-bar--name  { flex: 1 1 auto; max-width: 70%; }
.results-pane .results-top5-skel-bar--score { width: 22px; flex: none; }
@keyframes resultsTop5Shimmer {
  0%   { background-position: 100% 0; }
  100% { background-position: -180% 0; }
}
[data-theme="light"] .results-pane .results-top5-skel-bar {
  background: linear-gradient(90deg,
    rgba(15, 23, 42, 0.06) 25%,
    rgba(15, 23, 42, 0.13) 37%,
    rgba(15, 23, 42, 0.06) 63%);
  background-size: 280% 100%;
}

/* each ranked row — rank · name (fills) · score (right). */
.results-pane .results-top5-row {
  display: flex;
  align-items: baseline;
  gap: 6px;
  padding: 1px 0;
}
.results-pane .results-top5-rank { opacity: 0.55; min-width: 14px; font-weight: 700; }
.results-pane .results-top5-name {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 600;
}
.results-pane .results-top5-score { font-weight: 800; }
/* "You" — strong player-achievement highlight. */
.results-pane .results-top5-row--you {
  color: #34C759;
  font-weight: 800;
}
.results-pane .results-top5-row--you .results-top5-rank,
.results-pane .results-top5-row--you .results-top5-score { opacity: 1; color: #34C759; }
[data-theme="light"] .results-pane .results-top5-row--you,
[data-theme="light"] .results-pane .results-top5-row--you .results-top5-rank,
[data-theme="light"] .results-pane .results-top5-row--you .results-top5-score { color: #16A34A; }

/* Right card row 2 — stats (TIME / MOVES / LEVELS), moved from
 * left container per Sprint A Q2.a. */
/* ════════════════════════════════════════════════════════════════
 * v450 (2026-05-22) Owner redesign — premium dashboard hierarchy.
 * Reduced palette: subtle elevated stat tiles (no saturated
 * gradients), ONE green CTA (Next), ONE blue secondary (Share), the
 * rest neutral. Red reserved for genuine error metrics only.
 *   Background #0F172A · Card #1B2436 · Elevated #202B3F
 *   Border #334155 · Text #F8FAFC / #AAB6C8
 *   Success/Next #34C759 · Share #2F80ED · Reward/Level #F5A524
 *   Error #EF4444
 * ════════════════════════════════════════════════════════════════ */

/* Stats row — 3 tiles: Time / Moves / Level. Semantic colour per the
 * Owner design system (v450d 2026-05-22): every colour has a job —
 *   Time  = blue   (neutral performance metric)
 *   Moves = conditional: good→green (default) · average→amber · bad→red
 *   Level = orange (progress indicator)
 *   Score = green  (achievement — used if a score tile is shown)
 * Dark = saturated fills; light = soft tinted versions. A low Moves
 * count is GOOD, so it stays green unless the game flags quality. */
.results-pane .results-row-2 {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
}
.results-pane .results-stat {
  background: #202B3F;
  border: 1px solid transparent;
  border-radius: 12px;
  padding: 8px 10px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 0;
  color: #FFFFFF;
}
/* Dark — neutral tile + coloured VALUE (matches the gameplay scoreboard + the
 * light-theme treatment). v459b: dropped the saturated per-stat backgrounds so
 * Time/Moves/Level no longer fill with colour while un-accented stats
 * (Tries/Words/Captures) stay neutral — Owner "align Time with the others, no
 * blue background in dark theme". All tiles keep the base #202B3F fill. */
.results-pane .results-stat[data-stat="time"]    .results-stat-value { color: #60A5FA; }
.results-pane .results-stat[data-stat="moves"]   .results-stat-value { color: #4ADE80; }
.results-pane .results-stat[data-stat="moves"][data-quality="bad"] .results-stat-value { color: #F87171; }
.results-pane .results-stat[data-stat="errors"]  .results-stat-value { color: #F87171; }
.results-pane .results-stat[data-stat="level"]   .results-stat-value,
.results-pane .results-stat[data-stat="levels"]  .results-stat-value { color: #FBBF24; }
.results-pane .results-stat[data-stat="score"]   .results-stat-value { color: #4ADE80; }
.results-pane .results-stat-label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: normal;
  text-transform: none;   /* v455: sentence case per Owner "Time, Error, Score, Level only initials capital" */
  color: rgba(255, 255, 255, 0.85);
  line-height: 1.4;
}
.results-pane .results-stat-value {
  font-size: 18px;
  font-weight: 800;
  line-height: 1.2;
  color: #FFFFFF;
}
/* moves "average" quality → amber value on the neutral tile (dark theme). */
.results-pane .results-stat[data-stat="moves"][data-quality="average"] .results-stat-value { color: #FBBF24; }

/* Light — soft tinted fills with dark-on-tint text. */
[data-theme="light"] .results-pane .results-stat { background: #F1F5F9; color: #1F2937; }
/* Neutral tiles with no semantic accent (e.g. backgammon "Borne") kept the
 * dark-theme white label/value text, which is invisible on the light #F1F5F9
 * fill. Force dark text in light mode; the accented tiles below override with
 * their own colours (higher specificity). */
[data-theme="light"] .results-pane .results-stat-label,
[data-theme="light"] .results-pane .results-stat-value { color: #1F2937; }
[data-theme="light"] .results-pane .results-stat[data-stat="time"]   { background: #DBEAFE; }
[data-theme="light"] .results-pane .results-stat[data-stat="time"]   .results-stat-label,
[data-theme="light"] .results-pane .results-stat[data-stat="time"]   .results-stat-value { color: #1D4ED8; }
[data-theme="light"] .results-pane .results-stat[data-stat="moves"]  { background: #DCFCE7; }
[data-theme="light"] .results-pane .results-stat[data-stat="moves"]  .results-stat-label,
[data-theme="light"] .results-pane .results-stat[data-stat="moves"]  .results-stat-value { color: #15803D; }
[data-theme="light"] .results-pane .results-stat[data-stat="moves"][data-quality="average"] { background: #FEF3C7; }
[data-theme="light"] .results-pane .results-stat[data-stat="moves"][data-quality="average"] .results-stat-label,
[data-theme="light"] .results-pane .results-stat[data-stat="moves"][data-quality="average"] .results-stat-value { color: #B45309; }
[data-theme="light"] .results-pane .results-stat[data-stat="moves"][data-quality="bad"] { background: #FEE2E2; }
[data-theme="light"] .results-pane .results-stat[data-stat="moves"][data-quality="bad"] .results-stat-label,
[data-theme="light"] .results-pane .results-stat[data-stat="moves"][data-quality="bad"] .results-stat-value { color: #B91C1C; }
[data-theme="light"] .results-pane .results-stat[data-stat="errors"] { background: #FEE2E2; }
[data-theme="light"] .results-pane .results-stat[data-stat="errors"] .results-stat-label,
[data-theme="light"] .results-pane .results-stat[data-stat="errors"] .results-stat-value { color: #B91C1C; }
[data-theme="light"] .results-pane .results-stat[data-stat="level"],
[data-theme="light"] .results-pane .results-stat[data-stat="levels"] { background: #FFEDD5; }
[data-theme="light"] .results-pane .results-stat[data-stat="level"]  .results-stat-label,
[data-theme="light"] .results-pane .results-stat[data-stat="level"]  .results-stat-value,
[data-theme="light"] .results-pane .results-stat[data-stat="levels"] .results-stat-label,
[data-theme="light"] .results-pane .results-stat[data-stat="levels"] .results-stat-value { color: #7C2D12; }  /* v454: was #C2410C (~4.5:1 amber-on-cream, the small "Level" label read poorly) → #7C2D12 (~8:1) per Owner "level text not readable in light" */
[data-theme="light"] .results-pane .results-stat[data-stat="score"]  { background: #DCFCE7; }
[data-theme="light"] .results-pane .results-stat[data-stat="score"]  .results-stat-label,
[data-theme="light"] .results-pane .results-stat[data-stat="score"]  .results-stat-value { color: #15803D; }

/* v457: align the light-theme results stat-tile backgrounds to the neutral
 * silver treatment used by the in-game scoreboard (Owner: "align background
 * coloring to the light theme for the Time/Move/Level tiles"). The coloured
 * value text still distinguishes each stat. Placed after the per-stat tint
 * rules so it wins by source order (equal specificity). */
[data-theme="light"] .results-pane .results-stat[data-stat] {
  background: linear-gradient(160deg, #F4F6FB 0%, #D7DEEC 100%);
}

/* Buttons — 2-row 3-up grid (Owner preferred): View·Share·Rate over
 * Exit·Replay·Next, all equal height. v450b (2026-05-22). */
.results-pane .results-row-3-secondary {
  display: grid;
  /* v455: auto-size to the visible button count (1–3). Each button gets an
   * equal column via auto-flow, so omitting View (now opt-in) or hiding
   * Replay leaves NO empty cell — display:none buttons are skipped. Replaces
   * the fixed repeat(3) that left a gap when a button was removed, and the
   * per-game 2-col reflow overrides. */
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  gap: 6px;
  margin-bottom: 6px;
}
.results-pane .results-row-3 {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  gap: 6px;
}

.results-pane .results-btn {
  /* v504 (2026-06-05) — universal button standard (DESIGN-RULES §button):
   * height = --tap-target-min (44, Apple HIG), text = --font-size-label,
   * radius/padding/gap from tokens. No magic numbers; identical across
   * results / picker / sign-in / games. Hierarchy is colour + weight, not
   * size (see --primary below). Was: 40px / 13px / 10px hardcoded. */
  padding: 0 var(--space-3);
  border-radius: var(--radius-sm);
  font-size: var(--font-size-label);
  font-weight: 700;
  border: 1px solid #334155;
  background: #273246;                  /* neutral button (dark) */
  color: #F8FAFC;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-1);
  min-height: var(--tap-target-min);
  height: auto;                        /* v457: grow for 2-line labels */
  box-sizing: border-box;
  /* v457: wrap long localized labels (e.g. tr "Sonraki maç", "Tekrar oyna")
   * to 2 lines instead of clipping/overlapping. Grid stretches the row so
   * all three buttons match the tallest. */
  white-space: normal;
  line-height: 1.1;
  text-align: center;
  transition: background 0.15s ease, border-color 0.15s ease, transform 0.1s ease, filter 0.2s ease;
}
.results-pane .results-btn:hover:not(:disabled) { filter: brightness(1.12); transform: translateY(-1px); }
.results-pane .results-btn:active { transform: scale(0.98); }
[data-theme="light"] .results-pane .results-btn {
  background: #F1F5F9;                  /* neutral button (light) */
  border-color: #D7E0EA;
  color: #1F2937;
}

/* Primary — Next. The single hero CTA. Success green, strongest weight.
 * v450f: heavier glow + bolder text so it clearly out-ranks Share. */
.results-pane .results-btn--primary {
  background: linear-gradient(180deg, #34C759 0%, #248A3D 100%);
  color: #FFFFFF;
  border-color: rgba(0, 0, 0, 0.18);
  font-weight: 800;
  box-shadow: 0 4px 14px rgba(52, 199, 89, 0.45), inset 0 1px 0 rgba(255, 255, 255, 0.28);
}
[data-theme="light"] .results-pane .results-btn--primary {
  background: linear-gradient(180deg, #22C55E 0%, #16A34A 100%);
  color: #FFFFFF;
  border-color: rgba(0, 0, 0, 0.10);
  box-shadow: 0 4px 12px rgba(34, 197, 94, 0.28);
}
/* v455: Share aligned to Rate Us — the blue fill was dropped per Owner
 * ("no blue background needed; align Share to Rate Us"). Now mirrors the
 * neutral .results-btn--secondary in both themes (text/border inherit the
 * base .results-btn). */
.results-pane .results-btn--share { background: #273246; }
[data-theme="light"] .results-pane .results-btn--share { background: #F1F5F9; }
/* Neutral — Replay / View / Rate Us. */
.results-pane .results-btn--secondary { background: #273246; }
[data-theme="light"] .results-pane .results-btn--secondary { background: #F1F5F9; }
/* Exit — most subtle of all. */
.results-pane .results-btn--tertiary  { background: #1E293B; border-color: #2A3850; }
[data-theme="light"] .results-pane .results-btn--tertiary { background: #F8FAFC; border-color: #E2E8F0; }
/* Rate Us — neutral with a gold star accent (the ⭐ glyph already
 * renders gold; nudge it brighter for the premium cue). */
.results-pane #rateUsBtn span[aria-hidden] { color: #F5A524; }

/* ── Classic Wooden — GameEndScreen result surfaces. The shared result
 *    screen ships Core-dark defaults (#202B3F tiles, #273246/#1E293B
 *    buttons, iOS-green primary) + a [data-theme="light"] override, but
 *    NO wooden skin — so under [data-theme="wooden"] the stat tiles +
 *    buttons fell back to Core navy. Convert to the parchment + brass +
 *    green-felt system used on the gameplay surfaces. Wooden-scoped, so it
 *    applies to EVERY game's wooden result screen at once; Dark/Light are
 *    untouched (Owner block-puzzle result review 7.4/10 — Core→Classic
 *    conversion of the result/action area). */
/* Stat tiles (Lines / Level / Pieces / Time / Moves) → parchment + brass
 * (design reference). */
[data-theme="wooden"] .results-pane .results-stat {
  background: linear-gradient(180deg, #F5E8CC 0%, #E5D2AC 100%) !important;
  border: 1px solid #B8893A !important;
  color: #2A1B12;
  box-shadow:
    inset 0 1px 0 rgba(255, 247, 224, 0.55),
    inset 0 -1px 0 rgba(122, 85, 34, 0.20),
    0 2px 6px rgba(16, 8, 3, 0.22) !important;
}
/* Score + Top-5 → GREEN FELT panels + brass (design reference: the two
 * "achievement" panels are forest-green felt, not parchment). */
[data-theme="wooden"] .results-pane .results-score-cell,
[data-theme="wooden"] .results-pane .results-top5-cell {
  background: linear-gradient(180deg, #3F5E3B 0%, #284A26 100%) !important;
  border: 1px solid #B8893A !important;
  color: #F5ECD4 !important;
  box-shadow:
    inset 0 1px 0 rgba(255, 247, 224, 0.14),
    inset 0 -1px 0 rgba(0, 0, 0, 0.30),
    0 2px 6px rgba(16, 8, 3, 0.28) !important;
}
/* Stat-tile text → per-stat value hues + sentence-case muted-brown label,
 * MATCHING the in-game HUD .board-lower-stat tiles exactly (Owner: "time moves
 * level not aligned with the ones at game play screen" + "align game end screen
 * to game screen"). The in-game wooden palette (styles.css §HUD): time slate
 * #315A78, score/good felt-green #1F5C34, errors/bad burgundy #9B2F24, level
 * brass #7A5522, everything else espresso #2A1B12; label muted-brown #6F5A45,
 * sentence-case (the in-game labels dropped CSS uppercase in v455). Was: all
 * values forced espresso + warm-brass UPPERCASE label — the mismatch flagged. */
[data-theme="wooden"] .results-pane .results-stat .results-stat-value,
[data-theme="wooden"] .results-pane .results-stat[data-stat] .results-stat-value {
  color: #2A1B12 !important;
  font-weight: 800 !important;
}
[data-theme="wooden"] .results-pane .results-stat[data-stat="time"]   .results-stat-value { color: #315A78 !important; }
[data-theme="wooden"] .results-pane .results-stat[data-stat="score"]  .results-stat-value,
[data-theme="wooden"] .results-pane .results-stat[data-quality="good"] .results-stat-value { color: #1F5C34 !important; }
[data-theme="wooden"] .results-pane .results-stat[data-stat="errors"] .results-stat-value,
[data-theme="wooden"] .results-pane .results-stat[data-quality="bad"]  .results-stat-value { color: #9B2F24 !important; }
[data-theme="wooden"] .results-pane .results-stat[data-stat="level"]  .results-stat-value,
[data-theme="wooden"] .results-pane .results-stat[data-stat="levels"] .results-stat-value { color: #7A5522 !important; }
[data-theme="wooden"] .results-pane .results-stat-label {
  color: var(--moyako-text-muted) !important;
  letter-spacing: normal !important;
  text-transform: none !important;
}
/* Score + Top-5 text → ivory on the green felt (value/title bright, label +
 * leaderboard rows a dimmer ivory). */
[data-theme="wooden"] .results-pane .results-score-value,
[data-theme="wooden"] .results-pane .results-top5-title {
  color: #FBF3DC !important;
  font-weight: 800 !important;
}
[data-theme="wooden"] .results-pane .results-score-label,
[data-theme="wooden"] .results-pane .results-score-delta,
[data-theme="wooden"] .results-pane .results-top5-list {
  color: rgba(245, 236, 212, 0.86) !important;
}

/* Action buttons — View / Share / Rate / Replay / Exit → parchment secondary;
 * primary (Next Level / New match) → AMBER CTA + brass (design reference). */
[data-theme="wooden"] .results-pane .results-btn,
[data-theme="wooden"] .results-pane .results-btn--secondary,
[data-theme="wooden"] .results-pane .results-btn--share,
[data-theme="wooden"] .results-pane .results-btn--tertiary {
  background: linear-gradient(180deg, #F6E7C3 0%, #DFC48D 100%) !important;
  border: 1px solid #8C6428 !important;
  color: #2A1B12 !important;
  box-shadow: inset 0 1px 0 rgba(255, 247, 224, 0.45), 0 2px 5px rgba(16, 8, 3, 0.22) !important;
}
[data-theme="wooden"] .results-pane .results-btn--primary {
  background: linear-gradient(180deg, #D9923A 0%, #B85F17 100%) !important;
  border: 1px solid #D7AE54 !important;
  color: #FFF8E8 !important;
  box-shadow: inset 0 1px 0 rgba(255, 247, 224, 0.30), 0 3px 10px rgba(16, 8, 3, 0.32) !important;
}
[data-theme="wooden"] .results-pane #rateUsBtn span[aria-hidden] { color: #C8862A; }

/* "Game Over" / "Level N Cleared" title — espresso serif on the PARCHMENT hero
 * (design reference: the hero is parchment, not dark). */
[data-theme="wooden"] .results-pane .results-title {
  font-family: Georgia, 'Times New Roman', serif;
  font-weight: 800;
  color: #2A1B12 !important;
  text-shadow: none !important;
}
/* Subtitle ("Medium · 3s · 171 moves") → brown on the parchment hero. */
[data-theme="wooden"] .results-pane .results-subtitle {
  color: #6B4F2A !important;
  opacity: 1 !important;
}

/* v502 (2026-06-05) — Owner: align game-end cards to the PICKER's wooden
 * surface (parchment texture + carved frame). The surface (background +
 * border + shadow) now comes from the shared picker rule in styles.css
 * (`[data-theme="wooden"] .results-card`, §824 base + §845 carved frame) —
 * both result cards carry the .results-card class, so they inherit it.
 * Only the espresso text colour stays here (the celebration/action scope).
 * Was: solid parchment gradient + thin brass border (now superseded so the
 * results, sign-in and picker read as one framed set). */
[data-theme="wooden"] .results-pane .results-card--celebration,
[data-theme="wooden"] .results-pane .results-card--action {
  color: #2A1B12 !important;
}
/* Inner stats-block wrapper → transparent so the parchment card shows through
 * (it carried a faint white overlay that muddied the parchment). */
[data-theme="wooden"] .results-pane .results-stats-block {
  background: transparent !important;
  border-color: transparent !important;
  box-shadow: none !important;
}
/* Streak / rank badge pills sit on the PARCHMENT hero — they were ivory text on
 * a faint-white pill (invisible). Subtle warm pill + brass outline + espresso so
 * "🔥 Streak 0d" / "🏆 —" read clearly. */
[data-theme="wooden"] .results-pane .results-badge {
  background: rgba(122, 85, 34, 0.12) !important;
  border: 1px solid rgba(140, 100, 40, 0.45) !important;
  color: #5A3518 !important;
}
[data-theme="wooden"] .results-pane .results-badge #streakCount,
[data-theme="wooden"] .results-pane .results-badge #rankValue { color: #5A3518 !important; }

/* Top-5 empty/loading skeleton → faint ivory bars on the green felt. */
[data-theme="wooden"] .results-pane .results-top5-skel-bar {
  background: linear-gradient(90deg, rgba(245,236,212,0.12) 0%, rgba(245,236,212,0.28) 50%, rgba(245,236,212,0.12) 100%) !important;
}

/* #4 — keep "Next Level" / multi-word primary labels on one line instead of
 * wrapping (Next / Level). Applies to all result buttons; benign layout fix. */
.results-pane .results-btn {
  white-space: nowrap;
}

/* ── Card surface polish (v450d 2026-05-22) — design-system depth.
 * Results-scoped so the shared picker card rule is untouched. 16 px
 * radius per spec. Dark = subtle glow; light = soft depth (the light
 * theme needs this most — it was reading flat / too much empty
 * canvas). Cards go white in light mode. */
.results-pane .results-card {
  border-radius: 16px;
  box-shadow:
    0 12px 30px rgba(0, 0, 0, 0.28),
    inset 0 1px 0 rgba(148, 163, 184, 0.10);
  border: 1px solid rgba(148, 163, 184, 0.18);
}
[data-theme="light"] .results-pane .results-card {
  background: #FFFFFF;
  border: 1px solid #D7E0EA;
  box-shadow: 0 10px 24px rgba(15, 23, 42, 0.10);
}

/* ── Outcome theming via data-result on the .results-pane section ── */

/* WIN (default) — green accent, celebrate. */
.results-pane[data-result="win"] .results-card--celebration {
  border-color: rgba(46, 125, 79, 0.55);
  box-shadow: 0 12px 30px rgba(0, 0, 0, 0.28), inset 0 0 0 1px rgba(52, 199, 89, 0.20);
}
.results-pane[data-result="win"] .results-title {
  color: #34C759;
}
[data-theme="light"] .results-pane[data-result="win"] .results-card--celebration {
  border-color: #BBF7D0;
  background: #ECFDF3;
  box-shadow: 0 10px 24px rgba(15, 23, 42, 0.10);
}
[data-theme="light"] .results-pane[data-result="win"] .results-title { color: #16A34A; }

/* LOSE — red accent, neutral copy. */
.results-pane[data-result="lose"] .results-card--celebration {
  border-color: rgba(239, 83, 80, 0.32);
  box-shadow: inset 0 0 0 1px rgba(239, 83, 80, 0.18);
}
.results-pane[data-result="lose"] .results-title {
  color: #EF5350;
}

/* TIMEOUT — amber accent. */
.results-pane[data-result="timeout"] .results-card--celebration {
  border-color: rgba(255, 183, 77, 0.32);
  box-shadow: inset 0 0 0 1px rgba(255, 183, 77, 0.18);
}
.results-pane[data-result="timeout"] .results-title {
  color: #FFB74D;
}

/* DRAW — neutral grey/blue accent. */
.results-pane[data-result="draw"] .results-card--celebration {
  border-color: rgba(120, 144, 156, 0.32);
  box-shadow: inset 0 0 0 1px rgba(120, 144, 156, 0.18);
}
.results-pane[data-result="draw"] .results-title {
  color: #B0BEC5;
}

/* LEVEL (interstitial between maze levels etc.) — blue accent,
 * "Next Level" CTA dominant. */
.results-pane[data-result="level"] .results-card--celebration {
  /* R3 (v453, 2026-05-22): softer single teal edge + depth shadow
   * (matching the win state), dropping the bright double blue ring so
   * the TITLE is the hero, not the border. Per Owner results audit. */
  border-color: rgba(45, 212, 191, 0.30);
  box-shadow: 0 12px 30px rgba(0, 0, 0, 0.28), inset 0 0 0 1px rgba(45, 212, 191, 0.12);
}
.results-pane[data-result="level"] .results-title {
  /* R1 (v453): teal "success" instead of cyan-blue — distinct from the
   * win-state green + the green Next/Score (no green overload) while
   * still reading as a cleared/celebration state. */
  color: #2DD4BF;
}
[data-theme="light"] .results-pane[data-result="level"] .results-card--celebration {
  border-color: rgba(13, 148, 136, 0.30);
  box-shadow: 0 10px 24px rgba(15, 23, 42, 0.10);
}
[data-theme="light"] .results-pane[data-result="level"] .results-title {
  color: #0D9488;
}

/* ── Landscape phone — picker-pattern parity:
 *   - Right card hosts cap-settings-anchor (sound + gear rail) absolutely
 *     positioned top-right. Padding-top reserved so content clears the
 *     icon rail (44 px = 4 anchor top + 32 icon + 8 breathing).
 *   - Sandwich math: TopBar 56 + nav 60 + padding 16 → pane height
 *     ~243 on 375 px viewport.
 * The actual position absolute rule for .cap-settings-anchor inside
 * .results-card--action lives in moyako-layout.css §6963 (existing
 * cap-settings-host hook), to keep all settings-anchor rules in one
 * place. We only flag the host class here.
 * ──────────────────────────────────────────────────────────── */
.results-pane .results-card--action.cap-settings-host {
  /* hook for moyako-layout.css §7186 to absolutely position the rail */
  position: relative;
}
/* v449t (2026-05-21): more breathing room around the sound/gear rail
 * inside the results card. Per Owner "give some space to gear/sound
 * icons". The shared rule at moyako-layout.css §7186 sets a tight
 * 4 px / 4 px offset that works for the taller picker .difficulty-card
 * (~400 px) but feels cramped on the shorter results card (~208 px).
 *
 * Anchor lives only in landscape phone (moyako-layout.css §7107 hides
 * the .cap-settings-anchor by default; §7108 @media landscape-phone
 * re-enables it). In portrait + desktop the sound/gear icons render in
 * the topbar instead. So we scope both the offset bump AND the card
 * padding-top reservation to the same @media — otherwise portrait
 * gets 48 px of wasted top padding for an invisible anchor. */
@media (orientation: landscape) and (max-height: 500px) {
  .results-pane .results-card--action.cap-settings-host > .cap-settings-anchor {
    top: 9px;
    right: 12px;
    gap: 8px;
  }
  .results-pane .results-card--action.cap-settings-host {
    padding-top: 48px;
  }
}
@media (orientation: landscape) and (max-height: 500px) {
  /* v449j (2026-05-21): landscape-phone compaction so the full
   * action card (recap + stats + 2 button rows) fits the ~259 px
   * sandwich without clipping the bottom button row. Per Owner
   * "bottom row cut".
   *
   * v449s (2026-05-21): pane gap/padding now sourced from picker-
   * parity rule above (12 px row × 16 px column gap, 12 px top/bottom
   * × 16 px left/right padding). Only inner-element sizes compact
   * here. Per Owner "align the left right margin to picker screen". */
  .results-pane {
    max-width: 100%;
  }
  .results-pane .results-card {
    padding: 6px 8px;
    gap: 4px;
  }
  .results-pane .results-card--action {
    padding-top: 32px;
  }
  .results-pane .results-hero-icon { font-size: 28px; }
  .results-pane .results-hero-logo { width: 44px; height: 44px; }
  .results-pane .results-panda { width: 48px; height: 48px; }
  .results-pane .results-title { font-size: 16px; }
  .results-pane .results-subtitle { font-size: 11px; }
  .results-pane .results-badges { gap: 6px; }
  .results-pane .results-badge { font-size: 11px; padding: 2px 8px; }
  .results-pane .results-card-title {
    font-size: 11px;
    letter-spacing: 1px;
    padding: 2px 2px 4px;
  }
  .results-pane .results-stats-block { padding: 4px; gap: 4px; }
  .results-pane .results-row-1 { gap: 6px; min-height: 84px; }
  .results-pane .results-score-cell,
  .results-pane .results-top5-cell { padding: 4px 6px; }
  .results-pane .results-score-label,
  .results-pane .results-top5-title { font-size: 10px; letter-spacing: 0.6px; line-height: 1.2; margin-bottom: 1px; }
  .results-pane .results-score-value { font-size: 18px; }
  .results-pane .results-top5-list { font-size: 9px; line-height: 1.2; }
  .results-pane .results-row-2 { gap: 4px; }
  .results-pane .results-stat { padding: 3px 4px; }
  .results-pane .results-stat-label { font-size: 9px; letter-spacing: 0.4px; line-height: 1.1; }
  .results-pane .results-stat-value { font-size: 13px; line-height: 1.1; }
  /* v450b: button-grid compaction (landscape phone). */
  .results-pane .results-row-3-secondary { gap: 4px; margin-bottom: 4px; }
  .results-pane .results-row-3 { gap: 4px; }
  .results-pane .results-btn {
    font-size: 10px;
    min-height: 30px;
    height: 30px;
    padding: 3px 5px;
    gap: 3px;
  }
}
