/* Magtein Science Playable — Run C internal-feedback GAME STAGE (PD-013 D5).
   Isolated stylesheet OUTSIDE the governed production CSS roots (PD-012
   precedent). Loaded only by the play route in internal-feedback mode;
   default mode never requests this file.

   WHAT THIS FILE DOES: reproduces the authoritative earlier game-platform
   stage treatment — the donor field #0a0d0a with its twin green bloom
   gradients, donor chrome text/border/surface values (magtein-hub-platform
   @ 89506376, theme/tokens.css) — as ONE stable outer stage band shared by
   every game, and re-maps the appearance CHROME custom properties inside
   that band so existing game chrome sits on the donor field.

   WHAT THIS FILE NEVER TOUCHES: frozen functional colours (#1db954,
   #d7263d, #8a8a8e, #08130b, #d9822b, the CC inks), stimulus identity,
   geometry, hitboxes, trial structure, timing, scoring, or any governed
   token module. Game-internal rules always win where they set explicit
   colours, because frozen values are literals, not var() references.

   High-contrast players keep their hc chrome: the donor re-mapping is
   skipped under :root[data-appearance="hc"]. */

/* Donor chrome tokens, scoped to the stage subtree only. */
:root:not([data-appearance="hc"]) [data-msp-donor-stage="true"] .runc-stage-shell {
  --surface-0: #0a0d0a; /* donor --field */
  --surface-1: #111511; /* donor --field-2 */
  --surface-2: #191e18; /* donor --field-3 */
  --text-primary: #f1f3f0; /* donor --bone */
  --text-secondary: #a4a8a4; /* donor --graphite */
  --border-subtle: rgba(232, 235, 232, 0.08); /* donor --hairline */
  --border-strong: rgba(232, 235, 232, 0.17); /* donor --hairline-2 */
  --focus-ring: #9ce59c;
  --link: #9ce59c;
  --card-shadow: 0 1px 3px rgb(0 0 0 / 0.5);
}

/* One stable full-width stage band for every game (donor field + bloom). */
[data-msp-donor-stage="true"] .runc-stage-shell {
  background-color: #0a0d0a;
  background-image:
    radial-gradient(
      130% 85% at 50% -18%,
      rgba(113, 219, 113, 0.1) 0%,
      rgba(113, 219, 113, 0.03) 42%,
      rgba(113, 219, 113, 0) 68%
    ),
    radial-gradient(
      120% 90% at 50% 118%,
      rgba(47, 158, 78, 0.07) 0%,
      rgba(47, 158, 78, 0) 55%
    );
  background-repeat: no-repeat;
  color: #f1f3f0;
  /* MT-06/MT-03 (manual-playtest fix). This band used to force itself to a
     full viewport (calc(100dvh - 120px)), so the READY state — title, Start,
     How to play, Sound — sat at the top of a near-empty dark page and read as
     "no demonstration, huge empty area". The band now wraps its content: the
     ready state is compact with Start immediately visible, and during a run
     the band is exactly as tall as the stable game stage needs. The stage
     rectangle itself is pinned per game in each game's own stylesheet. */
  display: flex;
  flex-direction: column;
  min-height: calc(100svh - 101px);
}
:root[data-appearance="hc"] [data-msp-donor-stage="true"] .runc-stage-shell {
  background-color: #000000;
  background-image: none;
  color: #ffffff;
}

/* PD-014 D8 — STATIC GAME HEADER. Magtein logo top left, one "Back to all
   games" link top right. No rail, no game icons, no Previous/Next, no
   animation. */
[data-msp-donor-stage="true"] .runc-game-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 14px clamp(12px, 3vw, 28px);
  background: #0a203d;
  border-bottom: 1px solid rgba(246, 248, 237, 0.14);
}

[data-msp-donor-stage="true"] .runc-game-header-home {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  flex: none;
  text-decoration: none;
}

[data-msp-donor-stage="true"] .runc-game-brand-divider {
  color: rgba(246, 248, 237, 0.7);
}

[data-msp-donor-stage="true"] .runc-game-brand-title {
  display: inline-flex;
  align-items: center;
  min-height: 22px;
  padding: 0.32rem 0.4rem;
  border-radius: 999px;
  background: #71db71;
  color: #08130b;
  font: 600 0.54rem/1 Inter, system-ui, -apple-system, "Segoe UI", sans-serif;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  white-space: nowrap;
  box-shadow: inset 0 0 0 1px rgba(10, 32, 61, 0.08);
}

[data-msp-donor-stage="true"] .runc-game-logo {
  display: block;
  width: auto;
  height: 72px;
  max-width: 58vw;
  object-fit: contain;
}

