/* ─── CRITICAL — slice 1 ──────────────────────────────────────────────────────
   Its own stylesheet for the same reason Gem Duel has one: the board is a dense grid with a dozen
   states per cell, and folding that into the shared sheet is how cascade collisions start
   (predicely_cascade_collisions — a reskin rule that ties colour to a class it does not own).

   ⛔ EVERY SELECTOR IN HERE IS SCOPED to #critical-game-screen or .cr-root. Nothing global.

   ⭐ LOCKED LAYOUT (predicely_locked_layout_rule): the chain counter, the status line and the seat
   cards have FIXED heights, not min-heights — `min-height` still lets a row GROW, which is exactly
   the 1.5px hop the rule exists to stop. critical-board.test.html measures the boxes before and
   after a chain and demands they agree to the pixel.

   ⛔ GameEndScreen appends to document.body, so it is a SIBLING of the game screen: the --cr-*
   tokens below DO NOT reach it. The end-screen block at the foot declares its own.
   ──────────────────────────────────────────────────────────────────────────── */

#critical-game-screen {
  /* Seat colours and the critical gold, from the mock's `classic` look [306]. Owner is colourblind,
     so SHAPE carries identity everywhere these colours do (▲ ■ ● ◆) and the escalation ramps size,
     count and motion — never colour alone (the GD-M1 check, which CRITICAL passes). */
  --cr-own0: #4C9BE8;
  --cr-own1: #E8A33D;
  --cr-own2: #4FBFA8;
  --cr-own3: #D46FC0;
  --cr-crit: #FFD166;
  /* ⚖️ KNOCKED OUT (owner, 2026-09-21): a hue NO SEAT OWNS, so red means only one thing. The load-
     bearing signal is still the ✕ + the struck name — red is the second channel, not the only one. */
  --cr-out: #E5484D;
  --cr-plate-ink: #16181d;
  --cr-empty-bg: rgba(255, 255, 255, .028);
  --cr-empty-bd: rgba(255, 255, 255, .10);
  --cr-neutral-bg: #262A31;
  --cr-neutral-bd: rgba(255, 255, 255, .17);
  --cr-board-bg: rgba(0, 0, 0, .24);
  --cr-board-bd: rgba(255, 255, 255, .06);
  --cr-slot-bg: #E9E3D5;
  --cr-slot-pip: #1d1f25;
  --cr-txt: #e9e8e4;
  --cr-dim: #8a8d94;
  --cr-panel: rgba(255, 255, 255, .032);
  --cr-line: rgba(255, 255, 255, .09);
  --cr-cellr: 10px;
}

/* ── setup card ─────────────────────────────────────────────────────────── */
#critical-game-screen .cr-setup-card { max-width: 560px; margin: 0 auto; text-align: left; }
#critical-game-screen .cr-setup-eyebrow {
  font-size: .78rem; letter-spacing: .08em; text-transform: uppercase; color: var(--cr-dim); margin-bottom: 6px;
}
#critical-game-screen .cr-setup-title { margin: 0 0 10px; font-size: 1.6rem; }
#critical-game-screen .cr-setup-blurb { margin: 0 0 14px; line-height: 1.5; color: var(--cr-txt); }
#critical-game-screen .cr-setup-row { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
#critical-game-screen .cr-setup-lab { font-weight: 600; }
#critical-game-screen .cr-opts { display: flex; gap: 6px; }
#critical-game-screen .cr-opt {
  min-width: 44px; padding: 8px 14px; border-radius: 10px; cursor: pointer;
  border: 1px solid var(--cr-line); background: var(--cr-panel); color: var(--cr-txt); font: inherit;
}
#critical-game-screen .cr-opt[data-on="1"] { border-color: var(--cr-own0); background: color-mix(in srgb, var(--cr-own0) 22%, transparent); }
#critical-game-screen .cr-setup-hint { font-size: .86rem; color: var(--cr-dim); line-height: 1.5; margin: 0 0 16px; }
#critical-game-screen .cr-start {
  width: 100%; padding: 13px; border-radius: 12px; border: 0; cursor: pointer;
  background: var(--cr-own0); color: #08131f; font: inherit; font-weight: 700; font-size: 1.02rem;
}

/* ── the root BoardFit scales ────────────────────────────────────────────── */
#critical-game-screen .cr-root {
  --cr-c: 66px; --cr-gap: 8px; --cr-pad: 12px;
  margin: 0 auto; color: var(--cr-txt);
}
#critical-game-screen:not(.cr-playing) #critical-area { display: none; }

/* the top bar — ⭐ a FIXED height, so the board below it never moves when the status changes */
#critical-game-screen .cr-bar {
  height: 42px; display: flex; align-items: center; gap: 14px; padding: 0 4px; overflow: hidden;
}
#critical-game-screen .cr-turn { font-weight: 700; font-variant-numeric: tabular-nums; flex: none; }
#critical-game-screen .cr-status {
  color: var(--cr-dim); font-size: .92rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* 🌐 The MP turn clock (critical_mp.js). Always BUILT (locked layout); shown only at a clocked table.
   The status line is the flexible column, so the clock takes a fixed slot at the bar's right end. */
