/* ===========================================================================
   shell2.css — THE BERTA TRAIL, the new grammar.
   Built to _gauntlet/loop0/DESIGN-SYSTEM.md §2 (the persistent frame),
   §3 (the eight tokens), §4 (colour and type), §5 (the hierarchy rule)
   and §8.4 (TRAVEL).

   ADDITIVE. This file is loaded AFTER styles.css and overrides nothing in it
   except `#frame` while `.s2on` is stamped. Every screen shell2.js has not
   taken over still renders through the old stylesheet, untouched.

   ONE MEASUREMENT NOTE, because it decides how everything below is written.
   tools/_measure.js counts an element as INK when it paints its own text OR
   carries a background-COLOUR at alpha >= 0.55. A panel painted as a
   background-IMAGE (a gradient) covers the same pixels and is not counted —
   which is exactly the correction DESIGN-SYSTEM §10 defect 2 asks for on the
   letterbox, and it is what both winning mocks do throughout. Every fill in
   this file is therefore a gradient, and the honest number the frame is
   judged on is BANDS + SUBJ% + CHARS beside INK, never INK alone.

   Every pixel number here is at 952x427 and there is no other viewport.
   =========================================================================== */

:root{
  /* --- §4 · THE PALETTE — nine values, seven jobs ------------------------ */
  --s2-asphalt:#05070b;              /* the deepest ground, the letterbox     */
  --s2-steel-a:#11161f;              /* every control that is not the primary */
  --s2-steel-b:#080b11;
  --s2-keyline:#3f4753;              /* the 1px edge on steel. Never a fill.  */
  --s2-sign-a:#0e6f3c;               /* the SIGN board. Scenery, never a ctrl */
  --s2-sign-b:#0a4f2b;
  --s2-go:#23c46a;                   /* GO GREEN — THE ACCENT. One per frame. */
  --s2-go-key:#8bf0b6;
  --s2-go-ink:#04150b;
  --s2-ivory:#f2eee4;                /* type, and the sign's 2px keyline      */
  --s2-mute:#98a2af;                 /* keys, sub-lines, neutral price tags   */
  --s2-mute-hi:#ccd3dc;              /* the same job, over a BRIGHT plate     */
  --s2-alarm:#ff5a3c;                /* under a floor, a loss, the alert edge */
  --s2-amber:#ffb02e;                /* money, and the `!` mark               */
  --s2-off-key:#242a33;
  --s2-off-tx:#5c6675;

  /* --- §4 · THE TYPE RAMP — five steps, every step >=1.25x --------------- */
  --s2-t-goal:34px;                  /* the goal-line value; the ending h1    */
  --s2-t-sign:26px;                  /* the sign's numerals                   */
  --s2-t-label:20px;                 /* sign place words, verb labels, status */
  --s2-t-body:15px;                  /* the alert, the qualifier, event body  */
  --s2-t-key:12px;                   /* status keys, price tags, DAY n        */

  /* --- §4 · THE FACE — system stacks, no shipped font file --------------- */
  --s2-hwy:"Arial Narrow","Roboto Condensed","Liberation Sans Narrow",Arial,Helvetica,sans-serif;
  --s2-voice:Georgia,"Times New Roman","Tinos","Droid Serif",serif;
}

/* ===========================================================================
   THE STAGE BOX — 952x427, scaled, never reflowed.
   §9.6.2: the composition is authored once at the deciding viewport and
   scaled with a transform, so a 1920 desktop and a 952 handset show the same
   picture rather than two different layouts.
   =========================================================================== */
#frame.s2on{display:block;padding:0}

.s2{
  position:absolute;left:50%;top:50%;
  width:952px;height:427px;margin:-213.5px 0 0 -476px;
  transform:scale(var(--s2-scale,1));transform-origin:50% 50%;
  font-family:var(--s2-hwy);font-weight:700;font-size:15px;color:var(--s2-ivory);
  letter-spacing:.04em;line-height:1;
  -webkit-font-smoothing:antialiased;
}
.s2 *{box-sizing:border-box}

/* --- THE FENCE ------------------------------------------------------------
   styles.css is 148 top-level rules deep and it owns generic tokens this file
   also needs — `.choice` above all, which the playtest finds option buttons
   by and which arrives carrying a flex layout, a clamped font size, a chamfer,
   a drop shadow and a 5px accent bar in ::before. Rather than fight each one
   with a more specific selector, everything inside .s2 starts from nothing.

   `:where()` is what makes this safe: it contributes ZERO specificity, so this
   rule weighs exactly (0,1,0) — the same as a bare `.choice` — and wins on
   source order alone because shell2.css is linked after styles.css. Every
   token rule below it is (0,1,0) or higher AND later, so nothing in this file
   has to be written defensively. Remove the :where() and this rule would beat
   the whole stylesheet it is introducing.
-------------------------------------------------------------------------- */
.s2 :where(*){
  margin:0;padding:0;border:0;outline:0;background:none;box-shadow:none;
  filter:none;clip-path:none;transform:none;transition:none;animation:none;
  text-shadow:none;min-width:0;min-height:0;max-width:none;
  font:inherit;color:inherit;letter-spacing:inherit;text-transform:none;
  line-height:1;text-align:left;position:static;display:block;
  -webkit-appearance:none;appearance:none;
}
.s2 :where(*)::before,.s2 :where(*)::after{content:none}
.s2 :where(*:hover),.s2 :where(*:active),.s2 :where(*:focus){
  background:none;transform:none;filter:none;box-shadow:none;opacity:1}

/* every text node in here is its own tight box: line-height 1 and
   inline-block, so a run measures the glyphs and not a paragraph of air */
.s2 .t{display:inline-block;line-height:1;white-space:nowrap}

/* the two legibility washes. Gradients: they cover nothing opaquely and they
   are how the sky reads behind 12px type at the top and the road reads behind
   a button row at the bottom. §6.6 — the weather is the sky, not a chrome row. */
.s2-sky{position:absolute;left:0;right:0;top:0;height:170px;z-index:1;pointer-events:none;
  background:linear-gradient(180deg,rgba(4,7,12,.62) 0,rgba(4,7,12,.22) 62%,rgba(4,7,12,0) 100%)}
.s2-road{position:absolute;left:0;right:0;bottom:0;height:150px;z-index:1;pointer-events:none;
  background:linear-gradient(0deg,rgba(4,6,10,.88) 0,rgba(4,6,10,.56) 44%,rgba(4,6,10,.16) 76%,rgba(4,6,10,0) 100%)}

/* ===========================================================================
   §2 · THE NINE PERSISTENT-FRAME SLOTS
   Fixed x, fixed y, fixed size, every screen that has them. They never move,
   never resize, never reorder. A screen that needs a slot to move does not
   get that slot.
   =========================================================================== */
.s2-latch  {position:absolute;left:12px; top:10px;  width:44px; height:44px; z-index:6}
.s2-snd    {position:absolute;left:62px;top:10px;width:44px;height:44px;z-index:6;
            border:0;padding:0;cursor:pointer;border-radius:8px;color:#aab2bd;
            background:linear-gradient(180deg,rgba(23,28,37,.92),rgba(9,12,17,.92));
            box-shadow:0 0 0 1px rgba(120,130,145,.42),0 3px 8px rgba(0,0,0,.5);
            display:flex;align-items:center;justify-content:center}