@media (max-width: 759px) {
  [data-msp-donor-stage="true"] .runc-game-header {
    gap: 12px;
    padding: 10px 16px;
  }
  [data-msp-donor-stage="true"] .runc-game-logo {
    height: 44px;
  }
  [data-msp-donor-stage="true"] .runc-game-brand-divider,
  [data-msp-donor-stage="true"] .runc-game-brand-title {
    display: none;
  }
  [data-msp-donor-stage="true"] .runc-game-header-back {
    margin-left: auto;
  }
}

[data-msp-donor-stage="true"] .runc-game-header-back {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 8px 18px;
  border-radius: 999px;
  border: 1.5px solid rgba(246, 248, 237, 0.35);
  color: #f6f8ed;
  font-weight: 600;
  font-size: 0.88rem;
  text-decoration: none;
  white-space: nowrap;
}
[data-msp-donor-stage="true"] .runc-game-header-back:focus-visible,
[data-msp-donor-stage="true"] .runc-game-header-home:focus-visible {
  outline: 3px solid #9ce59c;
  outline-offset: 2px;
}

/* PD-014 D8 — the rail gutter column is gone, so the stage column is the full
   band width and the game centres in the middle of it instead of sitting
   beside a 120 px strip of dead space. The game roots keep their own
   protected max-widths (640 px / Trail Switch 720 px) and centre inside it;
   no game root is widened, narrowed or distorted, and no stimulus geometry,
   hitbox or timing is touched. */
[data-msp-donor-stage="true"] .runc-stage-main {
  width: 100%;
  min-width: 0;
  padding-bottom: 28px;
}

[data-msp-donor-stage="true"] .runc-stage-status {
  width: 100%;
  padding: 0 1rem 1rem;
}
[data-msp-donor-stage="true"] .runc-stage-status .msp-prototype-status {
  margin-bottom: 0;
}

/* STABLE STAGE WIDTH (manual-playtest fix MT-09 … MT-13).

   The centring above used to be done with `margin-left/right: auto` on every
   child of the flex-column <section>. In a flex column the horizontal axis is
   the CROSS axis, and an auto cross-axis margin OVERRIDES `align-items:
   stretch`: the item is sized to fit-content and the leftover space is split
   between the two margins. Each game root therefore stopped being
   `min(canonical, available)` and became exactly as wide as whatever text the
   CURRENT state happened to render — measured on the unmodified tree at
   1440x900, Quick Tap ran 171.53 px on "TAP!" and 464.61 px on "Paused — that
   one didn't count.", and Pair Memory collapsed to 199.30 px during its study
   phase. Each game's own `max-width` is only an upper bound, so it could cap
   the width but never hold it steady.

   The column is now centred ONCE, as a whole, at the canonical donor width,
   and its children stretch to fill it. Centring — the original intent — is
   preserved; the state-dependent shrink-wrap is gone. This is a containing-
   block correction only: no stimulus geometry, hitbox, coordinate system,
   trial structure, timing or scoring is touched, and default/public mode never
   loads this file. */
[data-msp-donor-stage="true"] {
  /* Canonical donor stage width, authoritative per game. */
  --runc-stage-w: 640px;
}
[data-msp-donor-stage="true"][data-msp-stage-game="trail-switch"] {
  --runc-stage-w: 720px;
}
[data-msp-donor-stage="true"] .runc-stage-main > section {
  width: min(var(--runc-stage-w), 100%);
  margin-inline: auto;
  align-items: stretch;
}
[data-msp-donor-stage="true"] .runc-stage-main > section > * {
  /* Definite cross size, so `align-items: stretch` is never displaced by an
     auto margin and the box can no longer track its own text width. */
  width: 100%;
  min-width: 0;
  margin-left: 0;
  margin-right: 0;
}

/* Vertical fit at 1024x768 and larger: the band no longer has to be a full
   viewport tall now that the header is compact, so Start and the control row
   are reachable on initial load without an internal scroller. The control row
   is never placed inside an overflow container — the PAGE scrolls when a
   taller canonical game needs more room. */
[data-msp-donor-stage="true"] .runc-stage-shell,
[data-msp-donor-stage="true"] .runc-stage-main {
  overflow: visible;
}
[data-msp-donor-stage="true"] .runc-stage-main > section {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding-top: 6px;
}
[data-msp-donor-stage="true"] .runc-stage-main > section > h1 {
  margin: 0;
}

/* Donor inner width framing for the ready/result chrome (donor
   .mg-start-inner min(44rem,100%) / .mg-result-inner min(40rem,100%)). */