#critical-game-screen .cr-clock { display: none; }
#critical-game-screen .cr-clock[data-on="1"] {
  display: inline-flex; align-items: center; gap: 7px; flex: none; margin-left: auto; width: 128px;
}
#critical-game-screen .cr-ctrack {
  flex: 1; height: 6px; border-radius: 3px; background: rgba(255, 255, 255, .12); overflow: hidden;
}
/* ⭐ The turn is COLOUR (.460): the bar is the colour of the seat on the clock (--cr-clk, set per paint). */
#critical-game-screen .cr-ctrack b { display: block; height: 100%; width: 100%; background: var(--cr-clk, var(--cr-dim)); border-radius: 3px; }
#critical-game-screen .cr-clock[data-low="1"] .cr-ctrack b { background: var(--cr-out); }
#critical-game-screen .cr-clock em {
  font-style: normal; font-weight: 800; font-size: 12px; min-width: 28px; text-align: right;
  font-variant-numeric: tabular-nums;
}
#critical-game-screen .cr-clock[data-low="1"] em { color: var(--cr-out); }
#critical-game-screen .cr-clock[data-run="0"] { opacity: .3; }

#critical-game-screen .cr-body { display: flex; gap: 10px; align-items: flex-start; }

/* ── ⚖️ CR-M6: the LEFT RAIL — chain counter and turn pill beside the board ─ */
#critical-game-screen .cr-rail { width: 264px; flex: none; display: flex; flex-direction: column; gap: 10px; }
#critical-game-screen .cr-seats { display: flex; flex-direction: column; gap: 6px; }
#critical-game-screen .cr-seat {
  height: 40px; display: flex; align-items: center; gap: 8px; padding: 0 10px; box-sizing: border-box;
  border-radius: 10px; border: 1px solid var(--cr-line); background: var(--cr-panel);
}
/* an unused seat is an OPEN SEAT — still built, still occupying its slot */
#critical-game-screen .cr-seat[data-open="1"] { opacity: .25; }
#critical-game-screen .cr-seat[data-open="1"] .cr-seatnm,
#critical-game-screen .cr-seat[data-open="1"] .cr-seatd { visibility: hidden; }
/* ⭐ SEAT CARDS ARE COLOUR-CODED (Squeak's pattern, squeak.css sq-seat-wash): every card carries a
   wash of its seat hue at rest, and the one whose turn it is a stronger wash + a breathing ring.
   ⛔ box-shadow and colour ONLY — the border stays 1px and the padding is untouched, or the
   locked-layout pin and the fit estimate move. */
#critical-game-screen .cr-seat[data-open="0"] {
  background: color-mix(in srgb, currentColor 13%, var(--cr-panel));
  border-color: color-mix(in srgb, currentColor 38%, transparent);
  transition: background .25s, border-color .25s, box-shadow .25s;
}
#critical-game-screen .cr-seat[data-turn="1"] {
  border-color: currentColor; background: color-mix(in srgb, currentColor 28%, var(--cr-panel));
  box-shadow: 0 0 14px 1px color-mix(in srgb, currentColor 55%, transparent);
  animation: cr-seatring 1.8s ease-in-out infinite;
}
@keyframes cr-seatring {
  0%, 100% { box-shadow: 0 0 10px 0 color-mix(in srgb, currentColor 45%, transparent); }
  50%      { box-shadow: 0 0 20px 3px color-mix(in srgb, currentColor 70%, transparent); }
}
/* ⚖️ KNOCKED OUT reads as OUT, not as "a bit faded": red card, ✕ in place of the shape, name struck. */
#critical-game-screen .cr-seat[data-seat][data-out="1"] {
  color: var(--cr-out); border-color: var(--cr-out);
  background: color-mix(in srgb, var(--cr-out) 20%, var(--cr-panel));
  box-shadow: none; animation: none;
}
#critical-game-screen .cr-seat[data-out="1"] .cr-sym { font-size: 0; }
#critical-game-screen .cr-seat[data-out="1"] .cr-sym::before { content: '✕'; font-size: .95rem; font-weight: 900; }
#critical-game-screen .cr-seat[data-out="1"] .cr-seatnm { text-decoration: line-through; text-decoration-thickness: 2px; opacity: .8; }
#critical-game-screen .cr-seat[data-out="1"] .cr-seatd { opacity: .6; }
#critical-game-screen .cr-seat[data-seat="0"] { color: var(--cr-own0); }
#critical-game-screen .cr-seat[data-seat="1"] { color: var(--cr-own1); }
#critical-game-screen .cr-seat[data-seat="2"] { color: var(--cr-own2); }
#critical-game-screen .cr-seat[data-seat="3"] { color: var(--cr-own3); }
#critical-game-screen .cr-seatnm { flex: 1; color: var(--cr-txt); font-size: .92rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#critical-game-screen .cr-seatd { color: var(--cr-dim); font-size: .86rem; font-variant-numeric: tabular-nums; flex: none; }
#critical-game-screen .cr-seatko {
  display: none; font-size: .64rem; font-weight: 800; letter-spacing: .08em;
  padding: 1px 5px; border-radius: 4px; background: var(--cr-out); color: #fff;
}
#critical-game-screen .cr-seat[data-out="1"] .cr-seatko { display: inline; }
#critical-game-screen .cr-sym { font-style: normal; flex: none; }