.s2-snd:hover,.s2-snd:focus-visible{color:#f2eee4;box-shadow:0 0 0 2px rgba(160,180,210,.7),0 3px 8px rgba(0,0,0,.6)}
.menuwrap{position:absolute;inset:0;z-index:99!important}
/* THE RAIL GREW 72px AND ANCHORED TO ITS RIGHT EDGE, AND THE DENOMINATOR IS
   WHY. See the T3 block below: `/100` behind a numeral that already carries a
   polarity triangle needs a 96px pitch, not 80, so six cells run 356..932. The
   right edge is what is fixed now, flush with the sign's 932, so a four-cell
   screen closes up under the sign instead of trailing off into a hole. */
.s2-rail   {position:absolute;left:356px;top:10px;  width:576px;height:46px; z-index:6}
.s2-goal   {position:absolute;left:22px; top:96px;  width:360px;height:62px; z-index:5}
/* §T9 · THE SCREEN NAME — see the block under T2 for the rule it implements */
/* z6, ONE ABOVE THE GOAL, AND THAT IS A BUG FIX AND NOT A PREFERENCE. The
   goal's scrim is a z-index:-1 child of `.s2-goal`, and `.s2-goal` is itself
   positioned with a z-index, so it opens a stacking context and the scrim is
   trapped INSIDE it at z5 — painting over anything else at z5 that comes
   earlier in the DOM. The screen name is exactly that, so the first shot of
   this token came back with a 34px headline sitting under a dark radial and
   reading grey against the 26px ivory below it: the largest type on the frame
   was also the dimmest. One level up and it is over the scrim it is lit by. */
.s2-name   {position:absolute;left:22px; top:60px;  width:412px;height:40px; z-index:6}
.s2-signbox{position:absolute;left:646px;top:84px;  width:286px;height:100px;z-index:4}
.s2-bill   {position:absolute;left:22px; top:188px; width:250px;height:96px; z-index:5}
.s2-slab   {position:absolute;left:22px; top:176px; width:250px;height:168px;z-index:5}
.s2-alert  {position:absolute;left:22px; top:262px; width:396px;height:40px; z-index:7}
.s2-act1   {position:absolute;left:20px; top:352px; width:912px;height:62px; z-index:6}

/* ---- §OT Oregon Trail Party Tray on Travel -------------------------------- */
.s2-travel .s2-ot-tray{
  position:absolute; left:20px; top:336px;
  display:flex; gap:6px; z-index:6;
}
.ot-card{
  width:64px; height:80px; position:relative;
  background:linear-gradient(180deg,rgba(24,32,44,0.92) 0%,rgba(10,15,22,0.96) 100%);
  border:1px solid rgba(255,255,255,0.18); border-radius:6px;
  overflow:hidden; box-shadow:0 4px 10px rgba(0,0,0,0.5);
  display:flex; flex-direction:column;
}
.ot-card.hurt{ border-color:var(--s2-alarm, #E23A22); }
.ot-card .ot-face{
  flex:1 1 auto; position:relative; overflow:hidden;
  background:rgba(255,255,255,0.03);
}
.ot-card .ot-face img,.ot-card .ot-face svg{
  width:100%; height:100%; object-fit:cover; object-position:top center;
  filter:drop-shadow(0 2px 4px rgba(0,0,0,0.7));
}
.ot-card.ot-trk .ot-face img{
  object-fit:contain; object-position:center;
}
.ot-card .ot-warn{
  position:absolute; top:2px; right:2px;
  background:var(--s2-alarm, #E23A22); color:#FFF;
  font-size:12px; font-weight:700; line-height:1;
  padding:1px 3px; border-radius:3px;
}
.ot-card .ot-foot{
  flex:0 0 auto; padding:2px 4px 4px 4px;
  background:rgba(6,10,15,0.9);
  border-top:1px solid rgba(255,255,255,0.08);
  display:flex; flex-direction:column; gap:2px;
}
.ot-card .ot-nm{
  font-size:12px; font-weight:700; letter-spacing:.08em;
  color:var(--s2-ivory, #F3F6F9); text-align:center; line-height:1;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.ot-card .ot-bar{
  height:4px; background:rgba(255,255,255,0.14);
  border-radius:2px; overflow:hidden;
}
.ot-card .ot-bar i{
  display:block; height:100%;
  background:var(--s2-go, #25D074); border-radius:2px;
}
.ot-card.hurt .ot-bar i{ background:var(--s2-alarm, #E23A22); }

/* ---- §OT Trail Control Bar ------------------------------------------------ */
.s2-travel .s2-trail-bar{
  position:absolute; right:20px; top:300px; width:452px; height:34px;
  display:flex; gap:6px; z-index:6;
}
.s2-trail-bar .s2-tbtn{
  flex:1 1 0; height:34px; padding:2px 4px;
  background:linear-gradient(180deg, rgba(28,38,50,0.95) 0%, rgba(14,20,28,0.98) 100%);
  border:1px solid rgba(255,255,255,0.2); border-radius:4px;
  box-shadow:0 2px 6px rgba(0,0,0,0.4);
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  cursor:pointer; transition:border-color .15s, background .15s;
}
.s2-trail-bar .s2-tbtn:hover{
  border-color:var(--s2-ivory, #F3F6F9);
  background:rgba(40,54,72,0.98);
}
.s2-trail-bar .s2-tbtn .tb-k{
  font-family:var(--s2-hwy, Arial, sans-serif);
  font-size:12px; font-weight:700; letter-spacing:.08em; line-height:1;
  color:rgba(255,255,255,0.55);
}
.s2-trail-bar .s2-tbtn .tb-v{
  font-family:var(--s2-hwy, Arial, sans-serif);
  font-size:12px; font-weight:700; letter-spacing:.04em; line-height:1;
  color:var(--s2-ivory, #F3F6F9); margin-top:2px;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.s2-mappeek{position:absolute;left:646px;top:190px;width:286px;height:30px;z-index:6;
  display:flex;align-items:center;justify-content:center;gap:9px;border:1px solid var(--s2-keyline);
  border-radius:4px;background:linear-gradient(180deg,rgba(28,38,50,.95),rgba(14,20,28,.98));
  color:var(--s2-mute-hi);font:700 12px/1 var(--s2-hwy);letter-spacing:.1em;cursor:pointer}
.s2-mappeek svg{width:25px;height:16px;fill:none;stroke:currentColor;stroke-width:1.4;stroke-linejoin:round}
.s2-mappeek:hover{border-color:var(--s2-ivory);color:var(--s2-ivory)}
.s2-mappeek:focus-visible{outline:2px solid var(--s2-go-key);outline-offset:2px}

.s2-travel .s2-act1{
  left:auto; right:20px; width:452px; top:340px; height:74px;
}
.s2-travel .s2-act1 .s2-verb{
  width:144px; height:74px; padding:6px 10px;
}
.s2-travel .s2-act1 .s2-verb:nth-of-type(1){ left:0; }
.s2-travel .s2-act1 .s2-verb:nth-of-type(2){ left:154px; }
.s2-travel .s2-act1 .s2-verb:nth-of-type(3){ left:308px; }
.s2-travel .s2-act1 .s2-verb .vl{ font-size:13px; line-height:1.1; }
.s2-travel .s2-act1 .s2-verb .vr{ left:10px; bottom:6px; }
.s2-travel .s2-act1 .s2-verb .vr .km{ font-size:12px; }
.s2-travel .s2-act1 .s2-verb .vr .tag{ font-size:12px; }
.s2-act2   {position:absolute;left:20px; top:288px; width:912px;height:112px;z-index:6}
/* ACTION-2 screens lift the left column by the amounts named in §2 */
.s2-act2mode .s2-bill {top:176px}
.s2-act2mode .s2-alert{top:232px}
.s2-act2mode .s2-slab {top:176px;height:140px}

/* THE SLUDGE, AND WHY IT IS ONLY ON ACTION-2.
   Side by side with the travel frame the town read as "murkier, and the scene
   is sludge behind the panels" — and the panels are the reason. An ACTION-1
   screen puts one 62px row at y352 and the road wash under it earns its .88;
   an ACTION-2 screen puts a 112px grid at y288, so the same wash is laid over
   a hundred and twelve pixels of plate that is already covered by six steel
   verbs and is doing nothing but darkening the fifty pixels of ground between
   the truck's wheels and the grid. It is shortened and lightened here, and the
   sky wash with it, because an ACTION-2 frame has less picture left and cannot
   afford to dim what it has. The truck is graded a step warmer and brighter on
   the same screens so the mascot comes off the plate rather than sinking into
   it — a grade on the subject, not a light on it: no bloom, no halo, nothing
   that spends the one lamp. */
.s2-act2mode .s2-sky{
  background:linear-gradient(180deg,rgba(4,7,12,.54) 0,rgba(4,7,12,.16) 62%,rgba(4,7,12,0) 100%)}
.s2-act2mode .s2-road{height:118px;
  background:linear-gradient(0deg,rgba(4,6,10,.74) 0,rgba(4,6,10,.40) 48%,rgba(4,6,10,0) 100%)}
.s2-act2mode .truck{
  filter:drop-shadow(0 14px 16px rgba(0,0,0,.55)) saturate(1.12) brightness(1.15) contrast(1.05)}

/* §T8 · THE TRUCK — two sizes, no others.
   TRUCK-WIDE x 284-636 clears the sign at 646 by 10px and the billboard at
   272 by 12px. TRUCK-PARKED clears both by more. Load-bearing numbers. */
.truck{position:absolute;z-index:3;display:block;
  filter:drop-shadow(0 14px 16px rgba(0,0,0,.52)) saturate(1.04) brightness(1.05)}
.truck.wide  {left:284px;top:168px;width:352px;height:176px}
.truck.parked{left:300px;top:136px;width:300px;height:150px}

/* ===========================================================================
   §3 · T1 — THE SIGN
   An Alberta highway destination sign. Green board, 2px ivory keyline, two
   steel posts, DAY n stamped on the near post. Scenery, never a control.
   =========================================================================== */
.s2-post{position:absolute;z-index:2;width:9px;height:92px;top:184px;border-radius:1px;
  background:linear-gradient(90deg,#4e545c,#98a1ab 40%,#5f666f);
  box-shadow:0 2px 6px rgba(0,0,0,.55)}
.s2-post.near{left:668px}
.s2-post.far {left:890px}

.sign{position:absolute;left:646px;top:84px;width:286px;height:100px;z-index:4;
  border-radius:7px;padding:6px;
  background:linear-gradient(180deg,var(--s2-sign-a) 0,var(--s2-sign-b) 100%);
  box-shadow:0 8px 20px rgba(0,0,0,.62),inset 0 1px 0 rgba(255,255,255,.20)}
.sign .in{height:100%;border:2px solid var(--s2-ivory);border-radius:4px;
  padding:8px 11px;display:flex;flex-direction:column;justify-content:center;gap:7px}
.sign .ln{display:flex;align-items:center;gap:9px}
.sign .pl{flex:1;font-size:17px;letter-spacing:.03em;overflow:hidden;
  text-overflow:ellipsis;text-shadow:0 1px 0 rgba(0,0,0,.4)}
.sign .km{font-size:var(--s2-t-sign);letter-spacing:.02em;text-shadow:0 1px 0 rgba(0,0,0,.4)}
.sign .rule{height:2px;border-radius:2px;flex:none;
  background:linear-gradient(90deg,rgba(242,238,228,.62),rgba(242,238,228,.62))}
/* the 13x10 blue Alberta route-shield glyph that bullets row 2. Drawn, not
   typed: it costs no text run and no character. */
.s2-shield{flex:none;width:13px;height:10px;border-radius:1px;position:relative;
  background:linear-gradient(180deg,#24499b,#1b3f8f);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.6)}
.s2-shield::after{content:"";position:absolute;left:4px;top:2px;width:5px;height:6px;
  background:linear-gradient(180deg,#e04a3a 0 50%,#3f8f4e 50% 100%)}
/* §J4 · DAY n, stamped on the near post. The clock is on the same object as
   the distance, and there is no date header anywhere. */
.s2-stamp{position:absolute;left:676px;top:190px;width:66px;height:22px;z-index:5;
  display:flex;align-items:center;justify-content:center;border-radius:3px;
  border:1px solid #59616d;
  background:linear-gradient(180deg,#232935,#141922);
  box-shadow:0 2px 6px rgba(0,0,0,.55)}
.s2-stamp .t{font-size:var(--s2-t-key);letter-spacing:.14em;color:#b9c1cc}

/* A small service blade hangs from the destination sign. It describes the
   next place—not another meter—so distance and resupply planning are one
   glance, as they are throughout the reference journey. */
.s2-next-services{position:absolute;left:750px;top:187px;width:182px;height:24px;z-index:5;
  display:flex;align-items:center;justify-content:center;padding:0 7px;
  border:1px solid rgba(242,238,228,.82);border-radius:0 0 4px 4px;
  background:#123f2a;box-shadow:0 4px 8px rgba(0,0,0,.48)}
.s2-next-services .t{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  font-size:9px;line-height:1;letter-spacing:.07em;color:var(--s2-ivory)}

/* ===========================================================================
   §3 · T2 — THE GOAL LINE
   The win condition, its current value and its direction. The largest type on
   every screen, and the only element in the set whose largest type answers
   "what am I trying to do".
   =========================================================================== */
/* THE VALUE AND THE BAR IT HAS TO CLEAR ARE ONE STATEMENT, SO THEY ARE ONE
   LINE. The blind read: "the target lives one line below, third of the way
   into a three-clause string, at roughly 10px letterspaced grey caps against
   28px white. In four seconds I read 40% YES and nothing else." The target is
   now at T-SIGN — the second-largest step in the ramp, 1.7x the 15px it used
   to share row 2 with — separated from the value by a drawn keyline rather
   than by a middot, so the two read as one comparison and not as a list.
   CHANNEL 1 is untouched: the 34px value is still the only T-GOAL run on the
   frame and it is still the .goal node. */
.s2-goal .r1{display:flex;align-items:baseline;gap:12px;height:36px}
.s2-goal .v{font-size:var(--s2-t-goal);letter-spacing:.02em;
  text-shadow:0 2px 10px rgba(0,0,0,.75),0 1px 0 rgba(0,0,0,.6)}
.s2-goal .tg{font-size:var(--s2-t-sign);letter-spacing:.05em;color:var(--s2-mute-hi);
  text-shadow:0 2px 8px rgba(5,7,11,.92),0 1px 0 rgba(0,0,0,.6)}
/* the keyline between them. Drawn, so it costs no character and no text run. */
.s2-goal .cut{flex:none;width:2px;height:24px;align-self:center;border-radius:1px;
  background:linear-gradient(180deg,rgba(242,238,228,0),rgba(242,238,228,.55) 50%,
                                    rgba(242,238,228,0))}
.s2-goal .r2{position:absolute;left:0;top:44px;font-size:var(--s2-t-key);
  letter-spacing:.10em;color:var(--s2-mute-hi);
  text-shadow:0 1px 2px rgba(5,7,11,.98),0 0 7px rgba(5,7,11,.95)}
/* the direction arrow, drawn as a pseudo-element with its own colour on the
   same terms as the alert's icon: full size, no text run, no character. */
.s2-goal .r2::before{font-size:var(--s2-t-key);letter-spacing:0}
.s2-goal .r2.fall::before{content:"\25BC\0000a0";color:var(--s2-alarm)}
.s2-goal .r2.rise::before{content:"\25B2\0000a0";color:var(--s2-ivory)}
.s2-goal .r2.flat::before{content:"\25AC\0000a0";color:var(--s2-mute-hi)}

/* THE SCRIM, AND WHY IT IS NOT A PANEL.
   The blind note: "AND HOLDING and THE REFERENDUM 527 KM TO GO are grey on a
   lit sky." Both are true and both are the same defect — 12px and 15px mute
   over the brightest third of reddeer.webp, where a text-shadow alone is not
   enough because the plate behind it is not dark.

   Three things fix it and none of them is a plate. (1) The two runs move from
   `mute` to `mute-hi`, which is the same job one step brighter and is still
   plainly subordinate to the 34px ivory beside them. (2) A single-stop-to-zero
   gradient sits BEHIND the goal line only. (3) It is 404x92 — 42% of the
   frame's width, half of BANDS' 85% threshold, so it cannot become a band, and
   it fades to nothing on two edges so it has no edge to read as a box.

   It is a gradient rather than a background-colour, so it costs INK-a in
   proportion to the mean alpha of its stops (about .30 across 404x92, which is
   9.1% of the frame) rather than charging as an opaque panel. That is the
   honest way to buy the contrast and it is what both winning mocks do. */
.s2-goal .s2-scrim{position:absolute;left:-16px;top:-14px;width:404px;height:92px;
  z-index:-1;pointer-events:none;border-radius:10px;
  background:
    radial-gradient(82% 82% at 24% 46%,rgba(4,7,12,.80) 0,rgba(4,7,12,.48) 48%,
                                        rgba(4,7,12,.16) 76%,rgba(4,7,12,0) 100%)}

/* ===========================================================================
   §T9 · THE SCREEN NAME, AND THE SWAP IT PERFORMS.

   THE RULE, CORRECTED. §5 CHANNEL 1 read "the goal line is the largest type on
   every screen". That was the fix for the original diagnosis and on travel,
   town and event it worked — all three won. It OVER-CORRECTED: with the same
   sentence in the largest type on all ten frames, no frame could say WHAT IT
   WAS. Blind, on the store: "there is no title anywhere on the screen. I would
   not have guessed this was a shop." Confidence in what the screen was: ours
   30, the shipped build 75. The reference does the opposite — MATT'S GENERAL
   STORE and KANSAS RIVER CROSSING are the largest type on those frames.

     THE LARGEST TYPE ON A SCREEN ANSWERS "WHAT AM I DOING HERE". On the journey
     screens — travel, event, town — that IS the goal line, because the journey
     is the subject. On every other screen the SCREEN'S OWN NAME takes the size
     crown and the goal line demotes ONE STEP, keeping its slot, its colour and
     its meaning.

   Mechanically it is one class on the frame root and two ramp steps. `.s2-name`
   takes T-GOAL; the goal's value drops T-GOAL → T-SIGN and its target T-SIGN →
   T-LABEL; the whole goal block slides from y96 to y106 so the two sit as one
   left-column header, name over score, in the reading order they are read in.
   Nothing else on any screen moves. The scrim grows upward to carry both.
   =========================================================================== */
.s2-name .t{display:block;max-width:412px;font-size:var(--s2-t-goal);
  letter-spacing:.03em;color:var(--s2-ivory);
  overflow:hidden;text-overflow:ellipsis;
  text-shadow:0 2px 10px rgba(0,0,0,.82),0 1px 0 rgba(0,0,0,.65)}

.s2-named .s2-goal{top:106px;height:50px}
.s2-named .s2-goal .r1{height:28px;gap:10px}
.s2-named .s2-goal .v {font-size:var(--s2-t-sign)}
.s2-named .s2-goal .tg{font-size:var(--s2-t-label)}
.s2-named .s2-goal .cut{height:19px}
.s2-named .s2-goal .r2{top:36px}
/* one scrim under both runs rather than two overlapping ones, which is what
   made a second radial look like a smudge when it was tried */
.s2-named .s2-goal .s2-scrim{top:-54px;height:132px}

/* ===========================================================================
   §3 · T3 — THE STATUS CELL
   Icon + numeral + key, in the rail. 74x46, pitch 80, from x452.
   Never a word where a number belongs — and, after three rounds, never a fill
   bar under one either. See the block below the cell box for what replaced it.
   =========================================================================== */
.s2-rail{border:0;padding:0;background:none;cursor:pointer;text-align:left;
  -webkit-tap-highlight-color:transparent}
.s2-cell{position:absolute;top:0;width:92px;height:46px}

/* ===========================================================================
   THE SIGNAL IS IN THE NUMBER. THIRD ROUND ON THIS SLOT, AND THE APPROACH
   CHANGED RATHER THAN THE PIXELS.

   Two bars have now failed here in front of three blind critics apiece — a 3px
   `mute` hairline, then a 6px ivory segment in a dark keylined well. Both were
   reasoned to be legible; neither was, and the notes came back identical every
   round: "OIL 63 — direction NOT stated, I infer higher-is-better from a jerry
   can"; "Scale: NO. The bar under it is a hairline I could not read"; "the
   delta glyph is unreadable at 427 so it tells me nothing at actual size."

   A third attempt at a bar is a third attempt at the same idea. So the bar is
   GONE, the delta is GONE, and both jobs move INTO the numeral, which is the
   one thing in this cell that is already 20px and already the thing you read:

     1. THE NUMERAL IS COLOURED BY HOW THAT CELL IS DOING, ON ITS OWN
        POLARITY. Ivory above 55% of the room it has, `mute` between 30% and
        55%, `alarm` below 30% — and for GRIEVANCE, the one stock whose bad end
        is the top, the room is its complement, so grievance at 74 is alarm for
        the same arithmetic that makes oil at 21 alarm. A player learns which
        way is up by watching numbers dim and redden, which needs no legend, no
        word and no maximum, and it works at 20px where 5px of bar does not.
        §T3 already licenses this ("the numeral turns alarm below 25"); it was
        simply not doing enough of the work.

     2. THE NUMERAL STATES ITS DIRECTION ONCE, STATICALLY, IN THE GOOD SENSE.
        A drawn triangle leads it and points at the end of the range you want
        to be at: ▲ on the five stocks you want high, ▼ on grievance. It takes
        `currentColor`, so it is always the same colour as the number it
        belongs to — a red 74 behind a red ▼ says "you want this down and it is
        not" in two objects and no prose — and being drawn it costs no
        character on a frame with a character cap.

   AND THEN — FOURTH ROUND — THE DENOMINATOR, WHICH WAS NEVER MISSING FROM THE
   SIMULATION, ONLY FROM THE FRAME.

   Colour and polarity were the right half of the answer and the judges said so
   ("can I tell it is in trouble? Yes, but only from the colour"). They were
   never the whole answer, because the question every round was the same six
   words: "21 OF WHAT?" — and the verdict this round was "it does not read;
   five of six numbers fail." Three devices had now been built to answer that
   without printing it.

   CLAUDE.md answers it in one line: THE FIVE METERS ARE ALL 0-100 AND ANY ONE
   HITTING 0 ENDS THE RUN. So `/100` goes on all four of the free meters and
   `/50` stays on SUPPORT, where the line is `tallyVote()`'s own `sup>=50`. FUND
   still prints nothing, because cash genuinely has no ceiling in the code and
   the only honest thing to print against it would be invented.

   IT COST 72px OF RAIL AND THAT IS THE RIGHT PRICE. A fraction behind a T-LABEL
   numeral that already leads with a polarity triangle measures about 86px, so
   the 80px pitch that fitted a bare number does not fit an answered one. The
   pitch is 96, the cell is 92, and the rail anchors to its right edge. Squeezing
   it instead — dropping the key word to `⛽ 21/100`, which was the obvious
   saving — was rejected: an emoji at 15px is the thing three rounds of critics
   have called a blob, and OIL is the word that stops the blob from having to
   carry the noun on its own.
   =========================================================================== */
.s2-cell .n{position:absolute;left:0;top:2px;font-size:var(--s2-t-label);
  letter-spacing:.02em;text-shadow:0 1px 5px rgba(0,0,0,.9)}
.s2-pixi{display:inline-flex;align-items:center;justify-content:center;line-height:0;vertical-align:-1px}
.s2-cell .n .s2-pixi{width:20px;vertical-align:0}
.s2-cell .n .pixi{display:block}
.s2-verb .tag .s2-pixi,.s2-detail .tag .s2-pixi{margin-left:2px}
.s2-cell .n.ok  {color:var(--s2-ivory)}
.s2-cell .n.warn{color:var(--s2-mute)}
.s2-cell .n.low {color:var(--s2-alarm)}
.s2-cell .n.fund{color:var(--s2-amber)}
.s2-cell .k{position:absolute;left:0;top:27px;font-size:var(--s2-t-key);
  letter-spacing:.04em;color:var(--s2-mute);text-shadow:0 1px 5px rgba(0,0,0,.9)}
/* THE DIRECTION ARROW LEADS THE NUMERAL, NOT THE KEY, AND THAT IS A
   MEASUREMENT AND NOT A PREFERENCE. Measured at 952x427 in the shipping font
   stack, `GRIEVANCE` sets to 78px inside a 74px cell on an 80px pitch — it
   already spends its whole gutter — so a 15px arrow in front of it lands on
   `SUPPORT`. The numerals are 52-68px wide in the same cell, so the room is on
   the numeral's line and nowhere else. Leading it there also stands the six
   arrows in one column down the left edge of the rail, which is what makes
   them read as a property of each stock rather than as a delta.

   IT IS DRAWN, NOT TYPED, AND THAT IS ALSO A MEASUREMENT. A `▲` glyph at
   T-BODY sets to 15px of advance width, most of it side bearing, and SUPPORT's
   numeral already carries `/50` and runs to 68px — 68 + 15 + 3 lands 6px into
   the FUND cell. A CSS triangle is 8px of pure ink and no side bearing, it
   takes `currentColor` so it can never drift out of step with the numeral it
   belongs to, and it costs no character on a frame with a character cap. */
/* ~~THE POLARITY TRIANGLE~~ — DELETED, ON THE JUDGE THAT LOOKED AT IT AT SIZE.
   "The rail's arrow glyphs are unresolvable at this size and read as noise. If
   an 8px arrow cannot be identified, it is not carrying polarity — the
   numeral's colour already does that job."
   That is the fourth device this rail has built to answer one question and the
   third one killed for the same reason: a 3px hairline, a 6px keylined well,
   and now an 8px triangle, each of them a picture of a fact at a size nobody
   could read the picture at. The two things that DID land are still here and
   they are the two that are made of type — the numeral's state colour, which
   the judges said outright works, and `/100`, which stopped the four-round
   question about the scale. Eight pixels of ink beside them was buying a
   distinction the colour had already made, and paying for it in noise on the
   one strip that is on nine of the ten screens.
   `.up` / `.dn` are still emitted by s2RailHTML(): they are the polarity, they
   cost nothing, and a later round that finds a way to draw them at a size that
   resolves should not have to re-derive which way each stock points. */
.s2-cell .n::before{display:none}
/* THE DENOMINATOR. Drawn from the cell's `den`, at T-KEY and in `mute`, hard
   against a T-LABEL numeral: `21` reads as the value and `/100` as the scale it
   is 21 of, which is the difference between a number and a score. A
   pseudo-element for the same reason the alert's icon is one — it is a unit,
   not a run of prose, and it should not cost the frame a character on a screen
   with a character cap. Five of the six cells carry one; FUND does not, because
   the Heritage Fund has no ceiling anywhere in the code. */
.s2-cell .n[data-den]::after{content:attr(data-den);font-size:var(--s2-t-key);
  letter-spacing:.01em;color:var(--s2-mute);margin-left:1px}

/* the latch. A control, so steel — and a gradient, so it hides nothing it is
   not standing on. */
.s2-latch{border:0;padding:0;cursor:pointer;border-radius:8px;
  background:linear-gradient(180deg,rgba(23,28,37,.92),rgba(9,12,17,.92));
  box-shadow:0 0 0 1px rgba(120,130,145,.42),0 3px 8px rgba(0,0,0,.5)}
.s2-latch i{position:absolute;left:12px;width:20px;height:2px;border-radius:2px;
  background:linear-gradient(90deg,#aab2bd,#aab2bd)}
.s2-latch i:nth-child(1){top:15px}
.s2-latch i:nth-child(2){top:21px}
.s2-latch i:nth-child(3){top:27px}

/* ===========================================================================
   §3 · T4 — THE ALERT
   One plain-English sentence about a threshold that was crossed. At most one
   on screen, ever. It is the entire reporting channel for morale, grievance,
   the seventeen afflictions, weather damage and empty inventory.
   It deliberately overlaps the truck's lower body and is z-ordered above it —
   a roadside object standing on the road in front of the vehicle. Its top
   edge is always below the truck's midline, so it never covers the cab or the
   FREE ALBERTA lettering.
   =========================================================================== */
.s2-alert{display:flex;align-items:center;gap:11px;padding:0 14px;border-radius:8px;
  background:linear-gradient(180deg,var(--s2-steel-a),var(--s2-steel-b));
  box-shadow:0 0 0 1.5px var(--s2-alarm),0 6px 18px rgba(0,0,0,.6),
             inset 0 1px 0 rgba(255,255,255,.10)}
/* the 18px icon is a pseudo-element: it draws at full size, costs no text run
   and no character on a frame whose character cap is 260 */
.s2-alert-icon{display:flex;align-items:center;justify-content:center;width:18px;flex:none;
  color:var(--s2-alarm);filter:drop-shadow(0 0 5px rgba(255,120,90,.75))}
.s2-alert-icon .pixi{display:block}
.s2-alert .t{font-size:var(--s2-t-body);letter-spacing:.09em;color:var(--s2-ivory);
  overflow:hidden;text-overflow:ellipsis;max-width:322px}

/* §5 · THE ONE LAMP RULE. Exactly one element on a frame carries a bloom.
   On travel it is the alert if one fired, otherwise the GO verb. */
.s2 .lit{animation:s2pulse 1.9s ease-in-out infinite}
@keyframes s2pulse{
  0%,100%{filter:drop-shadow(0 0 0 rgba(255,90,60,0))}
  50%    {filter:drop-shadow(0 0 14px rgba(255,120,80,.55))}
}
.s2 .s2-verb.go.lit{animation:s2golamp 2.1s ease-in-out infinite}
@keyframes s2golamp{
  0%,100%{box-shadow:0 0 0 1px var(--s2-go-key),0 6px 16px rgba(0,0,0,.55)}
  50%    {box-shadow:0 0 0 1px var(--s2-go-key),0 6px 16px rgba(0,0,0,.55),0 0 24px rgba(35,196,106,.55)}
}
/* A STEEL VERB TAKING THE LAMP. The town has no green any more (see
   shell2.js), so its one lamp lands on the opportunity verb — the option only
   this town has. A bloom and a keyline, never a fill: the verb stays steel, the
   accent stays unspent, and the amber matches the MARK sitting on the same
   button, so the billboard, the mark, the price and the light are four
   statements of one fact rather than four objects competing for the eye.
   Specificity (0,4,0), so it beats the generic `.s2 .lit` above it. */
.s2 .s2-verb.lit:not(.go){animation:s2verblamp 2.2s ease-in-out infinite}
/* THE LAMP IS ON AT REST AND BREATHES ON TOP OF THAT. A pulse whose trough is
   the unlit state is invisible in half the frames of its own cycle — and a
   still is one frame. The keyline is amber the whole time and only the bloom
   moves, which is how the GO lamp already behaves. */
@keyframes s2verblamp{
  0%,100%{box-shadow:0 0 0 1px rgba(255,176,46,.78),0 5px 14px rgba(0,0,0,.55),
                    inset 0 1px 0 rgba(255,255,255,.09),0 0 12px rgba(255,176,46,.22)}
  50%    {box-shadow:0 0 0 1px rgba(255,176,46,.92),0 5px 14px rgba(0,0,0,.55),
                    inset 0 1px 0 rgba(255,255,255,.09),0 0 26px rgba(255,176,46,.46)}
}
@media (prefers-reduced-motion:reduce){
  .s2 .lit,.s2 .s2-verb.go.lit,.s2 .s2-verb.lit:not(.go){animation:none}
  .s2 .s2-verb.go.lit{box-shadow:0 0 0 1px var(--s2-go-key),0 0 24px rgba(35,196,106,.55)}
  .s2 .s2-verb.lit:not(.go){box-shadow:0 0 0 1px rgba(255,176,46,.80),
    0 5px 14px rgba(0,0,0,.55),0 0 22px rgba(255,176,46,.40)}
}

/* ===========================================================================
   §3 · T5 — THE VERB, and §3 · T6 — THE PRICE TAG
   The button. Three paints and only three: steel, GO, off. An `off` verb
   always states its reason, never just dims. Two arrangements and no third.
   =========================================================================== */
/* A <button> vertically CENTRES its own content box no matter what `display`
   says, so a label meant to sit at the top of the tile drifted down into the
   absolutely-positioned price row underneath it — visible as THE YARD sitting
   on top of +6% YES at 52px. Declaring the verb an explicit flex column with
   flex-start pins the label to the top and gives the tag row its whole gap
   back, on both ACTION-1 and ACTION-2. */
.s2-verb{position:absolute;top:0;height:62px;border:0;cursor:pointer;text-align:left;
  display:flex;flex-direction:column;align-items:flex-start;justify-content:flex-start;
  padding:9px 14px 8px;font-family:var(--s2-hwy);
  background:linear-gradient(180deg,var(--s2-steel-a) 0,var(--s2-steel-b) 100%);
  box-shadow:0 0 0 1px var(--s2-keyline),0 5px 14px rgba(0,0,0,.55),
             inset 0 1px 0 rgba(255,255,255,.09);
  /* the project's stepped pixel chamfer, top-left and bottom-right */
  clip-path:polygon(0 6px,3px 6px,3px 3px,6px 3px,6px 0,
                    100% 0,100% calc(100% - 6px),calc(100% - 3px) calc(100% - 6px),
                    calc(100% - 3px) calc(100% - 3px),calc(100% - 6px) calc(100% - 3px),
                    calc(100% - 6px) 100%,0 100%)}
.s2-act1 .s2-verb{width:296px}
.s2-act1 .s2-verb:nth-of-type(1){left:0}
.s2-act1 .s2-verb:nth-of-type(2){left:308px}
.s2-act1 .s2-verb:nth-of-type(3){left:616px}
/* the crossing's row of four and the fork's row of two, declared here so the
   two screens that need them cannot invent a third arrangement */
.s2-act1.four .s2-verb{width:220px}
.s2-act1.four .s2-verb:nth-of-type(1){left:0}
.s2-act1.four .s2-verb:nth-of-type(2){left:231px}
.s2-act1.four .s2-verb:nth-of-type(3){left:462px}
.s2-act1.four .s2-verb:nth-of-type(4){left:693px}
/* A ROW WHOSE LABELS ARE ALLOWED TWO LINES. §8.7's own mock wraps
   `TURN BACK TO THE / TRAIL` inside a 220px verb, and `Turn back to the trail`
   is a §9.3 click hook that two harnesses match by its literal string, so it
   cannot be shortened to fit. 62px holds two lines of T-LABEL at line-height 1
   over a 12px tag row with 5px of padding top and bottom, and that is exactly
   what this class sets. Verbs whose label is one line simply sit higher in the
   same box. */
.s2-act1.wrap2 .s2-verb{padding:5px 12px 5px}
.s2-act1.wrap2 .s2-verb .vl{line-height:1.0;letter-spacing:.03em}
.s2-act1.wrap2 .s2-verb .vr{left:12px;bottom:5px}
.s2-act1.wrap2 .s2-verb.go::after{right:12px;bottom:4px}
.s2-act1.two .s2-verb{width:446px}
.s2-act1.two .s2-verb:nth-of-type(1){left:0}
.s2-act1.two .s2-verb:nth-of-type(2){left:466px}
/* ACTION-2 — the 2x3 grid, and the only other arrangement §T5 allows.
   Rows at y 288 and y 348 measured from the container's own top edge, which is
   288, so the second row is 60px down. TRUCK-PARKED bottoms at y 286 and the
   grid starts at 288: the clearance is 2px and it is deliberate. */
.s2-act2 .s2-verb{width:296px;height:52px}
.s2-act2 .s2-verb:nth-of-type(1){left:0;   top:0}
.s2-act2 .s2-verb:nth-of-type(2){left:308px;top:0}
.s2-act2 .s2-verb:nth-of-type(3){left:616px;top:0}
.s2-act2 .s2-verb:nth-of-type(4){left:0;   top:60px}
.s2-act2 .s2-verb:nth-of-type(5){left:308px;top:60px}
.s2-act2 .s2-verb:nth-of-type(6){left:616px;top:60px}
.s2-act2 .s2-verb{padding:8px 14px 7px}
.s2-act2 .s2-verb .vr{bottom:7px}
/* one line, always: a 52px verb has a label row and a price row and no third
   row to wrap into. The town falls back to the authored SHORT name above 22
   characters, so this is a guard rather than a policy. */
.s2-act2 .s2-verb .vl{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.s2-act2 .s2-verb.go::after{bottom:7px}

/* THE REASON PHRASE. It replaces the price tags on an `off` verb and it is
   never optional — a disabled verb that only dims is the one thing both
   judges named as the cleanest communication in the whole set when it is done
   right, and the shipped town does it right. It is kept. */
.s2-verb .tag.rs{color:var(--s2-off-tx);letter-spacing:.08em;
  overflow:hidden;text-overflow:ellipsis;max-width:266px}

/* §8.5 — AN EVENT CHOICE.
   The deck's own `l` strings run to 53 characters, which is two lines at 20px
   in a 296px verb, so the label centres itself in the box and wraps rather
   than being clipped or shrunk under the 12px floor. No price tags: the deck
   hides its consequences on purpose — `e` is the outcome and `r` is the
   writing that reveals it — so printing the deltas here would be a different
   game, not a better frame. */
.s2-verb.ev{flex-direction:row;align-items:center;justify-content:flex-start;
  padding:8px 14px}
.s2-verb.ev .vl{white-space:normal;line-height:1.08;letter-spacing:.04em}

.s2-verb .vl{display:block;width:100%;font-size:var(--s2-t-label);letter-spacing:.06em;
  text-transform:uppercase;color:var(--s2-ivory);line-height:1}
.s2-verb .vr{position:absolute;left:14px;bottom:9px;display:flex;align-items:center;gap:7px}
.s2-verb .km{font-size:var(--s2-t-key);letter-spacing:.10em;color:var(--s2-mute)}
.s2-verb .tag{font-size:var(--s2-t-key);letter-spacing:.06em;color:var(--s2-mute)}
.s2-verb .tag.bad{color:var(--s2-alarm)}
.s2-verb .tag.cash{color:var(--s2-amber)}
.s2-verb .tag.gain{color:var(--s2-ivory)}
/* THE RISK COLUMN, on the crossing and only there. Every option prints one,
   they are all the same sentence, and they line up under one another so the
   comparison is a read down a column rather than four conversions. `alarm`
   where there is a risk and `mute` where there is none — the palette's own
   two jobs, and nothing new. */
.s2-verb .tag.rk{color:var(--s2-alarm)}
.s2-verb .tag.rk0{color:var(--s2-mute)}
.s2-verb.go .tag.rk{color:#6d1403}
.s2-verb.go .tag.rk0{color:#0d3c22}
/* ONE PRICE CHIP, TWO CURRENCIES. A town press costs money AND a day, and
   those are one statement rather than two, so they are one tag with the
   divider drawn between them — which is what leaves the second tag free to
   carry the payoff. The amount is amber (money) and the day is mute (a
   duration), exactly as §T6 colours them when they stand apart. */
.s2-verb .tag .sep{display:inline-block;margin:0 4px;color:var(--s2-keyline)}
.s2-verb .tag .dy{display:inline-block;color:var(--s2-mute);letter-spacing:.06em}

/* GO — the one control that advances the journey. Nothing else, ever, on any
   screen. Grep-enforceable: --s2-go appears on one rendered element. */
.s2-verb.go{background:linear-gradient(180deg,#28cf74 0,#1eb662 100%);
  box-shadow:0 0 0 1px var(--s2-go-key),0 6px 16px rgba(0,0,0,.55)}
.s2-verb.go .vl{color:var(--s2-go-ink)}
.s2-verb.go .km{color:rgba(4,21,11,.72)}
/* A PRICE TAG ON THE GREEN FILL. `alarm` on `#23c46a` is two saturated colours
   at nearly the same luminance and it disappeared: the crossing's GO verb is
   the one place in the system where a cost is printed on the accent, because
   §8.7 greens the risky road. The tags take the fill's own ink instead — the
   loss dark red rather than alarm, the neutral dark green — so they read as
   what is written ON the button rather than as a second colour fighting it. */
.s2-verb.go .tag{color:rgba(4,21,11,.74)}
.s2-verb.go .tag.bad{color:#6d1403}
.s2-verb.go .tag.cash{color:#5a3200}
.s2-verb.go::after{content:"\25B6";position:absolute;right:14px;bottom:8px;
  font-size:15px;line-height:1;color:var(--s2-go-ink)}
/* THE WAY OUT, WITHOUT THE ACCENT. The town's exit is steel like everything
   else in its grid, so the one thing that still has to say "this leads out of
   here" is the arrow — drawn, in `mute`, costing no character. */
.s2-verb.exit::after{content:"\25B6";position:absolute;right:14px;bottom:8px;
  font-size:15px;line-height:1;color:var(--s2-mute)}
.s2-act2 .s2-verb.exit::after{bottom:7px}
/* off — dimmed AND explained. Never a bare dim button. */
.s2-verb.off{cursor:default;
  background:linear-gradient(180deg,rgba(11,14,20,.60),rgba(11,14,20,.60));
  box-shadow:0 0 0 1px var(--s2-off-key)}
.s2-verb.off .vl,.s2-verb.off .km,.s2-verb.off .tag{color:var(--s2-off-tx)}

/* THE MARK — an 18px amber disc with a black `!`, at most one per screen, on
   the option that only exists in this town. */
/* INSIDE the verb, not hung off its corner: §T5's chamfer is a clip-path, and
   a clip-path clips its children, so a mark at right:-6px was sliced in half. */
.s2-verb.marked .vl{padding-right:26px}
/* THE HALO IS GONE, AND THE OPEN FINDING WITH IT.
   `.s2-mark` carried `box-shadow:0 0 10px rgba(255,176,46,.6)` — a coloured
   bloom on a frame that already had a lit element — and it did not carry
   `.lit`, so the lint `frame.querySelectorAll('.lit').length === 1` PASSED
   while two things glowed. §5 says a coloured halo, a saturated fill and a
   bright outline are the same budget and the budget is one; a rule enforced by
   a lint its own exception does not participate in is not enforced.
   The fix is not to add the dot to the count and leave two lamps burning. The
   mark now reads on saturation, size and position alone — amber on steel at
   the top right of one verb — separated from the plate by a DARK ring, which
   is a shadow and not a bloom. The light the mark was reaching for went to the
   verb underneath it instead, as `.lit`: inside the budget, and inside the
   lint that measures it. */
.s2-mark{position:absolute;right:10px;top:8px;width:18px;height:18px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  background:linear-gradient(180deg,#ffc555,var(--s2-amber));
  box-shadow:0 0 0 1.5px rgba(5,7,11,.8),0 1px 3px rgba(0,0,0,.55)}
.s2-mark .t{font-size:var(--s2-t-key);color:#1a1204;letter-spacing:0}

/* ===========================================================================
   §3 · T7 — THE BILLBOARD, and its CAPTION SLAB fallback
   A real sign in the world carrying one local fact. Above 12 words it stops
   being a sign and becomes a plain slab in the same slot, doubled in height.
   =========================================================================== */
/* WEATHERED PLYWOOD, NOT A LIT CREAM PANEL. The blind read on the town: "the
   cream billboard out-shouts the truck and sits on top of it — it is the second
   brightest object on the frame". §T7 calls the billboard a real sign in the
   world, and §5's loudness ladder puts it on the bottom rung beside the rail,
   the verbs and the faces: a thing you look UP, not a thing that calls you. It
   was painted at about 92% luminance, brighter than any panel on the truck. It
   is now a sun-bleached board at about 60% — still the warmest object in the
   left column, still comfortably legible against its own ink, and no longer
   competing with the mascot. */
.s2-bill{padding:11px 13px;border-radius:3px;transform:rotate(-.7deg);
  display:flex;flex-direction:column;justify-content:center;
  background:linear-gradient(180deg,#a99c81 0,#8b7f66 100%);
  box-shadow:0 6px 14px rgba(0,0,0,.5),inset 0 0 0 2px rgba(58,47,26,.42)}
.s2-bill .t{display:block;font-family:var(--s2-voice);font-weight:400;
  color:#1d1709;letter-spacing:0;white-space:normal;line-height:1.3;
  font-size:var(--s2-t-body)}
.s2-slab{padding:13px 14px;border-radius:4px;
  background:linear-gradient(180deg,rgba(17,22,31,.90),rgba(8,11,17,.90));
  box-shadow:0 8px 20px rgba(0,0,0,.55)}
.s2-slab .h{display:block;font-size:var(--s2-t-label);letter-spacing:.06em;
  text-transform:uppercase;color:var(--s2-ivory);line-height:1.06}
/* THE BODY SIZES ITSELF, between T-BODY and the 12px floor and never under it.
   §T7 caps the slab's copy at 26 words; the shipped 191-event deck runs to 43
   and 240 characters, and the deck is read rather than rewritten. So the slab
   spends its own line-height instead of the reader's punchline: 15px to 130
   characters, then 14, 13 and 12. Measured worst case — a 40-character
   headline on two lines over 240 characters at 12px — is 144px inside a 144px
   content box, so nothing in the deck overflows and nothing is clipped. */
.s2-slab .b{display:block;margin-top:7px;font-family:var(--s2-voice);font-weight:400;
  font-size:var(--s2-t-body);line-height:1.30;color:#ded9cd;letter-spacing:0}
.s2-slab{padding:11px 13px 9px;overflow:hidden}

/* ===========================================================================
   §T8 — THE PARTY RIDES IN IT
   3-5 busts composited on the box rail. An afflicted person gets a 14px alarm
   pip at the lower right of their face and nothing else — no name, no bar, no
   number, on any screen. The pip is the only mark a face ever carries.
   =========================================================================== */
.s2-crew{position:absolute;z-index:2;pointer-events:none;overflow:hidden}
.s2-crew.wide{left:324px;top:205px;width:126px;height:48px}
.s2-crew.parked{left:336px;top:175px;width:108px;height:42px}
.s2-crew b{position:absolute;bottom:0;display:block;height:100%;overflow:hidden;border-radius:3px;
  background:#17222d;box-shadow:0 0 0 1px rgba(242,238,228,.46),0 3px 7px rgba(0,0,0,.72)}
.s2-crew b.art{border-radius:0;background:transparent;box-shadow:none}
.s2-crew img{display:block;width:100%;height:auto;
  filter:drop-shadow(0 2px 3px rgba(0,0,0,.55)) brightness(.96)}
.s2-crew svg{display:block;width:100%;height:100%;object-fit:cover}
.s2-crew u{position:absolute;right:-2px;bottom:9px;width:14px;height:14px;border-radius:50%;
  background:linear-gradient(180deg,#ff7358,var(--s2-alarm));
  box-shadow:0 0 8px rgba(255,90,60,.85)}

/* On the live road, the truck is side-on and its cab window is only about
   42x43px at authored scale. Seat the leader inside that glass instead of
   balancing the whole party on the roof; the full group remains readable in
   the party tray and appears together on stop/event tableaux. */
.s2-travel .s2-crew.wide{left:347px;top:184px;width:126px;height:74px;z-index:2}
.s2-travel .s2-crew.wide b{display:block!important;width:44px!important;height:66px;bottom:-8px}
/* One driver in the cab and up to four campaigners riding behind it. Their
   lower halves are clipped by this shallow strip, so they read as people in
   the truck rather than portrait cards pasted over its door. */
.s2-travel .s2-crew.wide b:nth-child(1){left:0!important;bottom:-7px}
.s2-travel .s2-crew.wide b:nth-child(2){left:31px!important;bottom:-9px}
.s2-travel .s2-crew.wide b:nth-child(3){left:62px!important;bottom:-7px}
.s2-travel .s2-crew.wide b:nth-child(4){left:93px!important;bottom:-9px}
.s2-travel .s2-crew.wide img{filter:brightness(.68) saturate(.78)}
.s2-travel .s2-crew.wide u{right:-1px;bottom:10px;width:9px;height:9px}
.s2-travel .s2-crew.travelDriver{left:483px;top:201px;width:44px;height:45px;z-index:4}
.s2-travel .s2-crew.travelDriver b{left:0!important;bottom:0;width:100%!important;height:100%;border:0;box-shadow:none;background:transparent}
.s2-travel .s2-crew.travelDriver img{filter:brightness(.72) saturate(.76)}

/* The road is idling under the convoy even while the player studies the next
   leg. Truck and passengers share one restrained suspension cycle; separating
   them would make the people float out of the cab. */
.s2-travel .truck,.s2-travel .s2-crew{animation:s2Ride 1.05s cubic-bezier(.37,0,.63,1) infinite alternate}
@keyframes s2Ride{from{transform:translate3d(0,0,0) rotate(-.15deg)}to{transform:translate3d(0,-3px,0) rotate(.18deg)}}
@media(prefers-reduced-motion:reduce){.s2-travel .truck,.s2-travel .s2-crew{animation:none}}

/* ===========================================================================
   §8.3 · OUTFITTING — THE COUNTER
   The reference's store is a PLACE WITH A PERSON IN IT: goods as objects on a
   counter with a price under each, ONE detail panel for the selected item, two
   big buttons. `ot_95f82b94.jpg` shows description text for exactly one thing
   on the whole screen, and that single observation is the shape of this
   screen — eleven goods keep every word they have and put one sentence on the
   frame instead of eleven.

   What it replaces measured INK 83%, 22 buttons of which 7 were under 44px,
   and 44 text runs under 12px, on the second screen a new player ever sees.
   =========================================================================== */
/* THE SHELF. One row of goods along the bottom of the picture, each an icon
   over a price and nothing else — no name, no effect, no sentence. The name
   and the sentence are in the panel, on the accessible name, and one tap away,
   which is exactly what the reference does with its six. */
/* THE TILES ARE THE SUBJECT OF THIS SCREEN AND THEY ARE SIZED LIKE IT NOW.
   Blind, on the frame that was ranked LAST: "the eleven item tiles are the
   reason the screen exists and they are the smallest, dimmest, most crowded
   element on it", and "the icons render as ~28px blobs I could not identify."
   They were 52px tall with a 20px icon. They are 86px tall with a 42px icon —
   goods as objects on a counter with a price under each, which is the one
   observation `ot_95f82b94.jpg` settles the whole screen with.

   THE COUNTER STANDS IN FRONT OF THE TRUCK, AND THAT IS THE POINT. It runs from
   y258 to y344 and the parked truck (raised to y124) bottoms at y274, so the
   counter covers the bottom 16px of the sprite — its wheels. §2 already
   licenses exactly this for the ALERT ("a roadside object standing on the road
   in front of the vehicle") and the rule it sets is that the overlap stays
   below the truck's midline, which 258 does by 59px. A shop counter in front of
   the window the truck is parked outside is the same move and the same depth
   cue: the cab, the box and the FREE ALBERTA lettering are all untouched. */
.s2-counter{position:absolute;left:20px;top:288px;width:912px;height:52px;z-index:6}
/* THE COUNTER GREW A THIRD LINE AND PAID FOR IT OUT OF THE ICON.
   Blind, twice, and the second time exactly: "Eleven emoji with prices and
   nothing else: I cannot tell a wrench from a wheel in purpose terms" against
   the shipped build's "every tile carries its effect — +12 OIL, HALVES ICE +
   FOG, COVERS 3 STORMS — for the first time I can shop without tapping." The
   effect IS the thing being bought, so it goes on the tile.
   The arithmetic, at eleven tiles and a 76px pitch: icon + 3 + price + 3 + two
   lines of 12px = 34+3+15+3+26 = 81, plus 10 of padding, in 92. The height
   comes out of the frame between the detail panel (which ends at y252) and
   ACTION-1 (which starts at y352), and every one of those 92 pixels is
   already spoken for — so the icon comes down from 42px to 34px and that is
   the trade, stated rather than hidden. §8.3's own words for the alternative
   were "fewer tiles per row with a scroll", which puts a shopping decision
   behind a gesture on the screen whose whole job is comparison, and dropping
   the effect was never on the table. 34px is still an object on a counter;
   what actually identifies it now is the line underneath it. */
/* WAVE 6 — THE COUNTER IS A 7-COLUMN GRID AND THE TRUCK PAID FOR IT.
   DESIGN-SYSTEM §2 amended: the persistent frame yields SPACE as well as size
   on a screen whose subject is not the journey. TRUCK-PARKED came off this
   screen, TRUCK-SHELF (240x120 at x396 y60) went on, and the whole band from
   y172 to y344 came back to the goods — 172px of frame that four rounds of this
   screen spent looking at a parked truck.
   The arithmetic, at 7 columns and a 130px pitch: 125px tiles, so `COVERS 3
   STORMS` (~112px in plain Arial at 12px, the face §4's stack actually resolves
   to here) sets on ONE line — which buys back the 13px the wrap was costing and
   puts it into the ICON, 34px -> 48px. That is the diagnosis in one number: at
   28-34px a judge could not name the object, and naming the object at a glance
   is the reference's whole proposition.
   `top` and `height` are set inline by the renderer, because a trading post
   with four goods is one row and the shelf always bottoms at y344. */
.s2-store .s2-counter{left:20px;top:184px;width:912px;height:160px}
.s2-good{position:absolute;top:0;height:52px;border:0;cursor:pointer;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;
  padding:4px 2px;font-family:var(--s2-hwy);
  background:linear-gradient(180deg,rgba(23,28,37,.94),rgba(9,12,17,.94));
  box-shadow:0 0 0 1px var(--s2-keyline),0 4px 12px rgba(0,0,0,.55),
             inset 0 1px 0 rgba(255,255,255,.08)}
/* THE GOODS ARE OBJECTS, NOT PANELS, AND THAT IS BOTH THE REFERENCE AND THE
   MEASUREMENT AGREEING FOR ONCE.
   First cut of this rebuild kept the steel tile behind each good and just made
   it taller. It measured INK-a 64% against §9.5's cap of 46 — eleven opaque
   boxes 86px tall across the full width is a wall, which is the disease this
   whole system exists to treat, arriving in the costume of the cure.
   Open `ot_95f82b94.jpg` again: there is no panel behind any of its six goods.
   They are OBJECTS SITTING ON A COUNTER, each with a price under it, and the
   only box on the shelf is the thin keyline around the one that is selected.
   So the tile loses its fill, its keyline and its shadow; the icon grows to
   42px and carries its own drop shadow; the price keeps a text shadow; and the
   selection box — which is now the only ink on the row — is what says which
   good the panel is describing. The road wash already sits over this band, so
   the type has its contrast without a plate under it. */
/* TOP-ALIGNED, NOT CENTRED. Eleven tiles whose contents are one, two or three
   rows deep, centred in a fixed 92px box, put eleven prices at eleven
   different heights — visible in the first shot of this counter as a shelf
   that looks tilted. Aligned to the top, every icon and every price sits on
   one line and only the effect, which is the thing that varies, is allowed to
   grow downward. */
.s2-store .s2-good{height:80px;gap:1px;padding:1px 1px 1px;
  justify-content:flex-start;background:none;box-shadow:none}
/* 42px -> 38px, and the 4px is the name's. The object is still the biggest
   thing on the tile and still the thing the eye lands on; what it is called is
   now printed under it instead of being a fact only the detail card holds. */
.s2-store .s2-good .gi{font-size:38px;
  filter:drop-shadow(0 3px 7px rgba(0,0,0,.78)) drop-shadow(0 0 2px rgba(0,0,0,.6))}
/* THE NAME. T-KEY ivory caps, one line, ellipsised — a tile is 125px and the
   longest counter name in the deck (`WEATHER RADIO`) sets to 84px at 12px in
   the stack §4 resolves to, so nothing in this deck reaches the ellipsis and a
   future deck that does is trimmed rather than allowed to wrap the price off
   the shelf. It is `.t`, so it is nowrap by the same rule as every other run
   in this file except the effect. */
.s2-store .s2-good .gn{font-size:var(--s2-t-key);line-height:1.15;
  letter-spacing:.045em;text-transform:uppercase;color:var(--s2-ivory);
  max-width:100%;overflow:hidden;text-overflow:ellipsis;
  text-shadow:0 1px 3px rgba(0,0,0,1),0 0 6px rgba(0,0,0,.95)}
.s2-store .s2-good.cant .gn{color:var(--s2-off-tx)}
.s2-store .s2-good .gp{font-size:var(--s2-t-body);line-height:1.1;
  text-shadow:0 1px 4px rgba(0,0,0,.95),0 0 8px rgba(0,0,0,.8)}
.s2-store .s2-good .gq{text-shadow:0 1px 4px rgba(0,0,0,.95)}
/* WHAT IT DOES, UNDER WHAT IT COSTS. The deck's own short form — LD_FX[id][2]
   — read, never composed, and uppercased here rather than in the string so
   nothing downstream that matches on it has to know.
   IT IS THE ONE RUN IN THIS FILE ALLOWED TO WRAP. Everything else is `.t`,
   which is nowrap by design because a run that breaks is a run whose box is
   not its glyphs. `COVERS 3 STORMS` is fifteen characters in a 76px tile, so
   this one breaks to a second line, centred, at the 12px floor and not a
   thousandth under it — and the box is capped at two lines so a longer string
   from a future deck cannot push the price off the shelf. */
.s2-store .s2-good .gf{display:-webkit-box;-webkit-line-clamp:1;
  -webkit-box-orient:vertical;overflow:hidden;
  /* THE FULL TILE WIDTH, AFTER TRYING NOT TO. Narrowing this box to 84% was
     an attempt to break the counter back to BANDS 0 by widening the gaps
     between the eleven runs. It did not work — _measure.js's grid is 8px with
     a ceil on the right edge, so eleven boxes across 912px stay contiguous at
     any width a 12px line is still legible at — and it cost `HALVES ICE +…`,
     `COVERS 3…` and `FORECAS TO 95%`, three clipped effects on the screen
     whose whole fix this round is that the effects are readable. So the box
     is full width, every string sets whole, and outfitting measures BANDS 1
     where it measured 0. That is inside §9.5's cap of 2 for this screen, it
     is the honest cost of putting the effect on the goods, and it is recorded
     here rather than tuned around. */
  width:100%;font-size:var(--s2-t-key);line-height:1.10;letter-spacing:.005em;
  text-transform:uppercase;text-align:center;white-space:normal;
  color:var(--s2-ivory);
  text-shadow:0 1px 2px rgba(0,0,0,1),0 0 4px rgba(0,0,0,1),0 0 10px rgba(0,0,0,.92)}
.s2-store .s2-good.cant .gf{color:var(--s2-off-tx);text-shadow:0 1px 3px rgba(0,0,0,.9)}
/* the selected good keeps its box, because the box IS the selection */
.s2-store .s2-good.on{box-shadow:0 0 0 2px var(--s2-ivory),0 4px 12px rgba(0,0,0,.6)}
.s2-good .gi{font-size:20px;line-height:1}
.s2-good .gi::before{content:attr(data-ic)}
.s2-good .gi .pixi{display:block}
.s2-good .gp{font-size:var(--s2-t-key);letter-spacing:.04em;color:var(--s2-amber);
  line-height:1}
/* the selected tile takes a 2px IVORY keyline — never green. GO green is the
   one control that advances the journey and a chosen sack of flour is not it. */
.s2-good.on{box-shadow:0 0 0 2px var(--s2-ivory),0 4px 12px rgba(0,0,0,.6),
            inset 0 1px 0 rgba(255,255,255,.10)}
/* §5 · THE ONE LAMP, ON THE STORE, GOES BACK TO THE PRIMARY — wave 6.
   Last round the store had no green, so the lamp went to the selected good.
   The green is back and it is on `Buy` (DESIGN-SYSTEM §8.3's boxed call), so
   §5's ladder reads straight down again — no alert, no caption slab, no fork
   sign, therefore the GO verb — and the bloom the tile was carrying is gone.
   The selected good keeps the 2px IVORY keyline below, which is the whole of
   what a selection has to say: THIS is the one the card is describing. Two
   glowing objects is the failure this budget exists to prevent, and with the
   goods now 48px and 125px wide the tile no longer needs light to be found. */
/* what you already carry, as a count on the tile — the reference's own badge */
/* WAVE 10 — THE COUNT WAS A GHOST. A 12px ivory numeral at .9 opacity, with no
   ground under it, over a photographic plate: it was on the tile and it could
   not be seen, which is the same failure as the gauge two rows above it in a
   smaller costume. Same numeral, same place, same meaning — set at T-BODY on
   its own dark disc with an ivory keyline, which is the badge the reference
   draws and the only reason its counts read at this size. */
.s2-good .gq{position:absolute;right:1px;top:1px;font-size:var(--s2-t-body);
  min-width:19px;height:19px;padding:0 3px;border-radius:10px;
  display:flex;align-items:center;justify-content:center;
  line-height:1;color:var(--s2-ivory);letter-spacing:0;opacity:1;
  background:linear-gradient(180deg,rgba(11,15,22,.94),rgba(5,7,11,.96));
  box-shadow:0 0 0 1px rgba(242,238,228,.55),0 2px 6px rgba(0,0,0,.75)}
.s2-good.cant .gp{color:var(--s2-off-tx)}
.s2-good.cant .gi{opacity:.5}

/* THE DETAIL PANEL, IN THE BILLBOARD SLOT. §8.3 draws it at x646 y196, which
   is where §2 stands the DAY stamp and where the sign's own posts land. A
   screen that needs a persistent slot to move does not get that slot — so the
   panel takes a slot the store already has spare instead: the store has no
   alert and no billboard, and the left column is 250x96 and empty. Same
   geometry as every other screen, one fewer bespoke number. */
/* y160..252 rather than y188..284: the name and the demoted goal line take the
   top of this column now, and the counter takes the bottom of it. 92px holds
   two lines of T-LABEL name over a tag row over a clamped sentence, which is
   the worst case the deck actually produces. */
/* THE DETAIL CARD MOVES INTO THE DOCK, BESIDE THE BUTTON THAT ACTS ON IT.
   The two shelves take the whole width now (see the block above the counter),
   so the left column at y160 is gone — and the third of ACTION-1 this screen's
   two verbs leave empty is exactly 280x76 of unspoken-for frame, directly left
   of `Buy`. The card keeps everything the tile cannot say: the full name, what
   it costs in slots, how many are already in the box, and the deck's one
   sentence. It is not a button and it does not look like one — no chamfer, no
   keyline, a flatter plate than a verb — so the dock still reads as two
   presses and a label. */
/* THE DETAIL CARD GOES BACK TO THE LEFT COLUMN, WITH THE SHELF.
   y160..252 rather than y188..284: the screen name and the demoted goal line
   take the top of this column, and the one shelf takes the bottom of it. 92px
   holds two lines of T-LABEL name over a tag row over a clamped sentence,
   which is the worst case the deck actually produces. */
/* WAVE 6 — THE DETAIL CARD IS A CELL OF THE SHELF.
   It was in the FAR LEFT column while the selection happened at the bottom
   right, which is the longest eye-trip the frame can produce. It now takes the
   three trailing cells of the shelf's last row — 385x86 at x544 y258 — so it is
   IN the counter, one row from any tile you press, with `Buy` directly under
   it. Its left/top/width/height are set inline by the renderer from the same
   grid numbers the tiles use, so the card cannot drift out of the row. */
.s2-store .s2-detail{z-index:7;padding:6px 12px 5px}
/* the full name sets on ONE line at 233px of card — `JERRY CAN OF DIESEL` is
   the longest in the deck and measures ~209px at T-LABEL — and the deck's
   sentence keeps its two lines under it. */
.s2-store .s2-detail .h{-webkit-line-clamp:2;line-height:.96}
/* WAVE 10 — `1 SLOT` AND `2 IN BOX` WERE NAMED AS UNREADABLE, so they go from
   T-KEY to T-BODY and the neutral one takes `mute-hi` instead of `mute`. They
   are the two facts on this card the tile one row away cannot say, and they
   were set two steps under the name that introduces them. The 4px they cost
   is bought back out of the three leadings around them, not out of the deck's
   sentence — nothing on the card is cut. */
.s2-store .s2-detail .ch{margin-top:2px;flex-wrap:wrap;gap:9px;row-gap:0}
.s2-store .s2-detail .ch .tag{font-size:var(--s2-t-body);letter-spacing:.03em;
  color:var(--s2-mute-hi);line-height:1.05}
.s2-store .s2-detail .b{-webkit-line-clamp:2;margin-top:2px;line-height:1.10}
/* §2 · TRUCK-SHELF — 240x120 at x396 y60, and it exists on this screen only.
   x396-636 clears the SIGN at 646 by 10px (the same 10 TRUCK-WIDE clears it by)
   and the goal block (x22 w360, ending 382) by 14px; it tops 4px under the rail
   and bottoms at y180, so the first shelf row at y172 crosses its WHEELS by 8px
   and nothing else — the identical licence §2 already gives the ALERT. */
.s2-store .truck.parked{left:396px;top:60px;width:240px;height:120px}
.s2-store .s2-crew.parked{left:425px;top:81px;transform:scale(.8);
  transform-origin:0 100%}
/* a long store title must ellipsise before it reaches the fender, not over it */
.s2-store .s2-name{width:370px}
.s2-detail{position:absolute;left:22px;top:188px;width:250px;height:96px;z-index:5;
  padding:9px 12px 8px;border-radius:4px;
  background:linear-gradient(180deg,rgba(17,22,31,.92),rgba(8,11,17,.92));
  box-shadow:0 8px 20px rgba(0,0,0,.55),inset 0 1px 0 rgba(255,255,255,.08);
  overflow:hidden}
/* THE NAME WRAPS TO TWO LINES AND THE SENTENCE TAKES WHAT IS LEFT. Set in
   caps at T-LABEL, `JERRY CAN OF DIESEL` runs past the 226px this slot has, so
   a single clamped line ate the noun off the end of every long good. Two lines
   of name plus one of sentence, or one of name plus two of sentence, both come
   to under the 96px the slot has — so the card asks for the shorter sentence
   when the name is long, which is s2StorePanelHTML()'s own word cap, and
   nothing is ever cut mid-clause. */
.s2-detail .h{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  font-size:var(--s2-t-label);letter-spacing:.04em;
  text-transform:uppercase;color:var(--s2-ivory);line-height:1.0;overflow:hidden}
.s2-detail .ch{display:flex;align-items:center;gap:8px;margin-top:5px}
.s2-detail .ch .tag{font-size:var(--s2-t-key);letter-spacing:.05em;color:var(--s2-mute)}
.s2-detail .ch .tag.gain{color:var(--s2-ivory)}
.s2-detail .ch .tag.own{color:var(--s2-amber)}
.s2-detail .b{display:block;margin-top:5px;font-family:var(--s2-voice);font-weight:400;
  font-size:12px;line-height:1.26;color:#ded9cd;letter-spacing:0}
/* the store's sign hangs on a wall, so it has no posts and its DAY stamp goes
   on the board's own bottom rail instead of on a post that is not there */
/* §2 · THE PERSISTENT FRAME YIELDS LOUDNESS TOO — the third correction, and it
   is the same argument as the other two. Wave 5 took the frame's claim on TYPE
   (a named screen's own name takes the size crown); wave 6 took its claim on
   SPACE (a screen whose subject is not the journey gets the middle of the
   frame back). This is the claim on ATTENTION, and it was filed blind on this
   exact screen: "the second-loudest thing is the green EDMONTON / THE REPUBLIC
   603 sign, which is a mistake — 603 is the biggest unexplained number on the
   screen and it steals attention from the shop I am supposed to be using."
   §2 keeps every letter of what it already says: the sign keeps its slot, its
   286x100, its two lines and both its numbers, on all ten screens. What it
   surrenders here is the only thing it was ever going to surrender — the lit,
   saturated finish of a board caught in headlights, on the ONE screen that is
   indoors and whose subject is a counter. It is a sign hanging on a shop wall
   in shop light, which is what §8.3 already calls it in words. Scoped to
   `.s2-store`, so the six screens that won this round see none of it. */
.s2 .sign.hung{box-shadow:0 10px 24px rgba(0,0,0,.66),inset 0 1px 0 rgba(255,255,255,.20)}
.s2-store .sign.hung{filter:saturate(.70) brightness(.78)}
.s2-store .sign.hung .in{opacity:.94}
.s2-stamp.hung{left:866px;top:190px}
/* ACTION-1 with two verbs in the right-hand two slots: the counter is the
   screen's real menu and the dock is a buy and a way out, so they sit under
   the panel and the sign rather than centred on nothing. */
/* THE WAY OUT ON THE LEFT, THE PRIMARY ON THE RIGHT UNDER ITS OWN CARD.
   DOM order is the visual order — `Hit the road` first, `Buy` second — and
   `Buy` at x633 lines its right edge up with the detail card's at x929, so the
   card and the button it feeds read as one column. */
.s2-act1.pair .s2-verb{width:296px}
.s2-act1.pair .s2-verb:nth-of-type(1){left:20px}
.s2-act1.pair .s2-verb:nth-of-type(2){left:636px}

/* ===========================================================================
   §8.7 · CROSSING — THE TRUCK GETS OFF THE RIVER
   The one per-screen departure from §2's TRUCK-WIDE x284, and it is declared
   rather than drifted into. reddeer.webp paints the river, the closed bridge
   and the BRIDGE OUT sign across the middle of the frame; TRUCK-WIDE at x284
   parks 352px of pickup on top of all three, which is why a screen whose whole
   subject is water was read, blind, as "the same road plate the travel screen
   uses". §2 fixes x284 on two clearances — the SIGN at 646 by 10px and the
   BILLBOARD at 272 by 12px. This screen has no billboard any more (it was
   printing the same four words as the sign painted into the plate), so the
   second constraint is gone and the first is cleared by 234px instead of 10.
   The truck sits nose-at-the-water on the left, the water is open to its right,
   and the ALERT still lands below the truck's midline.
   =========================================================================== */
.s2-xr .truck.wide{left:60px}
.s2-xr .s2-crew.wide{left:100px}

/* WAVE 10 — THE RISK COLUMN IS THE SCREEN AND IT WAS SET AT THE FLOOR.
   §8.7's whole proposition is that four roads across a river can be compared
   before you press, and the comparison is `SINKS 1 IN 7` against `SINKS 1 IN
   20` against `NEVER SINKS`. That sentence was printed at T-KEY — the same
   step as a `DAY n` stamp — in `alarm` on a dark plate, under a 20px label,
   at the bottom edge of the frame. Nothing here changes what is written or
   what colour it is: the cost keeps `alarm`/`amber`, the risk keeps `alarm`
   where there is one and `mute` where there is none. It goes up ONE STEP of
   §4's ramp, to T-BODY — the step §T4 already gives the alert, which is the
   other place this game states a threat in words — and the neutral `mute`
   goes to `mute-hi` so `NEVER SINKS` is a statement rather than a smudge.
   The row is 220px wide with 28px of padding; the longest pair the deck
   produces (`−$200` + `SINKS 1 IN 20`) sets to ~150px at T-BODY. */
/* AND IT IS THE RISK THAT MOVES, NOT THE PRICE. `−18 ⛽` is a price tag and
   §4 puts price tags at T-KEY on all ten screens; `SINKS 1 IN 7` is not a
   price, it is a plain-English statement of a consequence, which is the exact
   object §T4 sets at T-BODY in the alert. So the ramp is not bent — the risk
   is simply filed where the ramp already files a sentence, the price stays
   where the ramp already files a number, and the row still fits its 220px. */
.s2-xr .s2-verb .tag.rk,
.s2-xr .s2-verb .tag.rk0{font-size:var(--s2-t-body);letter-spacing:0}
.s2-xr .s2-verb .tag.rk0{color:var(--s2-mute-hi)}
/* THE ROW BUYS THE WIDTH THE STEP COSTS, OUT OF ITS OWN MARGINS AND NOTHING
   ELSE. The widest pair in the deck is `−12 ☕ · 1 DAY` + `SINKS 1 IN 13` and
   at T-BODY it needs ~192px of a 220px verb, so the price row comes in to 9px
   a side and its gap to 6px — no string is shortened and no tag is dropped.
   The GO verb's drawn ▶ owns the right 29px, so on that one the row stops
   short of it: `FORD IT` carries the shortest pair in the deck (`−12/26 🛻` +
   `NEVER SINKS`, ~160px) and clears it. */
.s2-xr .s2-verb .vr{left:9px;right:9px;gap:6px;bottom:8px}
.s2-xr .s2-verb.go .vr{right:38px}

/* ===========================================================================
   §8.7 · CROSSING — WHY THERE IS NO DRAWN DEPTH MARKER
   §8.7 calls the depth marker "the best diegetic object in the system" and
   says explicitly that IT IS NOT A TOKEN — it is painted into the crossing
   setpiece plate. `reddeer.webp` already carries the world objects that do
   that job: a BRIDGE OUT sign on a post and a striped road barrier standing in
   the frame at the water's edge. A second striped post drawn over the top of
   them in CSS read, at 952x427, as a grey rectangle sitting on the plate's own
   barrier — an artefact, not a gauge. So this shell draws none, and the risk
   is carried where §8.7 says it belongs: in the picture, and on the four
   priced roads underneath it.
   =========================================================================== */

/* ===========================================================================
   §8.8 · FORK — THE SIGN GROWS AN ARM
   The one screen where the sign changes shape: into what a real fork in a real
   highway has, a two-arm fingerpost, same slot, 40px taller. It does not drop
   the Republic's distance — arbitration ruling 9, against design C's own spec:
   a persistent frame with an exception is not persistent.
   =========================================================================== */
.s2 .sign.fork{height:140px}
.s2-post.fork{top:224px}
.s2-stamp.fork{top:230px}
.s2 .sign.fork .in{gap:5px}
.s2 .sign.fork .ln3{font-size:var(--s2-t-key);letter-spacing:.10em;
  color:rgba(242,238,228,.86);display:flex;align-items:center;gap:7px}
/* §5 — ON THE FORK THE SIGN TAKES THE LAMP, because the sign is literally the
   decision. Its bloom is IVORY, the colour of its own keyline, not the alert's
   orange and not the accent's green: the sign is scenery that has been lit,
   not a control that has been painted. */
.s2 .sign.lit{animation:s2signlamp 2.2s ease-in-out infinite}
@keyframes s2signlamp{
  0%,100%{box-shadow:0 8px 20px rgba(0,0,0,.62),inset 0 1px 0 rgba(255,255,255,.20),
                     0 0 18px rgba(242,238,228,.34)}
  50%    {box-shadow:0 8px 20px rgba(0,0,0,.62),inset 0 1px 0 rgba(255,255,255,.20),
                     0 0 30px rgba(242,238,228,.50)}
}
@media (prefers-reduced-motion:reduce){
  .s2 .sign.lit{animation:none;
    box-shadow:0 8px 20px rgba(0,0,0,.62),inset 0 1px 0 rgba(255,255,255,.20),
               0 0 26px rgba(242,238,228,.44)}
}

/* ===========================================================================
   THE LEG LINE — TRAVEL'S PLACE CUE, ONE RUNG UNDER THE CROWN.

   All three blind judges filed the same note against the winning travel frame:
   "Frame 9 has no name. The largest text is 44% YES NEEDS 50% — a persistent
   global meter — and the only place cue is FORT MACLEOD 47 on a road sign."
   §T9's corrected rule is what caused it: it hands a name to every screen whose
   job is not the journey and leaves the journey screens with the goal line
   alone, which left TRAVEL as the one frame in the game that does not say
   where it is.

   THE TOWN'S GRAMMAR IS THE FIX, because the town won with it. Read down the
   town's left column: the score at T-GOAL, then the place — `NISKU` on the
   board and one line about what Nisku is on the billboard. Read down travel's:
   the score, then nothing until the buttons.

   IT IS NOT §T9's SCREEN NAME AND IT IS DELIBERATELY NOT SHAPED LIKE ONE.
   T-SIGN, not T-GOAL, so CHANNEL 1 is untouched and `tools/hierarchy.js` still
   reads `.s2-goal .v` as travel's crown; the goal block does not slide; there
   is no `.s2-named` on the root. §T9 says the screen name is "never a place on
   the route" and this is a place, so it must not borrow that token's size, its
   slot or its class. It carries its own shadow rather than leaning on the
   goal's scrim, because it sits 20px above the top of it.
   =========================================================================== */
.s2-leg{position:absolute;left:22px;top:60px;width:560px;height:32px;z-index:6}
.s2-leg .t{display:block;max-width:560px;font-size:var(--s2-t-sign);
  letter-spacing:.10em;color:var(--s2-ivory);
  overflow:hidden;text-overflow:ellipsis;
  text-shadow:0 2px 9px rgba(5,7,11,.95),0 1px 0 rgba(0,0,0,.7)}

/* ===========================================================================
   ACTION-1 WITH ONE VERB IN IT. The title and the referendum each ask exactly
   one thing, and a lone 296px button hard against the left edge of a 912px row
   reads as the first of three that failed to render. Declared here so neither
   screen invents its own number.
   =========================================================================== */
.s2-act1.one .s2-verb{width:296px;left:328px}

/* ===========================================================================
   §8.1 · TITLE
   No rail, no latch, no left slot — there is no run. The truck is the only
   thing on the frame that is not chrome, and on this one screen it is whole.
   =========================================================================== */
/* THE TRUCK MOVES RIGHT ON THIS ONE SCREEN, AND IT IS DECLARED.
   §2 fixes TRUCK-WIDE at x284 on two clearances — the SIGN at 646 and the
   BILLBOARD at 272. §8.1 says the title has no left slot at all ("no rail, no
   latch, no left slot — there is no run"), so the billboard constraint does
   not exist here; and the tagline this screen lost its comparison for needs
   the left column at a width a serif paragraph is readable at. At x560 the
   roofline grazes the sign board's bottom edge by 8px, which is exactly the
   depth cue §2 already licenses for the inner post: the sign stands further
   down the road than the truck. The crossing made the same move first. */
.s2-title .truck.wide{left:560px;top:176px}
/* the title's sign quotes the WHOLE trail — §J1's `603 at the start`. It was
   an em-dash placeholder and it read, blind, as a bug. It is a numeral now and
   it is set in the numeral's own tracking like every other screen's. */

/* ---------------------------------------------------------------------------
   THE TITLE IS READ, NOT PLAYED. See the block above s2RenderTitle().
   The left column reads top to bottom as one paragraph of identity:
   register (badge) → name (logotype) → score (goal, at its zero state) →
   what the game IS (tagline) → what you are buying (meta).
   ------------------------------------------------------------------------ */
/* ONE WASH FOR THE READING COLUMN, AND IT IS WHY THE PROSE IS LEGIBLE.
   Blind, on the frame that lost 1-2: "the whole four-line description
   paragraph — too small and too low-contrast over the scene to read in four
   seconds", and "FIVE METERS · 28 ENDINGS · ONE TRUCK THAT WILL NOT MAKE IT is
   grey-on-dark and I only got it by squinting." `title.webp` is a dusk plate
   with a lit chinook arch across the middle of it, and four separate text
   shadows over a bright sky is the thing that does not work — it is the exact
   defect §T2's own scrim block diagnosed on the goal line, arriving on the
   three runs below it.
   So the whole column stands on one wash instead: 600px wide, fading to
   nothing at its right edge, replacing the goal's local radial. Its stops mean
   .44 alpha, under _measure.js's .55 threshold, so it TINTS and is not counted
   as a fill; it is 63% of the frame against BANDS' 85%, so the one screen in
   the game required to measure BANDS 0 still does. */
.s2-title .s2-wash{position:absolute;left:0;top:0;width:600px;height:427px;
  z-index:2;pointer-events:none;
  background:linear-gradient(90deg,rgba(4,7,12,.78) 0,rgba(4,7,12,.64) 44%,
                                   rgba(4,7,12,.28) 76%,rgba(4,7,12,0) 100%)}
.s2-title .s2-goal .s2-scrim{display:none}

.s2-badge{position:absolute;left:22px;top:20px;height:22px;z-index:6;
  display:flex;align-items:center}
/* The title is the only named screen that shows this badge. Its two persistent
   controls already own x12..106, so the badge begins after them instead of
   being painted across both hit targets. */
.s2-title .s2-badge{left:118px}
.s2-badge .t{padding:4px 9px;border-radius:2px;
  font-size:var(--s2-t-key);letter-spacing:.10em;text-transform:uppercase;
  color:var(--s2-amber);line-height:1;
  box-shadow:inset 0 0 0 1px rgba(255,176,46,.55);
  text-shadow:0 1px 4px rgba(5,7,11,.95)}

/* THE LOGOTYPE — the one place the ramp buys scale, declared in §4 as a
   title-only step. Stacked the way a highway sign is stacked: the article
   small and letterspaced over the name at 56px. It is still ONE object in the
   §T9 slot and still the crown `tools/hierarchy.js` reads. */
.s2-logo{top:44px;height:96px;width:430px;z-index:6}
.s2-logo .sm{display:block;max-width:430px;font-size:var(--s2-t-label);letter-spacing:.42em;
  margin-left:96px;
  text-transform:uppercase;
  color:var(--s2-mute-hi);line-height:1;
  text-shadow:0 2px 8px rgba(5,7,11,.95)}
.s2-logo .lg{display:block;max-width:430px;margin-top:7px;font-size:56px;letter-spacing:.045em;
  text-transform:uppercase;
  color:var(--s2-ivory);line-height:1;
  text-shadow:0 3px 0 rgba(5,7,11,.55),0 4px 22px rgba(5,7,11,.95)}
/* THE ARC — `CONFEDERATION → THE FREE REPUBLIC`, the shipped title's best
   line and the one a blind judge called the single most useful string on any
   of these screens. T-LABEL, directly under the logotype, plainly subordinate
   to the 56px name above it and the 26px score below it. */
.s2-arc{position:absolute;left:22px;top:138px;width:500px;height:22px;z-index:6}
.s2-arc .t{font-size:var(--s2-t-label);letter-spacing:.07em;
  text-transform:uppercase;color:var(--s2-ivory);
  text-shadow:0 2px 8px rgba(5,7,11,.95),0 1px 0 rgba(0,0,0,.6)}

/* the goal line drops under the logotype and the arc line rather than under
   the one-line name every other named screen carries */
.s2-title .s2-goal{top:170px}

/* THE TAGLINE — §4's VOICE face. 17px, not 15, and ivory, not #e4dfd3, on the
   column wash: it is the sentence the screen exists to deliver and it was
   being skipped. Three lines at 520px, clearing the truck at x560 by 18px. */
.s2-lead{position:absolute;left:22px;top:226px;width:520px;height:72px;z-index:6}
.s2-lead .b{display:block;font-family:var(--s2-voice);font-weight:400;
  font-size:17px;line-height:1.36;letter-spacing:0;color:var(--s2-ivory);
  white-space:normal;
  text-shadow:0 1px 3px rgba(5,7,11,1),0 0 10px rgba(5,7,11,.94)}
/* 13px and `mute-hi`, one step up on size and one on value — the squint fix */
.s2-meta{position:absolute;left:22px;top:306px;width:520px;height:16px;z-index:6}
.s2-meta .t{font-size:13px;letter-spacing:.12em;color:var(--s2-mute-hi);
  text-shadow:0 1px 4px rgba(5,7,11,1),0 0 9px rgba(5,7,11,.9)}
/* the gloss on the hook. Last line before the button it explains. */
.s2-gloss{position:absolute;left:22px;top:328px;width:520px;height:16px;z-index:6}
.s2-gloss .t{font-size:var(--s2-t-key);letter-spacing:.10em;
  text-transform:uppercase;color:var(--s2-mute-hi);
  text-shadow:0 1px 4px rgba(5,7,11,1),0 0 9px rgba(5,7,11,.9)}

/* ===========================================================================
   §8.2 · FOUNDERS
   Three cards in ACTION-1, no rail, no green, and the billboard takes the lamp
   because on this screen the billboard is the question being asked — §5's
   second rung, applied by its own stated reason rather than by its screen
   name. See the block above s2RenderFounders().
   =========================================================================== */
/* the archetype, ≤4 words, at T-KEY in `mute`, ahead of the two numbers */
.s2-verb .tag.rl{color:var(--s2-mute);letter-spacing:.09em;
  overflow:hidden;text-overflow:ellipsis;max-width:150px}
/* A LIT BILLBOARD BLOOMS IN ITS OWN COLOUR, not in the alert's orange and not
   in the accent's green — the same principle the fork's lit sign is drawn on:
   this is a real object in the world that has been lit, not a control that has
   been painted. Specificity (0,2,0) so it beats the generic `.s2 .lit` filter.
   Warm, because the board is sun-bleached plywood and a cold halo on it read
   as a rendering error the one time it was tried. */
.s2 .s2-bill.lit{animation:s2billlamp 2.2s ease-in-out infinite}
@keyframes s2billlamp{
  0%,100%{box-shadow:0 6px 14px rgba(0,0,0,.5),inset 0 0 0 2px rgba(58,47,26,.42),
                     0 0 14px rgba(230,206,160,.24)}
  50%    {box-shadow:0 6px 14px rgba(0,0,0,.5),inset 0 0 0 2px rgba(58,47,26,.42),
                     0 0 30px rgba(230,206,160,.46)}
}
@media (prefers-reduced-motion:reduce){
  .s2 .s2-bill.lit{animation:none;
    box-shadow:0 6px 14px rgba(0,0,0,.5),inset 0 0 0 2px rgba(58,47,26,.42),
               0 0 26px rgba(230,206,160,.40)}
}

/* ===========================================================================
   §8.9 · REFERENDUM — THE BALLOT IS THE BILLBOARD.
   The one screen where the billboard is not a fact about a town but the
   question itself, printed the way it is printed on the paper: the question in
   HIGHWAY caps, the two boxes, and the church-hall detail underneath in the
   VOICE serif. THE BOXES ARE DRAWN — ☐ at 12px is a glyph that half of §4's
   fallback stacks render as tofu, and a drawn square costs no character on a
   frame with a character cap.
   =========================================================================== */
.s2-ref .s2-bill{gap:9px}
.s2-bill.ballot .q{display:block;font-family:var(--s2-hwy);font-weight:700;
  font-size:var(--s2-t-label);letter-spacing:.04em;text-transform:uppercase;
  color:#1d1709;line-height:1}
.s2-bill.ballot .bx{display:flex;align-items:center;gap:8px;
  font-family:var(--s2-hwy);font-weight:700;font-size:var(--s2-t-body);
  letter-spacing:.10em;text-transform:uppercase;color:#241d0d;line-height:1}
.s2-bill.ballot .bx i{display:inline-block;width:13px;height:13px;flex:none;
  margin-right:12px;background:rgba(250,246,236,.55);
  box-shadow:inset 0 0 0 1.5px rgba(38,30,14,.75)}
.s2-bill.ballot .k{display:block;font-family:var(--s2-voice);font-weight:400;
  font-size:var(--s2-t-key);letter-spacing:0;color:#3a2f1c;line-height:1.2;
  white-space:normal}
/* §8.9 draws the one press bottom-right, under the sign it has been counting
   down for forty-one days */
.s2-ref .s2-act1.one .s2-verb{left:616px}

/* ===========================================================================
   §8.10 · ENDING — THE GOAL SLOT HOLDS AN <h1>, AND THAT IS THE CROWN.

   `tools/playtest.js` reads `#frame h1` to name the ending it reached, so the
   title is an h1 and it is the only one on the frame. It sits in the GOAL
   LINE's slot, which is what makes CHANNEL 1 resolve here without a §T9 name:
   `A NARROW, LEGALLY AMBIGUOUS YES` already IS what you did here, and §T9 says
   in as many words that the ending's h1 does that job from the goal slot and
   does not get a second one.

   THE SLOT IS THE ONE GEOMETRY THIS SCREEN CHANGES, AND IT IS DECLARED.
   §2's goal slot is 360x62 and holds one 34px line. The endings' authored
   titles run to 39 characters — `Somebody Is Already Separating From You` —
   which is 640px of T-GOAL, so a 360px nowrap slot would clip a third of every
   one of them and a smaller step would hand the size crown to the sign. It is
   600x104 instead, wrapping to at most two lines, ending 24px clear of the
   sign at x646. 600px is 63% of the frame, well under BANDS' 85%, so widening
   it cannot turn the frame's most important object into a strip.
   =========================================================================== */
/* THE TRUCK MOVES RIGHT, DECLARED, LIKE THE TITLE'S AND THE CROSSING'S.
   §2 fixes TRUCK-WIDE at x284 on the SIGN at 646 and the BILLBOARD at 272.
   The ending has no billboard — the slab is in that column — and the slab is
   the thing that has to grow, because this frame's job is to be READ. At x572
   the whole left half is the scorecard and the roofline grazes the sign board
   by 8px, which is §2's own depth cue for the inner post. */
.s2-end .truck.wide{left:572px;top:176px}
.s2-end .s2-crew.wide{left:612px}
.s2-end .s2-goal{left:22px;top:56px;width:480px;height:92px;
  display:flex;flex-direction:column;align-items:flex-start;gap:8px}
.s2-end .s2-goal .v{display:-webkit-box;-webkit-line-clamp:2;
  -webkit-box-orient:vertical;overflow:hidden;
  width:100%;font-size:var(--s2-t-goal);letter-spacing:.02em;line-height:1.04;
  text-transform:uppercase;color:var(--s2-ivory);
  text-shadow:0 2px 10px rgba(0,0,0,.78),0 1px 0 rgba(0,0,0,.62)}
.s2-end .s2-goal .r2{position:static}
/* ONE WASH FOR THE WHOLE LEFT COLUMN, AND IT REPLACES FOUR PLATES.
   Blind, 3-0: "the ending is a wall of panels rather than a poster". It was —
   an <h1> on its own radial scrim, a record row, an obituary on a .90 steel
   plate and an epilogue on another .90 steel plate, stacked down the left half
   as four stacked boxes. The words are all kept and every box is gone: the
   obituary and the epilogue now sit ON THE PICTURE exactly the way the goal
   line and the record row already did, and the contrast they were buying with
   a fill is bought once, for the whole column, by a single left-anchored
   gradient that fades to nothing at x600.

   IT IS A SCRIM AND NOT A PANEL, ON THE FILE'S OWN MEASUREMENT RULE. Its stops
   mean .46 alpha, under _measure.js's .55 threshold, so it tints rather than
   covers; it is 600px, 63% of the frame against BANDS' 85%, so it cannot read
   as a strip; and it fades to zero on its right edge so it has no edge to read
   as a box. The two .90 plates it replaces were both over the threshold and
   both counted, which is the honest arithmetic of what came off. */
.s2-end .s2-wash{position:absolute;left:0;top:0;width:600px;height:427px;
  z-index:2;pointer-events:none;
  background:linear-gradient(90deg,rgba(4,7,12,.80) 0,rgba(4,7,12,.66) 42%,
                                   rgba(4,7,12,.30) 74%,rgba(4,7,12,0) 100%)}
.s2-end .s2-goal .s2-scrim{display:none}

/* ---------------------------------------------------------------------------
   THE RECORD — four numbers on one row, and the run is the only source.
   `Trail covered` is S.distance, `Days lasted` is S.day, `Final support` is
   S.support and `Freedom Score` is computeScore(): the same four the shipped
   scorecard prints, in the same order. The hook keeps its exact string, its
   amber numeral at T-SIGN and the left column; it has stopped standing on its
   own with nothing to be compared against.
   ------------------------------------------------------------------------ */
.s2-report{position:absolute;left:22px;top:158px;width:470px;height:44px;z-index:6;
  display:flex;align-items:flex-start;gap:0}
.s2-report .s2rc{flex:1 1 0;display:flex;flex-direction:column;gap:5px;
  padding-left:11px;box-shadow:inset 1px 0 0 rgba(152,162,175,.34)}
.s2-report .s2rc:first-child{padding-left:0;box-shadow:none}
.s2-report .s2rc .k{font-size:var(--s2-t-key);letter-spacing:.09em;
  text-transform:uppercase;color:var(--s2-mute);
  text-shadow:0 1px 4px rgba(5,7,11,.98)}
.s2-report .s2rc .n{font-size:var(--s2-t-sign);letter-spacing:.01em;
  color:var(--s2-ivory);
  text-shadow:0 1px 4px rgba(5,7,11,.98),0 0 10px rgba(5,7,11,.9)}
.s2-report .s2rc.hi .n{color:var(--s2-amber)}

/* the obituary, in the caption-slab slot — never lit, because this one is a
   postscript and not a question (§5's second rung says so). It is 534 wide
   rather than 250 because the truck moved and because three lines of serif at
   the reading width is what a poster does with a paragraph. */
.s2-end .s2-slab{left:22px;top:206px;width:544px;height:44px;padding:0;
  border-radius:0;background:none;box-shadow:none}
.s2-end .s2-slab .b{margin-top:0;font-size:var(--s2-t-body);line-height:1.34;
  color:#ece7db;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  overflow:hidden;
  text-shadow:0 1px 3px rgba(5,7,11,1),0 0 9px rgba(5,7,11,.96)}

/* WHAT HAPPENED TO THE PEOPLE. The party goes in the picture on every other
   screen (§6 kill #2) and the ending is the one frame where that ends: the run
   is over, the busts on the box rail have nothing left to say, and this is the
   sentence anybody who screenshots this screen is screenshotting it for. */
.s2-epi{position:absolute;left:22px;top:258px;width:544px;height:86px;z-index:6;
  padding:0;overflow:hidden}
.s2-epi .k{display:block;font-size:var(--s2-t-key);letter-spacing:.12em;
  text-transform:uppercase;color:var(--s2-mute-hi);
  text-shadow:0 1px 3px rgba(5,7,11,1),0 0 8px rgba(5,7,11,.95)}
.s2-epi .b{display:block;margin-top:6px;font-family:var(--s2-voice);font-weight:400;
  font-size:13px;line-height:1.34;color:#e6e1d5;letter-spacing:0;
  white-space:normal;
  display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;
  overflow:hidden;
  text-shadow:0 1px 3px rgba(5,7,11,1),0 0 9px rgba(5,7,11,.96)}
/* RUN RECEIPT — an ending-only reading layer. It is intentionally modal: the
   fixed 16:9 poster has no honest spare band for two more paragraphs, while a
   fourth 62px verb already has a declared layout and remains a 44px target. */
.s2rr-shade{position:absolute;inset:0;z-index:80;background:rgba(2,5,9,.84);
  display:flex;align-items:center;justify-content:center;padding:22px}
.s2rr-panel{width:760px;max-height:370px;overflow:auto;padding:18px 20px 16px;
  background:linear-gradient(180deg,#101c29,#070d15);
  box-shadow:0 0 0 1px rgba(150,205,255,.32),0 18px 60px rgba(0,0,0,.7);
  clip-path:polygon(0 8px,8px 8px,8px 0,100% 0,100% calc(100% - 8px),calc(100% - 8px) calc(100% - 8px),calc(100% - 8px) 100%,0 100%)}
.s2rr-head{display:flex;align-items:flex-start;justify-content:space-between;gap:18px;
  padding-bottom:12px;border-bottom:1px solid rgba(150,205,255,.2)}
.s2 .s2rr-over{display:block;white-space:normal;font-size:9px;letter-spacing:.2em;text-transform:uppercase;color:var(--s2-mute-hi)}
.s2 .s2rr-head h2{display:block;white-space:normal;margin-top:5px;font-size:25px;line-height:1;text-transform:uppercase;
  letter-spacing:.04em;color:var(--s2-ivory)}
.s2rr-close{position:static;min-width:94px;min-height:50px;height:50px;border:0;cursor:pointer;
  padding:0 13px;text-transform:uppercase;font-size:12px;letter-spacing:.1em;
  color:var(--s2-ivory);background:var(--s2-steel-a);box-shadow:0 0 0 1px var(--s2-keyline)}
.s2rr-close:focus-visible{outline:3px solid var(--s2-mint);outline-offset:3px}
.s2rr-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));margin-top:12px}
.s2rr-row{min-width:0;padding:4px 16px 5px 0}
.s2rr-row+.s2rr-row{padding-left:16px;border-left:1px solid rgba(150,205,255,.18)}
.s2rr-k{display:block;font-size:9px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--s2-mute-hi);margin-bottom:6px}
.s2rr-row p{font-family:var(--s2-voice);font-size:15px;line-height:1.42;color:#e6e1d5}
.s2rr-row p b{display:block;margin-bottom:4px;font-size:13px;line-height:1.2;
  letter-spacing:.05em;text-transform:uppercase;color:var(--s2-ivory)}
.s2rr-row p span{display:block;color:#bcc7d0}
.s2rr-decisions{grid-column:1/-1;margin-top:8px;padding-top:11px!important;
  border-left:0!important;border-top:1px solid rgba(150,205,255,.18)}
.s2rr-decisiongrid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:18px}
.s2rr-decisiongrid p{min-width:0}
.s2rr-foot{margin-top:13px;padding-top:10px;border-top:1px solid rgba(150,205,255,.16);
  font-size:10px;letter-spacing:.11em;text-transform:uppercase;color:var(--s2-mute-hi)}
/* the ending's sign is a TOWN-LIMIT board for whatever you actually got, so
   its second line is a phrase rather than a place plus a numeral, and it is
   set one step down to fit `A PROVINCE OF CANADA` inside the same board */
.s2 .sign .pl.sm{font-size:var(--s2-t-body);letter-spacing:.06em}

/* ===========================================================================
   TOUCH — §9.6.3. 44px minimum in every orientation. These are the floors,
   not the sizes: nothing here is allowed to shrink under them.
   =========================================================================== */
.s2 button{min-height:44px}
.s2 .s2-cell{pointer-events:none}


/* ===========================================================================
   THE SLOT GAUGE — see s2SlotsHTML(). x22, in the 26px band between the goal
   line and the shelf, on the one screen where the box's capacity is a control
   the player is operating rather than a number they look up. Not a button:
   nothing on this frame under 44px is tappable. */
/* WAVE 10 — IT WAS ON THE FRAME AND IT COULD NOT BE READ, AND ONE JUDGE READ
   IT AS SOMETHING ELSE. All three failed to find the capacity readout; one
   filed it as "a progress bar for the referendum". Nothing here is added or
   taken away — the same pips and the same fraction — but four things change so
   that what is on the screen can be read for what it is:
     1. THE FRACTION LEADS, at T-LABEL ivory instead of T-KEY mute. It was
        "the smallest, greyest type on the screen"; it is now the same step as
        a status numeral, which is what it is.
     2. THE PIPS FOLLOW rather than lead, so the eye lands on a number and
        reads a picture of it, not on a stripe under a percentage.
     3. THE PIPS STOP LOOKING LIKE A BAR. Gap 2px -> 5px and every empty pip
        keeps an ivory keyline round a dark well, so the strip reads as a row
        of discrete cells with holes in it. A progress bar is continuous; this
        one now cannot be, at any distance.
     4. A WASH UNDER THE WHOLE GAUGE — the title's own fix, which won that
        screen 3-0 — so it is an object sitting in the band under the goal
        block rather than a third line of it. Gradient, never a flat colour:
        §10's INK metric counts a background-COLOUR and not a background-image,
        and a plate that buys legibility should not buy ink with it. */
.s2-slots{position:absolute;left:22px;top:155px;height:26px;
  z-index:6;display:inline-flex;align-items:center;gap:11px;pointer-events:none;
  padding:0 9px;border-radius:3px;
  background:linear-gradient(180deg,rgba(10,13,19,.86),rgba(5,7,11,.90));
  box-shadow:0 0 0 1px rgba(63,71,83,.9),0 4px 12px rgba(0,0,0,.6)}
.s2-slots .pips{display:flex;align-items:center;gap:5px}
.s2-slots .pips i{display:block;width:6px;height:15px;border-radius:1px;
  box-shadow:inset 0 0 0 1px rgba(242,238,228,.34);
  background:rgba(242,238,228,.05)}
/* what is already in the box */
.s2-slots .pips i.f{background:var(--s2-ivory);box-shadow:0 0 0 1px rgba(0,0,0,.8)}
/* and what the selected good would take — the amber is money's colour and a
   slot is what the money buys room for */
.s2-slots .pips i.p{background:var(--s2-amber);box-shadow:0 0 0 1px rgba(0,0,0,.8)}
.s2-slots .n{font-size:var(--s2-t-label);letter-spacing:.03em;line-height:1;
  color:var(--s2-ivory);white-space:nowrap;
  text-shadow:0 1px 3px rgba(0,0,0,1),0 0 7px rgba(0,0,0,.9)}
/* the divider and the key stay where §T3 puts a key: T-KEY, mute, beside the
   numeral rather than instead of it */
.s2-slots .n .sl{display:inline;color:var(--s2-keyline);margin:0 5px}
.s2-slots .n .ky{display:inline;font-size:var(--s2-t-key);
  letter-spacing:.09em;color:var(--s2-mute);margin-left:7px}


/* ===========================================================================
   §8.2 · FOUNDERS — THE CARD IS A PERSON.

   THE CALL, MADE ON THE TWO FRAMES SIDE BY SIDE. The shipped screen is the
   better screen and it is not close: it has FACES, it says what each person
   IS (`The Oil Baron`, `The Talk-Radio Firebrand`), it states the advantage
   you are picking in a sentence, and it lets you build one. Ours had three
   surnames and a pair of unexplained deltas — `+$287 −5` — on the one screen
   in the game whose entire subject is WHO. `PICK YOUR SEPPY` at 34px over a
   row of four steel oblongs is a menu of strings, not a cast.

   WHAT WAS TAKEN FROM THE BUILDER AND WHAT WAS NOT. The builder's win is its
   CONTENT — a face, a name, a role, and one stated advantage — and all four
   are now on the card. Its wizard is not: the appearance selectors are
   cosmetic, and the one mechanically live choice it makes (which past you had)
   is the same choice these three cards make with the writing already done. So
   `Make one up` stays, at the same size, in the same row, as the fourth EQUAL
   option rather than a footnote — and it is the one door on this screen that
   leads to more than it shows.

   THE CARD IS 220x114 AND IT IS NOT A PANEL. Four filled boxes 114px tall
   across 912px is the wall this whole system exists to treat, so the founders
   take the STORE COUNTER's own move: the portrait is the object, the type has
   its contrast from its own shadow, and the only ink is a hairline. */
/* WAVE 10 — THE CARD GROWS 14px DOWNWARD AND THE PERK LINE SPENDS ALL OF IT.
   The perk is the only run on this card that says what the choice DOES, and it
   was the smallest run on the card: T-KEY Georgia, two clamped lines, under a
   T-KEY role, under a T-LABEL name. A serif at 12px is the least legible
   combination this stylesheet is capable of producing and it was carrying the
   decision. It goes to T-BODY, which is the step §4 gives the VOICE face
   everywhere else it appears — the event's body, the billboard, the ending's
   paragraph — and the two lines it needs come out of the 21px of dead frame
   under the row, not out of anything above it. Nothing is cut, nothing moves
   up, and the row's top edge stays at 284 where §2's TRUCK-PARKED clearance
   put it. */
.s2-fndrow{top:284px;height:136px;gap:8px}
.s2-fndrow .s2-verb.fnd{width:220px;height:128px;padding:0;
  display:block;top:0;overflow:hidden;
  background:linear-gradient(180deg,rgba(17,22,31,.72),rgba(8,11,17,.80));
  box-shadow:0 0 0 1px var(--s2-keyline),0 6px 16px rgba(0,0,0,.55)}
.s2-fndrow .s2-verb.fnd .fp{position:absolute;left:9px;top:8px;
  width:42px;height:42px;border-radius:2px;object-fit:cover;object-position:50% 12%;
  box-shadow:0 0 0 1px rgba(242,238,228,.30),0 3px 8px rgba(0,0,0,.7)}
/* chad.webp and darlene.webp are head-on portraits; hank.webp is a wide plate
   with the man leaning on a fence at the FAR RIGHT of it, so a centred square
   crop of it is a photograph of a fence. Cropped to where his face actually is
   rather than nudging the plate, which lives in an asset folder this round
   does not touch. */
.s2-fndrow .s2-verb.fnd .fp[src*="hank"]{object-position:86% 20%}
/* the fourth card has no photograph because it has no face yet — an empty
   frame is the honest picture of `Make one up`, and it is drawn rather than
   typed so it costs no character and cannot render as tofu */
.s2-fndrow .s2-verb.fnd .fp.mk{background:
    repeating-linear-gradient(135deg,rgba(242,238,228,.07) 0 5px,transparent 5px 10px);
  box-shadow:0 0 0 1px rgba(242,238,228,.28) inset,0 0 0 1px rgba(0,0,0,.6)}
.s2-fndrow .s2-verb.fnd .vl{position:absolute;left:59px;top:5px;width:150px;height:42px;
  font-size:var(--s2-t-label);line-height:1.00;letter-spacing:.02em;overflow:hidden;
  text-align:left;white-space:normal;text-transform:uppercase;
  color:var(--s2-ivory);text-shadow:0 1px 4px rgba(0,0,0,.95)}
/* WHAT THEY ARE. The role is the half of the identity a surname cannot carry,
   and it is the deck's own string. T-KEY `mute`, two lines at 146px. */
/* one line, always, and clipped rather than wrapped: the name above it is
   allowed two lines and the role is what would otherwise push the sentence
   under it off the card. */
/* `.ro`, not `.rl` — `.rl` is a TAG class and this rule would otherwise
   grab the `6 PASTS` chip on the fourth card and stack it on the role. */
.s2-fndrow .s2-verb.fnd .ro{position:absolute;left:9px;top:52px;width:202px;
  font-size:var(--s2-t-key);line-height:1.12;letter-spacing:.04em;
  text-align:left;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  color:var(--s2-mute-hi)}
/* WHAT YOU ARE PICKING, IN A SENTENCE. `perkText` is the deck's own and it is
   the only line on the card that says what the choice DOES. VOICE serif,
   because §4 licenses prose in three places and a card that is a person
   talking about themselves is the same object as the event's slab. */
.s2-fndrow .s2-verb.fnd .pk{position:absolute;left:9px;width:202px;top:67px;
  font-family:var(--s2-voice);font-weight:400;text-transform:none;
  font-size:var(--s2-t-body);line-height:1.14;letter-spacing:0;
  text-align:left;color:var(--s2-ivory);
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  overflow:hidden;white-space:normal;text-shadow:0 1px 4px rgba(0,0,0,.95)}
/* and the two deltas, on the floor of the card where every other verb in the
   game keeps its price tags */
.s2-fndrow .s2-verb.fnd .vr{left:9px;right:9px;bottom:4px;gap:9px}
.s2-fndrow .s2-verb.fnd:hover{box-shadow:0 0 0 1px var(--s2-mute),0 6px 16px rgba(0,0,0,.6)}

/* §T9's name box is 412px and `THE MONTANA BORDER` sets to ~460 at T-GOAL, so
   on this one screen the box takes the room the frame has spare. It is the
   same licence §8.3 already spends in the other direction — the store NARROWS
   its box from 412 to 370 so a long store title ellipsises before it reaches
   the fender. Nothing lives in x434..620 at y60 on the fork: the rail is four
   cells anchored right and TRUCK-PARKED tops at y136. */
.s2-fk .s2-name{width:462px}
.s2-fk .s2-name .t{max-width:462px}

/* Eight authored border scenes now read as eight scenes. The first sentence
   stays on the calm face and the rest opens in place, clear of the sign at
   x646 and of the action row at y352. */
.s2-fkbeat{position:absolute;left:22px;top:100px;width:560px;max-height:170px;
  z-index:6;overflow:auto;scrollbar-width:thin}
.s2-fkbt{display:block;margin-bottom:4px;font-family:var(--s2-hwy);
  font-size:var(--s2-t-label);line-height:1.08;letter-spacing:.055em;
  text-transform:uppercase;color:var(--s2-ivory);text-shadow:0 2px 8px rgba(0,0,0,.9)}
.s2-fkcase summary{display:block;cursor:pointer;list-style:none;outline:none}
.s2-fkcase summary::-webkit-details-marker{display:none}
.s2-fkcase summary:focus-visible{outline:2px solid var(--s2-go-key);outline-offset:3px}
.s2-fkbx{display:block;font-family:var(--s2-voice);font-weight:400;
  font-size:var(--s2-t-body);line-height:1.34;letter-spacing:0;color:#e6e1d5;
  text-shadow:0 1px 3px rgba(0,0,0,.85),0 0 14px rgba(0,0,0,.75)}
.s2-fkcue{display:block;margin-top:4px;font:800 var(--s2-t-key)/1 var(--s2-hwy);
  letter-spacing:.10em;text-transform:uppercase;color:#8fe0c8}
.s2-fkcue::after{content:'  ▾'}
.s2-fkcase[open] .s2-fkcue::after{content:'  ▴'}
.s2-fkmore{margin:7px 0 0;padding:7px 9px;border-top:1px solid rgba(143,224,200,.45);
  font:400 var(--s2-t-body)/1.3 var(--s2-voice);color:#f0eadf;
  background:linear-gradient(90deg,rgba(7,14,19,.9),rgba(7,14,19,.55));
  text-shadow:0 1px 3px rgba(0,0,0,.9)}

/* WAVE 10 — THE ARM LABELS. `NORTH · LAST 18%`, `NO GROUND` and `SOUTH` are
   the only things on the fork's three verbs that say WHICH WAY EACH ONE GOES,
   which is the entire question the screen is asking. They were T-KEY in
   `mute`, one step under the sign's own third line and two under the labels
   they belong to, and at 952x427 they are a grey smear under a white word.
   The direction goes to T-BODY in `mute-hi`; `THIS ENDS THE RUN` goes to
   T-BODY and keeps `alarm`, because the one arm that ends the game should not
   be whispering it. No word changes and no tag is added — §T6's cap of two per
   verb is untouched. The `.rl` clip widens with the type so `NORTH · LAST 18%`
   still sets whole; the verb is 296px with 28px of padding, and the widest
   pair in the deck sets to ~205px.
   The same split the crossing makes: what moves is the LABEL and the
   consequence SENTENCE, both of which §4 already sets at T-BODY elsewhere;
   `+6 😡` is a price tag and stays at T-KEY like every price tag in the game. */
.s2-fk .s2-verb .tag.rl,
.s2-fk .s2-verb .tag.arm,
.s2-fk .s2-verb .tag.sen{font-size:var(--s2-t-body);letter-spacing:.02em}
.s2-fk .s2-verb .tag.rl,
.s2-fk .s2-verb .tag.arm{color:var(--s2-mute-hi);letter-spacing:.05em;max-width:200px;
  overflow:hidden;text-overflow:ellipsis}
.s2-fk .s2-verb .vr{gap:9px;bottom:8px}

/* ---- §WX Wildfire smoke glowing embers ----------------------------------- */
.k-smoke i{top:-9%;width:var(--sz);height:var(--sz);border-radius:50%;
  background:rgba(255,140,40,.85);box-shadow:0 0 4px rgba(255,90,10,.8);
  animation-name:wxember}
@keyframes wxember{0%{opacity:0;transform:translate3d(14vw,0,0)}
  15%{opacity:.92}82%{opacity:.6}100%{opacity:0;transform:translate3d(-112vw,78vh,0)}}