[data-msp-donor-stage="true"] .msp-ready-actions {
  max-width: none;
}
[data-msp-donor-stage="true"] .msp-result {
  max-width: min(40rem, 100%);
}

/* Donor result presentation concept (extraction §7.2) — WITHDRAWN by the
   pre-review polish (2026-08-07, PD-019 D3): the hero metric now renders in
   its own bordered box OUTSIDE the dl (ResultPanel internal composition),
   so the first dl row is an ordinary uniform grid card and must not carry
   hero typography. See the SESSION COMPLETE — DESIGN ARTEFACT block. */

/* Leave-run confirmation dialog (PD-013 D4). */
[data-msp-donor-stage="true"] .runc-leave-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(6, 20, 38, 0.72);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 100;
  padding: 16px;
}
[data-msp-donor-stage="true"] .runc-leave-dialog {
  background: #0f244a;
  color: #f6f8ed;
  border: 1px solid rgba(246, 248, 237, 0.3);
  border-radius: 16px;
  padding: 22px 24px;
  max-width: 26rem;
}
[data-msp-donor-stage="true"] .runc-leave-dialog h2 {
  margin: 0 0 8px;
}
[data-msp-donor-stage="true"] .runc-leave-dialog p {
  margin: 0 0 16px;
}
[data-msp-donor-stage="true"] .runc-leave-actions {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}
[data-msp-donor-stage="true"] .runc-leave-actions button {
  min-height: 44px;
  padding: 10px 20px;
  border-radius: 999px;
  border: 1.5px solid rgba(246, 248, 237, 0.35);
  background: transparent;
  color: inherit;
  font-weight: 700;
  cursor: pointer;
}
[data-msp-donor-stage="true"] .runc-leave-actions [data-runc-leave-confirm="true"] {
  background: #71db71;
  border-color: transparent;
  color: #0a203d;
}

/* PD-014 D1 — the quiet-navigation block is REMOVED. It existed only to pause
   decorative rail motion during a run; with the rail withdrawn there is no
   decorative motion on this page to pause, so the state, its observer and
   these rules are all gone rather than left as dead weight. */

/* ---------------- Trail Switch exact donor path treatment (PD-013 D6) ----
   Donor values from magtein-hub-platform @ 89506376:
   .te-seg  stroke url(#teGrad) width 4 linecap round opacity .9
            filter drop-shadow(0 0 6px rgba(113,219,113,.38))
   .te-pulse fill var(--pulse) #d9ffd6 with layered glow.
   The gradient paint itself is set inline by the client (an external-CSS
   url(#…) would resolve against this stylesheet's URL, not the document).
   Node geometry, order, hit testing, timing and scoring are untouched; the
   SVG is aria-hidden and takes no pointer input, and nodes render above it
   with no clipping exactly as before. */