/* ⭐ THE CHAIN COUNTER — a FIXED 118×28 slot, ALWAYS present. It reads "chain —" at rest so the
   rail cannot reflow when a chain starts, which is the LOCKED LAYOUT rule applied to the one
   element that changes on every single wave. */
#critical-game-screen .cr-chain {
  --cr-cbd: 1.5px; --cr-cbg: 14%; --cr-cglow: 8px;
  box-sizing: border-box; display: flex; align-items: center; justify-content: center;
  border-radius: 8px; font-variant-numeric: tabular-nums; font-weight: 700; font-size: .92rem;
  border: var(--cr-cbd) solid var(--cr-crit);
  background: color-mix(in srgb, var(--cr-crit) var(--cr-cbg), transparent);
  color: var(--cr-txt); overflow: hidden; white-space: nowrap;
}
#critical-game-screen .cr-chain[data-on="0"] { border-color: var(--cr-line); background: var(--cr-panel); color: var(--cr-dim); }
#critical-game-screen .cr-chain[data-on="1"] { box-shadow: 0 0 var(--cr-cglow) color-mix(in srgb, var(--cr-crit) 60%, transparent); }
/* A/B names so the pop RETRIGGERS on every wave — a single name would only animate once. */
#critical-game-screen .cr-chain[data-on="1"][data-pop="a"] { animation: cr-popa .22s ease-out; }
#critical-game-screen .cr-chain[data-on="1"][data-pop="b"] { animation: cr-popb .22s ease-out; }
@keyframes cr-popa { 0% { transform: scale(1); } 40% { transform: scale(1.12); } 100% { transform: scale(1); } }
@keyframes cr-popb { 0% { transform: scale(1); } 40% { transform: scale(1.12); } 100% { transform: scale(1); } }

#critical-game-screen .cr-pill {
  height: 28px; display: flex; align-items: center; justify-content: center; box-sizing: border-box;
  border-radius: 8px; font-size: .88rem; font-weight: 600;
  border: 1px solid var(--cr-line); background: var(--cr-panel);
}
#critical-game-screen .cr-pill[data-seat="0"] { color: var(--cr-own0); }
#critical-game-screen .cr-pill[data-seat="1"] { color: var(--cr-own1); }
#critical-game-screen .cr-pill[data-seat="2"] { color: var(--cr-own2); }
#critical-game-screen .cr-pill[data-seat="3"] { color: var(--cr-own3); }

/* the feed — a fixed box so the rail's height never depends on how much has happened */
#critical-game-screen .cr-feed {
  height: 168px; overflow: hidden; display: flex; flex-direction: column; gap: 4px;
  border-radius: 10px; border: 1px solid var(--cr-line); background: var(--cr-panel); padding: 8px;
}
#critical-game-screen .cr-fline {
  display: flex; align-items: center; gap: 6px; font-size: .82rem; color: var(--cr-dim);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  /* ⛔ overflow:hidden lets a flex item shrink BELOW its text — a short feed squashed 7 lines into a few px
     each (the phone's 48px box, 2026-09-23). A line that does not fit is clipped off the end, never crushed. */
  flex-shrink: 0;
}
#critical-game-screen .cr-fline[data-seat="0"] .cr-sym { color: var(--cr-own0); }
#critical-game-screen .cr-fline[data-seat="1"] .cr-sym { color: var(--cr-own1); }
#critical-game-screen .cr-fline[data-seat="2"] .cr-sym { color: var(--cr-own2); }
#critical-game-screen .cr-fline[data-seat="3"] .cr-sym { color: var(--cr-own3); }

/* ── the board ───────────────────────────────────────────────────────────── */
#critical-game-screen .cr-boardwrap { position: relative; flex: 1; display: flex; align-items: center; justify-content: center; }
#critical-game-screen .cr-grid {
  --cr-amp: .6px; --cr-shper: .3s; --cr-glow: 18px; --cr-glowsp: 0px; --cr-glowin: 10px;
  --cr-mover: var(--cr-own0);
  position: relative; display: grid; box-sizing: border-box;
  grid-template-columns: repeat(5, var(--cr-c));
  grid-template-rows: repeat(6, var(--cr-c));
  gap: var(--cr-gap); padding: var(--cr-pad);
  border-radius: 14px; background: var(--cr-board-bg); border: 1px solid var(--cr-board-bd);
  /* ⭐ THE GLOW IS THE TURN SIGNAL (owner, 2026-09-21) — the board is ringed in the ACTING seat's
     colour at rest too, not only mid-chain, so it carries whose turn it is now the cells are no
     longer greyed. A resting 3px spread on top of the chain-driven one. */
  border-color: color-mix(in srgb, var(--cr-mover) 55%, transparent);
  box-shadow: 0 0 var(--cr-glow) calc(3px + var(--cr-glowsp)) color-mix(in srgb, var(--cr-mover) 55%, transparent),
              inset 0 0 var(--cr-glowin) color-mix(in srgb, var(--cr-mover) 30%, transparent);
  transition: border-color .3s;
  z-index: 1;
}
/* ⛔ THE SHAKE TRANSFORMS THE GRID, which is exactly why the particle layer is its SIBLING and not
   its child — shaking the sparks with the board destroys the effect. */
#critical-game-screen .cr-grid[data-shake="1"] { animation: cr-shake var(--cr-shper) linear infinite; }
@keyframes cr-shake {
  0%   { transform: translate(0, 0); }
  25%  { transform: translate(var(--cr-amp), calc(var(--cr-amp) * -.6)); }
  50%  { transform: translate(calc(var(--cr-amp) * -.8), var(--cr-amp)); }
  75%  { transform: translate(calc(var(--cr-amp) * .5), calc(var(--cr-amp) * .7)); }
  100% { transform: translate(0, 0); }
}

/* ── a cell ──────────────────────────────────────────────────────────────── */
#critical-game-screen .cr-cell {
  position: relative; width: var(--cr-c); height: var(--cr-c); padding: 0; margin: 0;
  display: flex; align-items: center; justify-content: center; box-sizing: border-box;
  border-radius: var(--cr-cellr); appearance: none; -webkit-appearance: none; font: inherit;
  transition: background .16s, box-shadow .16s, transform .1s, filter .16s;
  cursor: default; background: var(--cr-empty-bg); border: 1.5px dashed var(--cr-empty-bd);
}
#critical-game-screen .cr-cell[data-o="e"] { background: var(--cr-empty-bg); border: 1.5px dashed var(--cr-empty-bd); }
#critical-game-screen .cr-cell[data-o="n"] {
  background: repeating-linear-gradient(45deg, rgba(255,255,255,.12) 0 4px, rgba(0,0,0,0) 4px 9px), var(--cr-neutral-bg);
  border: 1.5px solid var(--cr-neutral-bd);
}
#critical-game-screen .cr-cell[data-o="0"] { background: color-mix(in srgb, var(--cr-own0) 24%, var(--cr-plate-ink)); border: 2px solid var(--cr-own0); }
#critical-game-screen .cr-cell[data-o="1"] { background: color-mix(in srgb, var(--cr-own1) 24%, var(--cr-plate-ink)); border: 2px solid var(--cr-own1); }
#critical-game-screen .cr-cell[data-o="2"] { background: color-mix(in srgb, var(--cr-own2) 24%, var(--cr-plate-ink)); border: 2px solid var(--cr-own2); }
#critical-game-screen .cr-cell[data-o="3"] { background: color-mix(in srgb, var(--cr-own3) 24%, var(--cr-plate-ink)); border: 2px solid var(--cr-own3); }

/* a cell you can actually take gets the pointer and the hover; one you cannot gets NEITHER —
   absence of feedback is the signal (the review's "two flavours of not allowed"). */
#critical-game-screen .cr-cell[data-legal="1"] { cursor: pointer; }
#critical-game-screen .cr-cell[data-legal="1"]:hover { transform: translateY(-2px); }
#critical-game-screen .cr-cell[data-legal="1"]:active { transform: translateY(1px); box-shadow: inset 0 3px 8px rgba(0,0,0,.5); filter: brightness(.88); }
/* ⚖️ `data-lock` (another player is acting) is NO LONGER PAINTED GREY — owner, 2026-09-21: the
   desaturated board took the colour out of the very thing the game is about watching. Whose turn it
   is now reads off the board glow + the glowing seat card. The attribute stays as the hook the suite
   samples; the cells are disabled either way. */
#critical-game-screen .cr-cell[data-nope="1"] { animation: cr-nope .34s ease-out; }
@keyframes cr-nope { 0%,100% { transform: translateX(0); } 25% { transform: translateX(-3px); } 75% { transform: translateX(3px); } }

/* ⚖️ CR-M3 — the breathing ring + the gold "!" go ONLY on criticals the mover can set off. */
#critical-game-screen .cr-cell[data-crit="1"] { animation: cr-crit 1.5s ease-in-out infinite; }
@keyframes cr-crit {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--cr-crit) 70%, transparent); }
  50%      { box-shadow: 0 0 0 3px color-mix(in srgb, var(--cr-crit) 70%, transparent); }
}
#critical-game-screen .cr-bang {
  position: absolute; top: -4px; right: -4px; display: none; font-style: normal; font-weight: 900;
  font-size: calc(var(--cr-c) * .24); line-height: 1; color: var(--cr-crit);
  text-shadow: 0 1px 2px rgba(0,0,0,.8); pointer-events: none;
}
#critical-game-screen .cr-cell[data-crit="1"] .cr-bang { display: block; }
/* the firing flash */
#critical-game-screen .cr-cell[data-fire="1"] {
  animation: cr-fire .22s ease-out;
  box-shadow: 0 0 0 3px var(--cr-crit), 0 0 24px 4px color-mix(in srgb, var(--cr-crit) 55%, transparent);
}
@keyframes cr-fire { 0% { transform: scale(1); } 45% { transform: scale(1.1); } 100% { transform: scale(1); } }
/* ⚖️ CR-M1 — the BOARD TAKEN sweep, in the winner's colour, as it reaches each cell */
#critical-game-screen .cr-cell[data-beat="1"] { animation: cr-beat .42s ease-out; }
@keyframes cr-beat {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--cr-mover) 90%, transparent); transform: scale(1); }
  40%  { box-shadow: 0 0 18px 5px color-mix(in srgb, var(--cr-mover) 75%, transparent); transform: scale(1.07); }
  100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--cr-mover) 0%, transparent); transform: scale(1); }
}