[data-msp-donor-stage="true"] .tsw-svg line {
  stroke-width: 4;
  stroke-linecap: round;
  opacity: 0.9;
  filter: drop-shadow(0 0 6px rgba(113, 219, 113, 0.38));
}
[data-msp-donor-stage="true"] .tsw-pulse {
  fill: #d9ffd6;
  filter: drop-shadow(0 0 8px rgba(113, 219, 113, 0.38))
    drop-shadow(0 0 3px #b9f5b4);
}
/* Reduced motion: completed path retained, moving dots stopped (the client
   also never shows the pulse under reduced motion — this is belt and
   braces at the presentation layer). */
@media (prefers-reduced-motion: reduce) {
  [data-msp-donor-stage="true"] .tsw-pulse {
    visibility: hidden !important;
  }
}

/* ---------------- Signal Control "Just for fun" panel (PD-013 D9) ------- */

[data-msp-donor-stage="true"] .runc-fun {
  max-width: min(40rem, 100%);
  margin-top: 20px;
  padding: 18px 20px;
  border: 1.5px dashed rgba(246, 248, 237, 0.3);
  border-radius: 16px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
[data-msp-donor-stage="true"] .runc-fun-title {
  margin: 0;
  font-size: 1.05rem;
  letter-spacing: 0.1em;
}
[data-msp-donor-stage="true"] .runc-fun-note,
[data-msp-donor-stage="true"] .runc-fun-draft {
  margin: 0;
  font-size: 0.8rem;
  opacity: 0.7;
}
[data-msp-donor-stage="true"] .runc-fun-question {
  margin: 4px 0 0;
  font-weight: 600;
}
[data-msp-donor-stage="true"] .runc-fun-options {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
[data-msp-donor-stage="true"] .runc-fun-option {
  min-height: 44px;
  padding: 8px 18px;
  border-radius: 999px;
  border: 1.5px solid rgba(246, 248, 237, 0.3);
  background: transparent;
  color: inherit;
  font-weight: 600;
  cursor: pointer;
}
[data-msp-donor-stage="true"] .runc-fun-ack {
  margin: 0;
  font-size: 0.9rem;
}
[data-msp-donor-stage="true"] .runc-fun-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
  margin-top: 4px;
}
[data-msp-donor-stage="true"] .runc-fun-actions button,
[data-msp-donor-stage="true"] .runc-fun-actions a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 8px 16px;
  border-radius: 999px;
  border: 1.5px solid rgba(246, 248, 237, 0.35);
  background: transparent;
  color: inherit;
  font-weight: 600;
  font-size: 0.85rem;
  text-decoration: none;
  cursor: pointer;
}

/* Footer stays below the experience; the band grows, the footer never
   floats into it. */
[data-msp-donor-stage="true"] .msp-site-footer {
  margin-top: 0;
}

/* ================= Quick Tap composition pilot (2026-08-07) =================
   Every rule below is scoped to [data-msp-stage-game="quick-tap"]; the other
   eight games' play routes match none of it, and default/public mode never
   loads this file at all. */

/* UNIFORM STAGE SCALE. One canonical Quick Tap stage coordinate system —
   the game-owned 640x412 .qt-root (status strip, 640x320 surface, Finish
   row) — displayed through a single uniform transform. 1.58 is the maximum
   scale that keeps header, title, the whole stage and Finish run inside
   1440x900 without scrolling (measured vertical budget: stage top 211 px,
   bottom padding 28 px -> 661 px available; 412 x 1.58 = 651 px). Smaller
   viewports derive the factor from available width, so the whole stage
   scales down uniformly. Width and height always scale together; no
   internal element is stretched independently; coordinates, hitboxes,
   timing and scoring are untouched (Quick Tap's input path reads no
   coordinates — the whole surface is one button). */
[data-msp-donor-stage="true"][data-msp-stage-game="quick-tap"] {
  /* tan(atan2(a, b)) is the standards-supported way to turn a ratio of two
     LENGTHS into a plain NUMBER usable inside scale(); a straight division
     would make min() mix a number with a length and invalidate the value.
     Three bounds: the 1440x900 maximum (1.58), the available width, and the
     available height (viewport minus the 211 px of chrome above the stage
     and the 28 px bottom padding, over the canonical 412 px stage) — so the
     whole stage, Finish row included, stays inside ANY viewport without
     scrolling, and shorter windows scale the stage down uniformly. */
  --qt-scale: min(
    1.58,
    tan(atan2(100vw - 32px, 640px)),
    tan(atan2(100vh - 239px, 412px))
  );
  --runc-stage-w: calc(640px * var(--qt-scale));
}
[data-msp-donor-stage="true"][data-msp-stage-game="quick-tap"]
  .runc-stage-main
  > section
  > .qt-root {
  width: 640px;
  min-width: 640px;
  /* Centre the canonical box on the section at every scale factor: the
     margins are (scaled width - canonical width) / 2, symmetric — positive
     when the stage displays larger than 640 px, negative when a narrow
     viewport scales it down (which also keeps the LAYOUT box inside the
     section, so nothing overflows horizontally). */
  margin-inline: calc((var(--runc-stage-w) - 640px) / 2);
  transform: scale(var(--qt-scale));
  transform-origin: top center;
  /* A transform scales the paint, not the layout box: reserve the scaled
     visual height so following content sits below the stage, never under
     it. Negative below scale 1 is intentional — it reclaims the unused
     layout height when the stage scales down. */
  margin-bottom: calc(412px * (var(--qt-scale) - 1));
}

/* READY-STAGE FRAME (pilot ready phase in PlayShell). The inert pre-run
   stage: same canonical rectangle, neutral panel, instruction and Start
   centred inside it. No stimulus: nothing here ever turns green, and the
   panel deliberately uses the donor chrome surface — NOT the frozen wait
   grey — so an inert frame can never be read as the pre-signal stimulus.
   The game's own stylesheet ships inside its lazily-loaded client chunk and
   is absent before Start, so the frame's canonical metrics (640x412 root,
   320 surface, the status strip) are restated here from quick-tap.css. */
[data-msp-stage-game="quick-tap"] .qt-root[data-qt-ready="true"] {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  /* The inert frame is the status strip + the 320 surface (356 px): the
     SURFACE rectangle — the game area — is exactly the one gameplay uses,
     at the same position; the run-only Finish row region below it is not
     reserved here, so How to play and Sound stay inside the first viewport.
     The height reservation below therefore uses 356, not 412. */
  min-height: 356px;
}
[data-msp-donor-stage="true"][data-msp-stage-game="quick-tap"]
  .runc-stage-main
  > section
  > .qt-root[data-qt-ready="true"] {
  margin-bottom: calc(356px * (var(--qt-scale) - 1));
}
[data-msp-stage-game="quick-tap"] .qt-root[data-qt-ready="true"] .qt-status {
  display: flex;
  gap: 1rem;
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}
[data-msp-stage-game="quick-tap"] .qt-ready-surface {
  min-height: 320px;
  border: 2px solid var(--border-strong);
  border-radius: 12px;
  background: var(--surface-1);
  color: var(--text-primary);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 20px;
  cursor: default;
}
[data-msp-stage-game="quick-tap"] .qt-ready-surface .qt-message {
  font-size: 1.25rem;
  text-transform: none;
  letter-spacing: 0.02em;
  max-width: 34ch;
  text-align: center;
}

/* Keep programmatic heading focus for announcements without a visual ring. */
[data-msp-stage-game="quick-tap"] .runc-stage-main > section > h1 {
  width: fit-content;
}
[data-msp-stage-game="quick-tap"] .runc-stage-main > section > h1:focus,
[data-msp-stage-game="quick-tap"] .runc-stage-main > section > h1:focus-visible {
  outline: none;
}

/* SESSION COMPLETE COMPOSITION — the pilot's Quick-Tap-scoped align-to-start
   rules are WITHDRAWN here (pre-review polish, 2026-08-07): the artefact
   composition at the end of this file now governs every game's results,
   Quick Tap included. See the SESSION COMPLETE — DESIGN ARTEFACT block. */

/* ================= Games propagation (2026-08-07) =================
   The Quick Tap pilot pattern applied to the other eight games. Quick Tap's
   own pilot rules above are UNTOUCHED; nothing below matches
   [data-msp-stage-game="quick-tap"].

   UNIFORM STAGE SCALE, PER GAME. One canonical per-game stage coordinate
   system (the game-owned 640px root at its MT-09 pinned height) displayed
   through a single uniform transform. Each cap below is the maximum scale
   that keeps header, title, the whole root and Finish run inside 1440x900
   without scrolling — measured vertical budget 661px (chrome above the stage
   ends at 211px, bottom padding 28px), divided by that game's pinned root
   height, with the pilot's rounding margin. Smaller viewports derive the
   factor from available width and height, so the whole stage scales down
   uniformly. Width and height always scale together; no internal element is
   stretched independently; coordinates, hitboxes, timing and scoring are
   untouched (per-game pointer-path evidence in the propagation report).

   TRAIL SWITCH IS DELIBERATELY ABSENT from every scale rule below. Its input
   path is not transform-safe: the client measures the board and node probe
   with getBoundingClientRect (visual space) and re-injects those values as
   layout-pixel styles, so under a transform the drawn nodes and the hit
   tests diverge and the probe-measured diameter double-scales
   (TrailSwitchClient.tsx:491-503, 597-638, 865-870). Section 7 of the
   propagation prompt stops that game rather than adjusting coordinates: the
   donor clamp(360px, 62vh, 560px) geometry is preserved at scale 1.0. */

[data-msp-donor-stage="true"][data-msp-stage-game="target-rush"] {
  --rg-h: 540px; /* tr-root MT-09 pin */
  --rg-ready-h: 416px; /* status 24 + gap 12 + arena-sized panel 380 */
  --rg-panel-h: 380px; /* .tr-arena min-height */
  --rg-cap: 1.21; /* 661 / 540 = 1.224 */
}
@media (max-width: 760px) {
  [data-msp-donor-stage="true"][data-msp-stage-game="target-rush"] {
    --rg-h: 580px; /* tr-root narrow pin */
  }
}

[data-msp-donor-stage="true"][data-msp-stage-game="number-recall"] {
  --rg-h: 480px; /* nr-root MT-09 pin */
  --rg-ready-h: 356px; /* status + gap + stage-sized panel 320 */
  --rg-panel-h: 320px; /* .nr-card / .nr-stage min-height */
  --rg-cap: 1.36; /* 661 / 480 = 1.377 */
}

[data-msp-donor-stage="true"][data-msp-stage-game="pair-memory"] {
  --rg-h: 360px; /* pm-root MT-09 pin */
  --rg-ready-h: 292px; /* status + gap + study-sized panel 256 */
  --rg-panel-h: 256px; /* study card, the measured MT-09 study height */
  --rg-cap: 1.81; /* 661 / 360 = 1.836 */
}
@media (max-width: 760px) {
  [data-msp-donor-stage="true"][data-msp-stage-game="pair-memory"] {
    --rg-h: 420px; /* pm-root narrow pin */
  }
}

[data-msp-donor-stage="true"][data-msp-stage-game="picture-sequence"] {
  --rg-h: 412px; /* ps-root MT-09 pin */
  --rg-ready-h: 356px;
  --rg-panel-h: 320px; /* .ps-card / .ps-stage min-height */
  --rg-cap: 1.58; /* 661 / 412 = 1.604 (the pilot's own ceiling family) */
}

[data-msp-donor-stage="true"][data-msp-stage-game="signal-control"] {
  --rg-h: 416px; /* sc-root MT-09 pin */
  --rg-ready-h: 380px; /* the panel alone — sc renders no status strip */
  --rg-panel-h: 380px; /* .sc-panel min-height */
  --rg-cap: 1.57; /* 661 / 416 = 1.589 */
}

[data-msp-donor-stage="true"][data-msp-stage-game="arrow-focus"] {
  --rg-h: 360px; /* af-root MT-09 pin */
  --rg-ready-h: 196px; /* status + gap + stage-sized panel 160 */
  --rg-panel-h: 160px; /* .af-stage min-height */
  --rg-cap: 1.81; /* 661 / 360 = 1.836 */
}

[data-msp-donor-stage="true"][data-msp-stage-game="colour-conflict"] {
  --rg-h: 360px; /* cc-root MT-09 pin */
  --rg-ready-h: 196px; /* status + gap + stage-sized panel 160 */
  --rg-panel-h: 160px; /* .cc-stage min-height */
  --rg-cap: 1.81; /* 661 / 360 = 1.836 */
}
@media (max-width: 760px) {
  [data-msp-donor-stage="true"][data-msp-stage-game="colour-conflict"] {
    --rg-h: 460px; /* cc-root narrow pin */
  }
}

/* The single uniform factor (pilot idiom): the 1440x900 cap, the available
   width, and the available height over the canonical root — so the whole
   root, Finish row included, stays inside ANY viewport without scrolling. */
[data-msp-donor-stage="true"][data-msp-stage-game="target-rush"],
[data-msp-donor-stage="true"][data-msp-stage-game="number-recall"],
[data-msp-donor-stage="true"][data-msp-stage-game="pair-memory"],
[data-msp-donor-stage="true"][data-msp-stage-game="picture-sequence"],
[data-msp-donor-stage="true"][data-msp-stage-game="signal-control"],
[data-msp-donor-stage="true"][data-msp-stage-game="arrow-focus"],
[data-msp-donor-stage="true"][data-msp-stage-game="colour-conflict"] {
  --rg-scale: min(
    var(--rg-cap),
    tan(atan2(100vw - 32px, 640px)),
    tan(atan2(100vh - 239px, var(--rg-h)))
  );
  --runc-stage-w: calc(640px * var(--rg-scale));
}

/* The scaled root — live game root AND the inert ready frame (both carry the
   game root class). Same margin/reservation mechanics as the pilot's
   Quick Tap rule: centre the canonical box at every factor, reserve the
   scaled visual height so following content sits below the stage. */
[data-msp-donor-stage="true"] .runc-stage-main > section > :is(
  .tr-root,
  .nr-root,
  .pm-root,
  .ps-root,
  .sc-root,
  .af-root,
  .cc-root
) {
  width: 640px;
  min-width: 640px;
  margin-inline: calc((var(--runc-stage-w) - 640px) / 2);
  transform: scale(var(--rg-scale, 1));
  transform-origin: top center;
  margin-bottom: calc(var(--rg-h, 640px) * (var(--rg-scale, 1) - 1));
}

/* The ready frame is shorter than the full root (no Finish region — the
   pilot's own choice), so it reserves its own scaled height. */
[data-msp-donor-stage="true"] .runc-stage-main > section > .rg-ready-root {
  margin-bottom: calc(var(--rg-ready-h, 320px) * (var(--rg-scale, 1) - 1));
}

/* INERT READY FRAME CHROME (pilot pattern, per game). The game's own
   stylesheet ships inside its lazily-loaded client chunk and is absent
   before Start, so the frame restates the canonical metrics here. The panel
   deliberately uses the donor chrome surface — NOT any frozen stimulus
   colour — so an inert frame can never be read as a stimulus. */
[data-msp-donor-stage="true"] .rg-ready-root {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  min-height: var(--rg-ready-h, 320px);
}
[data-msp-donor-stage="true"] .rg-status {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 1rem;
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}
[data-msp-donor-stage="true"] .rg-status .msp-sound-control {
  margin-left: auto;
}
[data-msp-donor-stage="true"] .rg-status-sound-only {
  justify-content: flex-end;
}
[data-msp-donor-stage="true"] .rg-ready-surface {
  min-height: var(--rg-panel-h, 320px);
  border: 2px solid var(--border-strong);
  border-radius: 12px;
  background: var(--surface-1);
  color: var(--text-primary);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 20px;
  padding: 24px;
  cursor: default;
}
[data-msp-donor-stage="true"] .rg-message {
  font-size: 1.25rem;
  letter-spacing: 0.02em;
  max-width: 34ch;
  text-align: center;
}

/* Trail Switch ready frame: the donor board rectangle itself, unscaled. */
[data-msp-donor-stage="true"][data-msp-stage-game="trail-switch"] {
  --rg-ready-h: calc(clamp(360px, 62vh, 560px) + 36px);
}
[data-msp-donor-stage="true"][data-msp-stage-game="trail-switch"] .rg-ready-surface {
  min-height: clamp(360px, 62vh, 560px);
}

/* Match the pilot heading treatment across game stages. */
[data-msp-donor-stage="true"] .runc-stage-main > section > h1 {
  width: fit-content;
}
[data-msp-donor-stage="true"] .runc-stage-main > section > h1:focus,
[data-msp-donor-stage="true"] .runc-stage-main > section > h1:focus-visible {
  outline: none;
}

/* ============ SESSION COMPLETE — DESIGN ARTEFACT COMPOSITION ============
   Pre-review polish (2026-08-07, PD-019 D3). The results panel reproduces
   the "SESSION COMPLETE + RESULTS" panel of the approved design artefact
   ("Magtein All Nine Game Design Review.html", values read from its own
   markup): ONE light contained card on the stage column — cream surface,
   radius 16, padding 20; a bordered WHITE hero box (2px ink border, radius
   16); a STRICT UNIFORM two-column metric grid (1.5px ink-tint borders,
   radius 12, 8px gap — cards share width and row height, an odd count
   leaves the last cell empty, cards never size to their own content); and
   the bordered disclaimer closing the card. This SUPERSEDES the pilot's
   align-to-start composition above (both solved results scrolling; the
   artefact's tight uniform grid now governs). Fixed-light in EVERY
   appearance mode, under the same owner ruling as the pre-play pages
   (PD-018 D2): a light design-review surface, deliberately identical in
   light, dark and high contrast. Values, labels, units, order and
   calculations are the unchanged ResultPanel; presentation only. None of
   these colours is a frozen functional colour. */
[data-msp-donor-stage="true"] .msp-result {
  max-width: none;
  width: 100%;
}
[data-msp-donor-stage="true"] .runc-result-card {
  border: 1px solid rgba(246, 248, 237, 0.18);
  border-radius: 16px;
  background: #f6f8ed;
  color: #0a203d;
  /* The artefact's 20px card padding, with the bottom edge and the vertical
     joinery below trimmed a few pixels each (documented adaptation): the
     artefact panel carries no action row, and these trims are what let the
     complete live result PLUS Replay / Next game / All games sit inside the
     1440x900 fold for every game except the two 11-metric ones (named
     exception in the run report). Card, hero and cell geometry are the
     artefact's own values throughout. */
  padding: 20px 20px 16px;
}
[data-msp-donor-stage="true"] .runc-result-card h2 {
  margin: 0;
  font-family: "Barlow Semi Condensed", "Bahnschrift SemiCondensed", sans-serif;
  font-size: 26px;
  font-weight: 800;
  line-height: 1.05;
  text-transform: uppercase;
  color: #0a203d;
}
[data-msp-donor-stage="true"] .runc-result-card .msp-result-lede {
  margin: 4px 0 0;
  max-width: none;
  font-size: 0.85rem;
  color: #545554;
}
[data-msp-donor-stage="true"] .runc-result-hero {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 12px;
  border: 2px solid #0a203d;
  border-radius: 16px;
  padding: 16px 20px;
  background: #ffffff;
}
[data-msp-donor-stage="true"] .runc-result-hero-label {
  font-size: 10px;
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #274631;
}
[data-msp-donor-stage="true"] .runc-result-hero-value {
  font-family: "Barlow Semi Condensed", "Bahnschrift SemiCondensed", sans-serif;
  font-size: 38px;
  font-weight: 800;
  line-height: 1;
  color: #0a203d;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
[data-msp-donor-stage="true"] .runc-result-hero-note {
  font-size: 12.5px;
  font-weight: 500;
  line-height: 1.5;
  color: #545554;
}
[data-msp-donor-stage="true"] .runc-result-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
  margin: 10px 0 0;
}
@media (max-width: 480px) {
  /* Narrow phones only — the desktop grid NEVER collapses to one column. */
  [data-msp-donor-stage="true"] .runc-result-grid {
    grid-template-columns: minmax(0, 1fr);
  }
}
[data-msp-donor-stage="true"] .runc-result-grid .msp-result-row {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  gap: 2px;
  min-width: 0;
  border: 1.5px solid rgba(10, 32, 61, 0.25);
  border-radius: 12px;
  padding: 10px 12px;
  background: transparent;
}
[data-msp-donor-stage="true"] .runc-result-grid dt {
  font-size: 11px;
  font-weight: 500;
  line-height: 1.4;
  color: #545554;
}
[data-msp-donor-stage="true"] .runc-result-grid dd {
  margin: 0;
  font-family: "Barlow Semi Condensed", "Bahnschrift SemiCondensed", sans-serif;
  font-size: 17px;
  font-weight: 700;
  line-height: 1.1;
  color: #0a203d;
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}
[data-msp-donor-stage="true"] .runc-result-card .msp-result-note {
  margin: 8px 0 0;
  max-width: none;
  font-size: 12.5px;
  color: #545554;
}
[data-msp-donor-stage="true"] .runc-result-card .msp-disclaimer {
  display: inline-block;
  max-width: none;
  margin: 10px 0 0;
  border: 1.5px solid rgba(10, 32, 61, 0.3);
  border-radius: 10px;
  padding: 8px 12px;
  font-size: 11.5px;
  font-weight: 500;
  line-height: 1.5;
  color: #545554;
}
[data-msp-donor-stage="true"] .msp-result > .msp-result-actions {
  margin-top: 8px;
}

/* Public games share an unscaled responsive column so controls and Trail
   Switch's measured pointer geometry use the same coordinate space. */
[data-msp-donor-stage="true"][data-msp-stage-game] {
  --runc-stage-w: 720px;
  --runc-play-panel-h: clamp(420px, 62svh, 560px);
}

[data-msp-donor-stage="true"][data-msp-stage-game]
  .runc-stage-main > section > :is(.qt-root, .nr-root, .tsw-root, .cc-root) {
  width: 100%;
  min-width: 0;
  max-width: none;
  min-height: 0;
  margin: 0;
  transform: none;
}

[data-msp-donor-stage="true"][data-msp-stage-game="quick-tap"]
  .runc-stage-main > section > .qt-root[data-qt-ready="true"],
[data-msp-donor-stage="true"] .runc-stage-main > section > .rg-ready-root {
  margin-bottom: 0;
}

[data-msp-donor-stage="true"][data-msp-stage-game] :is(
  .rg-ready-surface, .qt-surface, .nr-card, .nr-stage, .nr-entry, .tsw-board, .tsw-card,
  .cc-intro, .cc-stage
) {
  min-height: var(--runc-play-panel-h);
}

[data-msp-donor-stage="true"] :is(.qt-status, .nr-status, .cc-status, .rg-status) {
  align-items: center;
  flex-wrap: wrap;
}

[data-msp-donor-stage="true"] :is(.qt-status, .nr-status, .cc-status) .msp-sound-control {
  margin-left: auto;
  flex-shrink: 0;
}

/* Mobile controls keep their actual size; the page scrolls instead of
   scaling a fixed-width game and estimating its painted height. */
@media (max-width: 759px) {
  [data-msp-donor-stage="true"][data-msp-stage-game] {
    --runc-stage-w: 100%;
  }

  [data-msp-donor-stage="true"] .runc-stage-shell {
    min-height: calc(100vh - 65px);
    min-height: calc(100svh - 65px);
  }

  [data-msp-donor-stage="true"] .runc-stage-main {
    padding: 16px 16px 32px;
  }

  [data-msp-donor-stage="true"][data-msp-stage-game]
    .runc-stage-main > section > :is(
      .qt-root, .tr-root, .nr-root, .pm-root, .ps-root, .sc-root, .af-root, .cc-root
    ) {
    width: 100%;
    min-width: 0;
    margin: 0;
    transform: none;
  }

  [data-msp-donor-stage="true"][data-msp-stage-game="quick-tap"]
    .runc-stage-main > section > .qt-root[data-qt-ready="true"] {
    margin-bottom: 0;
  }

  [data-msp-donor-stage="true"] .runc-stage-main :is(
    .qt-finish, .tr-finish, .nr-finish, .pm-finish, .ps-finish,
    .sc-finish, .af-finish, .cc-finish, .tsw-finish
  ) {
    min-height: 48px;
    min-width: 120px;
    padding: 12px 20px;
    font-size: 1rem;
    touch-action: manipulation;
  }
}