/* the notches — one per REAL neighbour, on that neighbour's edge, so a cell's LIMIT is readable
   without counting: two notches = a corner (limit 2), three = an edge, four = inside. */
#critical-game-screen .cr-notch { position: absolute; background: currentColor; border-radius: 2px; opacity: .55; }
#critical-game-screen .cr-cell[data-o="e"] .cr-notch { color: var(--cr-empty-bd); }
#critical-game-screen .cr-cell[data-o="n"] .cr-notch { color: var(--cr-neutral-bd); }
#critical-game-screen .cr-cell[data-o="0"] .cr-notch { color: var(--cr-own0); }
#critical-game-screen .cr-cell[data-o="1"] .cr-notch { color: var(--cr-own1); }
#critical-game-screen .cr-cell[data-o="2"] .cr-notch { color: var(--cr-own2); }
#critical-game-screen .cr-cell[data-o="3"] .cr-notch { color: var(--cr-own3); }
#critical-game-screen .cr-nu { top: 3px; left: 50%; transform: translateX(-50%); width: calc(var(--cr-c) * .17); height: 2.5px; }
#critical-game-screen .cr-nd { bottom: 3px; left: 50%; transform: translateX(-50%); width: calc(var(--cr-c) * .17); height: 2.5px; }
#critical-game-screen .cr-nl { left: 3px; top: 50%; transform: translateY(-50%); height: calc(var(--cr-c) * .17); width: 2.5px; }
#critical-game-screen .cr-nr { right: 3px; top: 50%; transform: translateY(-50%); height: calc(var(--cr-c) * .17); width: 2.5px; }
/* A cell on an edge has no neighbour that way, so it has no notch that way. ⛔ POSITION decides this,
   not the limit: a blanket `[data-lim="2"] .cr-nu, [data-lim="2"] .cr-nl { display:none }` looks like
   the same rule and is not — it hid the UP and LEFT notches on every corner, so the BOTTOM-RIGHT one
   (whose down and right notches these nth-child rules already hide) drew none at all. */
#critical-game-screen .cr-grid .cr-cell:nth-child(-n+5) .cr-nu { display: none; }
#critical-game-screen .cr-grid .cr-cell:nth-child(n+26) .cr-nd { display: none; }
#critical-game-screen .cr-grid .cr-cell:nth-child(5n+1) .cr-nl { display: none; }
#critical-game-screen .cr-grid .cr-cell:nth-child(5n) .cr-nr { display: none; }

/* the owner shape, top-left — identity that survives greyscale */
#critical-game-screen .cr-osym {
  position: absolute; top: 4px; left: 4px; width: calc(var(--cr-c) * .15); height: calc(var(--cr-c) * .15);
  display: none; background: currentColor;
}
#critical-game-screen .cr-cell[data-o="0"] .cr-osym { display: block; color: var(--cr-own0); clip-path: polygon(50% 0%, 100% 100%, 0% 100%); }
#critical-game-screen .cr-cell[data-o="1"] .cr-osym { display: block; color: var(--cr-own1); border-radius: 1px; }
#critical-game-screen .cr-cell[data-o="2"] .cr-osym { display: block; color: var(--cr-own2); border-radius: 50%; }
#critical-game-screen .cr-cell[data-o="3"] .cr-osym { display: block; color: var(--cr-own3); clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%); }

/* the die slot — 56% of the cell, pips at 20% of the slot [335, 381–386] */
#critical-game-screen .cr-slot {
  --cr-slotms: 150ms;
  width: calc(var(--cr-c) * .56); height: calc(var(--cr-c) * .56);
  display: flex; align-items: center; justify-content: center; flex-wrap: wrap;
  gap: calc(var(--cr-c) * .035);
  border-radius: 7px; background: var(--cr-slot-bg); box-sizing: border-box;
  /* ⭐ DICE GROW IN AND SHRINK AWAY (owner, 2026-09-20). A burst empties one cell and fills its
     neighbours, and doing that by swapping visibility made dice pop in and out of existence — jarring
     at exactly the moment the board is meant to feel alive. A slight overshoot on the way in reads as
     a die LANDING; the way out is plain and quicker, because it is being taken from you.
     ⛔ It is a TRANSFORM, so it reflows nothing and the LOCKED LAYOUT pin is untouched — the slot's
     box never moves. And it keys off data-n="0" alone, so 1→2 pips does NOT rescale. */
  transform: scale(1); opacity: 1; transform-origin: center;
  transition: transform var(--cr-slotms) cubic-bezier(.34, 1.42, .64, 1),
              opacity calc(var(--cr-slotms) * .6) linear;
}
#critical-game-screen .cr-slot[data-n="0"] {
  transform: scale(.3); opacity: 0;
  transition: transform calc(var(--cr-slotms) * .8) cubic-bezier(.4, 0, .7, .2),
              opacity calc(var(--cr-slotms) * .55) linear;
}
/* ⭐ PIP SOCKETS — a die shows its whole capacity, filled and empty (owner, 2026-09-20). The empty
   ones are outlines on the cream face, so "how full is this, and how full can it get" is one glance
   rather than a rule you had to read. Sized per LIMIT so four still fit across the slot; they wrap
   if a mid-chain cell is momentarily over its limit. */
#critical-game-screen .cr-pip {
  width: calc(var(--cr-c) * .112); height: calc(var(--cr-c) * .112);
  border-radius: 50%; flex: none; box-sizing: border-box;
}
#critical-game-screen .cr-pip[data-on="1"] { background: var(--cr-slot-pip); }
#critical-game-screen .cr-pip[data-on="0"] {
  background: transparent;
  box-shadow: inset 0 0 0 1.6px color-mix(in srgb, var(--cr-slot-pip) 45%, transparent);
}
#critical-game-screen .cr-slot[data-lim="2"] .cr-pip { width: calc(var(--cr-c) * .13); height: calc(var(--cr-c) * .13); }
#critical-game-screen .cr-slot[data-lim="3"] .cr-pip { width: calc(var(--cr-c) * .112); height: calc(var(--cr-c) * .112); }
#critical-game-screen .cr-slot[data-lim="4"] .cr-pip { width: calc(var(--cr-c) * .095); height: calc(var(--cr-c) * .095); }

/* ── the FX layer — a SIBLING of the grid, in grid coordinates ───────────── */
#critical-game-screen .cr-fx {
  position: absolute; left: 50%; top: 50%; width: 0; height: 0; pointer-events: none; z-index: 5;
  transform: translate(calc(-1 * (5 * var(--cr-c) + 4 * var(--cr-gap)) / 2),
                       calc(-1 * (6 * var(--cr-c) + 5 * var(--cr-gap)) / 2));
}
#critical-game-screen .cr-part, #critical-game-screen .cr-ring, #critical-game-screen .cr-dart {
  position: absolute; pointer-events: none; will-change: transform, opacity;
}
#critical-game-screen .cr-part { border-radius: 50%; animation-name: cr-ball; animation-timing-function: linear; animation-fill-mode: forwards; }
/* the 5-step ballistic curve [22]: out, then gravity, scaling 1 → .5, fading from 60% */
@keyframes cr-ball {
  0%   { transform: translate(0, 0) scale(1); opacity: 1; }
  25%  { transform: translate(calc(var(--dx) * .45), calc(var(--dy) * .55)) scale(.95); opacity: 1; }
  50%  { transform: translate(calc(var(--dx) * .75), calc(var(--dy) * .85 + var(--fall) * .1)) scale(.85); opacity: 1; }
  60%  { transform: translate(calc(var(--dx) * .85), calc(var(--dy) * .95 + var(--fall) * .2)) scale(.78); opacity: 1; }
  100% { transform: translate(var(--dx), calc(var(--dy) + var(--fall))) scale(.5); opacity: 0; }
}
#critical-game-screen .cr-ring {
  border-radius: 50%; border-style: solid; border-color: var(--cr-crit);
  animation-name: cr-ring; animation-timing-function: ease-out; animation-fill-mode: forwards;
}
@keyframes cr-ring { 0% { transform: scale(.3); opacity: .95; } 100% { transform: scale(1); opacity: 0; } }
/* ⚖️ CR-M5 — a pip that actually TRAVELS to its neighbour. The mock's cr-fly went (0,0) → (0,0). */
#critical-game-screen .cr-dart {
  border-radius: 50%; animation-name: cr-dart; animation-timing-function: cubic-bezier(.3,.7,.3,1); animation-fill-mode: forwards;
}
@keyframes cr-dart {
  0%   { transform: translate(0, 0) scale(.7); opacity: 0; }
  18%  { opacity: 1; }
  100% { transform: translate(var(--dx), var(--dy)) scale(1); opacity: 0; }
}

/* the screen aura [521–523] */
#critical-game-screen .cr-aura {
  position: absolute; inset: -40%; pointer-events: none; z-index: 0; opacity: 0;
  transition: opacity .16s linear;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--cr-mover) 34%, transparent), transparent 72%);
}
/* the milestone numeral [487–500] */
#critical-game-screen .cr-mile {
  position: absolute; left: 0; right: 0; top: 52%; display: flex; justify-content: center;
  pointer-events: none; z-index: 6; opacity: 0;
}
#critical-game-screen .cr-mile[data-on="1"] { animation: cr-mile .76s ease-out; }
#critical-game-screen .cr-milenum { font-weight: 900; color: var(--cr-crit); text-shadow: 0 0 24px color-mix(in srgb, var(--cr-crit) 70%, transparent); }
@keyframes cr-mile {
  0%   { opacity: 0; transform: scale(.6); }
  25%  { opacity: 1; transform: scale(1.08); }
  70%  { opacity: 1; transform: scale(1); }
  100% { opacity: 0; transform: scale(1.02); }
}

/* ⚖️ CR-M1 — the BOARD TAKEN label. It takes the SAME slot treatment as the counter (fixed box,
   contents only) and sits over the board rather than replacing anything. */
/* ⭐ A CARD, not bare text (owner, 2026-09-20). It appears over the board at its most crowded, and
   the die faces are a pale cream — coloured letters laid straight over them vanished. A dark panel
   gives the type something to sit on; the mover's colour stays as the border and the glow, so the
   winner is still named by colour without the words depending on it. */
#critical-game-screen .cr-taken {
  position: absolute; left: 0; right: 0; top: 50%; pointer-events: none; z-index: 7;
  display: flex; justify-content: center; opacity: 0;
}
#critical-game-screen .cr-takencard {
  padding: 12px 26px; border-radius: 14px;
  font-weight: 900; letter-spacing: .14em; font-size: 30px; white-space: nowrap;
  color: #fff;
  background: rgba(10, 11, 14, .88);
  border: 2px solid var(--cr-mover);
  box-shadow: 0 0 34px color-mix(in srgb, var(--cr-mover) 55%, transparent),
              0 12px 30px -12px rgba(0, 0, 0, .9),
              inset 0 0 22px color-mix(in srgb, var(--cr-mover) 22%, transparent);
  text-shadow: 0 0 18px color-mix(in srgb, var(--cr-mover) 80%, transparent);
}
#critical-game-screen .cr-taken[data-on="1"] { animation: cr-taken .7s ease-out forwards; }
@keyframes cr-taken {
  0%   { opacity: 0; transform: translateY(8px) scale(.94); }
  22%  { opacity: 1; transform: translateY(0) scale(1.04); }
  80%  { opacity: 1; transform: translateY(0) scale(1); }
  100% { opacity: .92; transform: translateY(0) scale(1); }
}

/* ── ⚖️ CR-M4: the hover tooltip ─────────────────────────────────────────── */
#critical-game-screen .cr-tip {
  position: absolute; left: 0; top: 0; z-index: 8; pointer-events: none; opacity: 0;
  padding: 5px 9px; border-radius: 7px; white-space: nowrap; font-size: .8rem;
  background: rgba(12, 13, 16, .96); border: 1px solid var(--cr-line); color: var(--cr-txt);
  box-shadow: 0 8px 20px -10px rgba(0, 0, 0, .9);
}
#critical-game-screen .cr-tip[data-on="1"] { opacity: 1; }
/* the little tail, which has to flip with the tip (CR-M4) */
#critical-game-screen .cr-tip::after {
  content: ''; position: absolute; left: 50%; margin-left: -5px; border: 5px solid transparent;
}
#critical-game-screen .cr-tip[data-below="0"]::after { top: 100%; border-top-color: rgba(12, 13, 16, .96); }
#critical-game-screen .cr-tip[data-below="1"]::after { bottom: 100%; border-bottom-color: rgba(12, 13, 16, .96); }

/* ── phone ───────────────────────────────────────────────────────────────── */
@media (max-width: 999px) {
  /* the same opt-out as the desktop block — a phone board is narrower than 640px, but the wrap's
     1.5rem padding still eats 48px of a 360px screen */
  #critical-game-screen.cr-playing .wrap { max-width: none; padding: 0 2px; }
  #critical-game-screen .cr-body { flex-direction: column; gap: 8px; }
  #critical-game-screen .cr-rail { width: 100%; }
  /* ⛔ PT0922-CF-1: the column's `align-items: flex-start` shrank the wrap to the grid, so a HEIGHT-bound
     board (60px cells at 390×844, the online clock/chat) sat flush left with the slack all on the right.
     CENTRED, not stretched: the wrap stays exactly the grid's size, so the aura / sparks / tip / milestone
     overlays positioned inside it are untouched. */
  #critical-game-screen .cr-boardwrap { align-self: center; }
  #critical-game-screen .cr-seats { flex-direction: row; flex-wrap: wrap; }
  #critical-game-screen .cr-seat { flex: 1 1 calc(50% - 3px); min-width: 0; }
  /* ⭐ the counter and the pill share ONE row on a phone, both still fixed-size */
  #critical-game-screen .cr-chain, #critical-game-screen .cr-pill { align-self: center; }
  /* ⚖️ OWNER, 2026-09-23 (on .499): NO FEED ON A PHONE. A 48px box can't hold its 7 lines (they rendered
     squashed into each other and unreadable), and nothing in it is needed to play: the status line,
     seat cards, chain counter and turn pill carry the state, and every line is in ⏱ Log. The space goes
     to the board (crFit measures the rail). The short tier's own `display: none` below is now moot on phones. */
  #critical-game-screen .cr-feed { display: none; }
  #critical-game-screen .cr-takencard { font-size: 20px; padding: 9px 18px; letter-spacing: .1em; }
}

/* ⛔ THE SHORT-PHONE TIER. Set by crFit when the board is already at its 30px floor and STILL cannot
   clear the chat bar — measured, not guessed at a breakpoint, because whether it is needed depends on
   the seat count as much as the height (375×600 at four seats needs it; the same phone at two does
   not). The feed collapses because it is the one thing a player can lose without losing the game
   state: whose turn it is, who holds what, and the chain counter all stay. */
#critical-game-screen .cr-root[data-short="1"] .cr-feed { display: none; }
#critical-game-screen .cr-root[data-short="1"] .cr-seat { height: 32px; padding: 0 7px; }
#critical-game-screen .cr-root[data-short="1"] .cr-seatnm { font-size: .82rem; }
#critical-game-screen .cr-root[data-short="1"] .cr-rail { gap: 6px; }
#critical-game-screen .cr-root[data-short="1"] .cr-bar { height: 34px; }

/* ── desktop: the fixed box BoardFit scales ──────────────────────────────── */
@media (min-width: 1000px) {
  /* ⛔⛔ THE WRAP HAS TO OPT OUT OF THE APP'S CONTENT COLUMN. style.css:352 makes every `.wrap`
     `max-width: 640px; overflow: hidden`, so a 1280px root inside one is simply CLIPPED — the board
     sat half off the right edge of the screen and no test said a word, because every suite that
     measures it reads the ROOT (which is a correct 1280×553) rather than what the viewer can see.
     Setting --pgr-shellMaxW is NOT enough on its own; the column cap is a separate rule. */
  #critical-game-screen .wrap { max-width: none; padding-left: 0; padding-right: 0; }
  /* ⛔ A MEASUREMENT with three copies — frontend/critical.js CR_FIT_W/H, board-fit.js and here.
     critical-board.test.html asserts all three agree. ⛔⛔ 700 × 550 is the CONTENT's size, not the
     shell's: a 5×6 board is portrait, and a 1280-wide box left ~590px dead, which BoardFit then
     scaled the whole root up to swallow — driving the height off the bottom of the window. */
  #critical-game-screen .cr-root { width: 700px; height: 550px; }
  /* the board wrap hugs the grid, so there is no slack for the grid to float in */
  #critical-game-screen .cr-boardwrap { flex: none; }
}

/* ── the END SCREEN ──────────────────────────────────────────────────────────
   ⛔⛔ GameEndScreen does document.body.appendChild, so the popup is a SIBLING of the game screen
   and NONE of the --cr-* tokens above reach it (measured on Gem Duel `.424`: a ring using the board's
   accent resolved to currentColor and the celebration would have shipped INVISIBLE). These rules
   therefore declare their own colours and hang off .ges-*, never off the board's classes. */
.ges-body .cr-endrows { display: flex; flex-direction: column; gap: 6px; }
.ges-body .cr-endrow {
  --cr-e0: #4C9BE8; --cr-e1: #E8A33D; --cr-e2: #4FBFA8; --cr-e3: #D46FC0;
  display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: 9px;
  background: rgba(255, 255, 255, .05); border: 1px solid rgba(255, 255, 255, .09);
}
.ges-body .cr-endrow[data-win="1"] { border-color: #FFD166; background: rgba(255, 209, 102, .14); }
.ges-body .cr-endrow[data-out="1"] { opacity: .6; }
.ges-body .cr-endnm { flex: 1; display: flex; align-items: center; gap: 7px; font-weight: 600; }
.ges-body .cr-endnm .cr-sym { font-style: normal; }
.ges-body .cr-endst { font-size: .82rem; opacity: .72; }
.ges-body .cr-endsc { font-weight: 700; font-variant-numeric: tabular-nums; }
.ges-body .cr-endnote { margin-top: 8px; font-size: .82rem; opacity: .7; }

.ges-body .cr-pb { display: flex; flex-direction: column; gap: 6px; }
.ges-body .cr-pbrow {
  position: relative; display: flex; align-items: center; gap: 10px; padding: 8px 10px;
  border-radius: 9px; background: rgba(255, 255, 255, .05); border: 1px solid rgba(255, 255, 255, .09);
}
.ges-body .cr-pbrow[data-beat="1"] { border-color: #FFD166; background: rgba(255, 209, 102, .12); }
.ges-body .cr-pbring {
  position: absolute; inset: -2px; border-radius: 11px; pointer-events: none;
  border: 2px solid #FFD166; animation: cr-pbring 1.4s ease-out 2;
}
@keyframes cr-pbring { 0% { box-shadow: 0 0 0 0 rgba(255, 209, 102, .7); } 100% { box-shadow: 0 0 0 12px rgba(255, 209, 102, 0); } }
.ges-body .cr-pbl { flex: 1; font-weight: 600; }
.ges-body .cr-pbv { font-weight: 800; font-variant-numeric: tabular-nums; }
.ges-body .cr-pbg { font-size: .8rem; opacity: .74; }
.ges-body .cr-pbnew {
  font-style: normal; font-weight: 900; font-size: .66rem; letter-spacing: .08em;
  padding: 1px 5px; border-radius: 4px; background: #FFD166; color: #1a1408;
}

/* ── reduced motion: keep the information, drop the movement ─────────────── */
@media (prefers-reduced-motion: reduce) {
  #critical-game-screen .cr-grid[data-shake="1"],
  #critical-game-screen .cr-cell[data-crit="1"],
  #critical-game-screen .cr-cell[data-fire="1"],
  #critical-game-screen .cr-cell[data-beat="1"],
  #critical-game-screen .cr-chain[data-pop],
  #critical-game-screen .cr-seat[data-turn="1"],
  #critical-game-screen .cr-part, #critical-game-screen .cr-ring, #critical-game-screen .cr-dart,
  .ges-body .cr-pbring { animation: none !important; }
  /* the "!" badge is the critical signal once the breathing ring is gone, so it stays */
}
