/* rgbVersion: self-contained signal-color interface. */


:root{

  --deep:#000;
  --sea:#0b2b36;

  --go:#3fa62b;
  --go-lit:#57c93f;
  --go-ink:#f2fff0;
  --take:#d2822a;
  --take-lit:#eda049;
  --take-ink:#fff8ee;
  --stop:#e03a34;
  --stop-lit:#f2564f;
  --stop-ink:#fff2f1;
  --crash-red:#d32f2f;
  --slate:#164150;
  --gold:#f3c257;
  --teal:#12b3a6;
  --teal-lit:#3fe3cf;
  --sand:#f7e681;

  --coral:#ff4052;
  --amber:#ffe640;
  --mint:#38ed70;
  --text:#eafaf6;
  --dim:#7ba8a6;

  /* THE OPTIONS MENU'S PALETTE, as four hooks rather than six literals. The
     menu is shared markup across every build, but each build paints its deck
     differently -- gold on blue here, green on black under the signal palette
     -- and a menu with its greens written in would be the one panel wearing
     another theme's colours. These carry the coast defaults; a build that
     repaints its deck restates them beside it. */
  --menu-surface:#0a2430ee;
  --menu-line:#f3c25740;
  --menu-ink:#c9d9d6;
  --menu-hot:var(--teal-lit);

  --road-centre:50%;
  --title:'Barlow Condensed',Impact,sans-serif;
  --body:'Barlow',system-ui,sans-serif;
}

*{box-sizing:border-box;margin:0}
html,body{height:100%;
  /* THE LONG PRESS IS A LANE CHANGE, NOT A TEXT SELECTION. Every steering
     control is text in a box -- WILD, RISKY, SAFE, DRIVE, CASH OUT -- so on
     iOS a press held past ~500ms raises the selection loupe and the
     copy/define callout over the road instead of moving the car. It is easy
     to hold a lane button that long while watching the multiplier, and the
     callout then has to be dismissed before play resumes.

     On `html,body` rather than on the buttons because the readout, the lane
     tags, the credits badge and the toast are all selectable text lying on
     the canvas and all of them raise the same loupe. The dialogs opt back in
     below: FAIR PLAY prints a seed and a commitment hash that exist to be
     copied, so they must stay selectable.

     `overscroll-behavior:none` alongside it, for the rubber band. `overflow:
     hidden` on `body` already stops the document scrolling, but on iOS the
     whole page can still be dragged away from the top or bottom edge and
     released -- and with `.stage{height:100dvh}` there is no scroll room to
     absorb it, so the road lifts off its edge and drops back. `.deck` has
     carried `overscroll-behavior:contain` for exactly this reason since it
     became scrollable; this is the same guarantee for the page under it. */
  overscroll-behavior:none;
  -webkit-user-select:none;user-select:none}
dialog,dialog *{-webkit-user-select:text;user-select:text}
body{
  background:var(--deep);color:var(--text);
  font-family:var(--body);font-weight:600;
  overflow:hidden;
  -webkit-tap-highlight-color:transparent;
}
/* `manipulation` and not `none`, which is the opposite of the choice made on
   the canvas and for the opposite reason. What has to go is the double tap:
   the three lane buttons are the other way to steer, and two lane changes in
   quick succession are two taps on two buttons 254px apart at 1366x1024 --
   inside the double-tap window, and enough to zoom the page out from under a
   round. What has to STAY is pan and pinch, because a control can end up
   inside the options menu or a dialog, and a player who has zoomed the rules
   text in must be able to scroll it. */
button,summary{touch-action:manipulation}
button{font:inherit;color:inherit;background:none;border:0;cursor:pointer;padding:0}
button:disabled{cursor:not-allowed;opacity:.35}
button:focus-visible{outline:2px solid var(--teal-lit);outline-offset:3px}
[hidden]{display:none!important}

.stage{height:100dvh;position:relative}

.road{position:absolute;inset:0;overflow:hidden;background:#05222a;isolation:isolate}
.road canvas{display:block;width:100%;height:100%;
  /* NOTHING THE BROWSER DOES WITH A TOUCH ON THIS CANVAS IS WANTED. The page
     has no scroll -- `body{overflow:hidden}` above -- so `auto` buys nothing
     and costs three separate faults on an iPad, all of them live today
     because `touch-action` appears nowhere else in this file.

     Double-tap zoom is the one that breaks play. The viewport meta says
     `width=device-width,initial-scale=1` with no `user-scalable=no`, which is
     the right call for accessibility and also what leaves the page zoomable,
     so two taps inside 300ms anywhere on the road zoom it. Steering IS
     tapping the road, and a lane change followed quickly by another is the
     commonest thing a player does: measured at 1366x1024, the two taps that
     take the car WILD -> SAFE land 508px apart and well inside the
     double-tap window. Once Safari zooms, the visual viewport stops matching
     the layout viewport, the canvas is scaled bitmap rather than redrawn, and
     resize() is never told -- `--dock-inset`, `geometry.h` and the click
     guard all go on describing a page that is no longer on screen.

     The other two are quieter. A drag begun within a few pixels of the left
     edge is Safari's swipe-back, which leaves the game; and a two-finger
     pinch over the road scales the page the same way a double tap does.
     `none` rather than `manipulation` because `manipulation` only gives up
     the double tap and keeps pan and pinch, and this surface wants to keep
     every horizontal drag for itself -- there is nothing on it to pan.

     `click` is unaffected: it still fires on a tap, which is what
     `canvas.onclick` in app.js steers from. The 350ms tap delay is NOT what
     this line is about and was never present here -- iOS dropped it for
     `width=device-width` pages in 9.3. */
  touch-action:none}

.lane-tags{

  position:absolute;top:var(--road-top,0px);left:var(--road-centre);transform:translateX(-50%);

  width:min(62%,560px);
  display:grid;grid-template-columns:repeat(3,1fr);

  z-index:3;
}
@property --tint{syntax:'<color>';inherits:true;initial-value:#0000}
.lane-tag{
  padding:clamp(9px,1.4vh,15px) 4px clamp(8px,1.2vh,13px);
  text-align:center;line-height:1;

  background:
    linear-gradient(var(--tint,#0000),#0000 76%),
    linear-gradient(#04151b8c,#04151b52 54%,#04151b00 78%);

  animation:tag-in .5s cubic-bezier(.22,.9,.3,1) both;
  animation-delay:calc(.08s + var(--n,0)*.07s);

  transition:background .2s,--tint .2s;

  position:relative;
}
@keyframes tag-in{from{opacity:0;transform:translateY(-12px)}to{opacity:1;transform:none}}
.lane-tag.hot{--tint:#ff40522b;--n:0}
.lane-tag.warm{--tint:#ffe6402b;--n:1}
.lane-tag.safe{--tint:#38ed702b;--n:2}

.lane-tag.hot.active{--tint:#ff40524a}
.lane-tag.warm.active{--tint:#ffe6404a}
.lane-tag.safe.active{--tint:#38ed704a}

.lane-tag em{
  display:block;font-family:var(--title);font-size:clamp(19px,2.1vw,32px);
  font-style:normal;letter-spacing:.6px;margin:5px 0 2px;color:#fffdf5;

  text-shadow:0 2px 6px #000000b8,0 0 2px #000000d9;
}
.lane-tag small{display:block;font-size:clamp(8px,.68vw,12px);letter-spacing:1.5px;font-weight:800;
  text-shadow:0 1px 4px #000000c4,0 0 2px #000000b8}

.lane-tag b{display:block;font-family:var(--title);font-size:clamp(13px,1.3vw,20px);margin-top:3px;letter-spacing:-.2px;opacity:.82;
  text-shadow:0 1px 4px #000000c4,0 0 2px #000000b8}
.lane-tag.hot small,.lane-tag.hot b{color:var(--coral)}
.lane-tag.warm small,.lane-tag.warm b{color:var(--amber)}
.lane-tag.safe small,.lane-tag.safe b{color:var(--mint)}

.lane-tag:not(:disabled):hover::after{opacity:.5}
.lane-tag:disabled{opacity:1;cursor:default}

.lane-tag::after{
  content:'';position:absolute;left:12%;right:12%;bottom:0;height:2px;
  background:linear-gradient(90deg,transparent,currentColor 22%,currentColor 78%,transparent);
  opacity:0;transition:opacity .18s;
}
.lane-tag.hot::after{color:var(--coral)}
.lane-tag.warm::after{color:var(--amber)}
.lane-tag.safe::after{color:var(--mint)}

.icon-defs{position:absolute;width:0;height:0;overflow:hidden}

.lane-tag .mark{display:none}
.mark{
  display:grid;place-items:center;margin:0 auto;
  width:var(--mark,clamp(26px,2.5vw,42px));height:var(--mark,clamp(26px,2.5vw,42px));
  border-radius:50%;border:1.5px solid currentColor;
  background:radial-gradient(circle at 50% 45%,#ffffff1f,#04151b66 72%);
  transition:box-shadow .2s,transform .2s;
}
.mark svg{width:60%;height:60%;fill:currentColor;display:block}
.hot .mark{color:var(--coral);box-shadow:0 0 12px #ff40523d,inset 0 0 10px #ff405226}
.warm .mark{color:var(--amber);box-shadow:0 0 12px #ffe6403d,inset 0 0 10px #ffe64026}
.safe .mark{color:var(--mint);box-shadow:0 0 12px #38ed703d,inset 0 0 10px #38ed7026}

.lane-tag.active::after{opacity:1}
.lane-tag.active .mark{transform:scale(1.1)}
.lane-tag.hot.active .mark{box-shadow:0 0 22px #ff40528c,inset 0 0 12px #ff405259}
.lane-tag.warm.active .mark{box-shadow:0 0 22px #ffe6408c,inset 0 0 12px #ffe64059}
.lane-tag.safe.active .mark{box-shadow:0 0 22px #38ed708c,inset 0 0 12px #38ed7059}

.readout{

  position:absolute;top:clamp(100px,16.8vh,158px);left:var(--road-centre);
  transform:translateX(-50%);
  text-align:center;z-index:3;pointer-events:none;
}

.readout>span{display:none}
.readout>b{
  display:block;font-family:var(--title);font-weight:900;
  font-size:clamp(60px,9.2vw,146px);line-height:.82;letter-spacing:.01em;

  font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1;
  color:#fffdf5;

  text-shadow:0 0 18px #f7e68173,0 0 54px #f7e6813d,0 4px 0 #00000038;
}
.readout>b small{

  font-size:.78em;letter-spacing:0;opacity:1;color:var(--sand);

  vertical-align:.12em;margin-left:.04em;

  text-shadow:0 0 16px #f7e68173,0 0 46px #f7e6813d,0 4px 0 #00000038;
}
#laneStatus{
  display:none;align-items:center;justify-content:center;gap:5px;margin-top:14px;
  font-size:clamp(8px,.62vw,9.5px);letter-spacing:1.4px;font-weight:800;
  color:#eafaf6;background:#04151bcc;padding:4px 10px;border-radius:100px;
  box-shadow:0 2px 0 #00000028;
  transition:background .18s,color .18s;
}
#laneStatus i{width:5px;height:5px;border-radius:50%;background:var(--sand);flex:none}

.road.is-ticking #laneStatus{display:inline-flex;background:#c2261c;color:#fff4f1}
.road.is-ticking #laneStatus i{background:#ffd7a1}
.road.is-ticking .readout>b{color:#ff9484}

body[data-phase=crashing] .readout>b,
body[data-phase=lost] .readout>b{
  color:var(--crash-red);
  text-shadow:0 0 18px #d32f2f80,0 0 54px #d32f2f47,0 4px 0 #00000038;
}
body[data-phase=crashing] .readout>b small,
body[data-phase=lost] .readout>b small{
  color:var(--crash-red);
  text-shadow:0 0 16px #d32f2f80,0 0 46px #d32f2f47,0 4px 0 #00000038;
}

.road.is-draining #laneStatus{display:inline-flex;background:#d3261c;color:#fff6f2}
.road.is-draining #laneStatus i{background:#ffe08a}
.road.is-draining .readout>b{color:#ff8878}

.credits{
  /* TOP-RIGHT, the options button's mirror image (the owner, v5: "move DEMO
     CREDITS to the top right of the screen"): on a phone, and wherever the
     laptop's bar leaves it no room beside it (ON A LAPTOP, below, is where a
     laptop puts it now). Its top is the button's top and its right inset is
     the button's left inset, the same two clamps as `.deck-extras`, so the
     pair frame the road's far end from either corner. It used to sit at the
     foot of the road on the left, lifted clear of the bar and the sheet by
     `--dock-inset`; up here nothing docks, so nothing has to be cleared. The
     one layout it cannot take is the landscape phone's side panel, which
     owns that corner (below). */
  position:absolute;top:clamp(10px,1.6vh,18px);right:clamp(10px,1.4vw,18px);
  z-index:3;line-height:1;
  padding:clamp(8px,.9vh,11px) clamp(13px,1.1vw,17px) clamp(9px,1vh,12px);
  border-radius:12px;
  background:linear-gradient(#0a2430ee,#04141cf2);
  box-shadow:inset 0 0 0 1px #f3c25740,inset 0 1px 0 #ffe6a826,0 8px 22px #0000004d;
}
/* It arrives with the options button, from its own corner, at 1.2-1.6s of
   the page's entrance, and moves with the rest of that entrance when the
   road's intro re-bases it (`--hud-shift`, hud-fx.js). A class that
   result-fx.js takes off once it has run, so the badge carries no animation
   afterwards: a phone's crash steps it out with an animation of its own
   (section 10), and a base animation would replay this entrance every time
   that one ended. */
.credits.is-arriving{animation:credits-in .4s cubic-bezier(.22,.9,.3,1) calc(1.2s + var(--hud-shift,0ms)) both}
@keyframes credits-in{from{opacity:0;transform:translate(16px,-12px)}to{opacity:1;transform:none}}
/* THE SIDE PANEL OWNS THE TOP-RIGHT CORNER on a landscape phone, and left of
   it, between the SAFE tag and the panel, there is about 50px of sky at the
   badge's height (667x375: the tag's rate ends at x=305, the panel starts at
   371), too little for it. So the badge goes under the panel, at the foot of
   that column, its right edge on the panel's: the foot, not hung from the
   panel, because the panel is shorter mid-round and the badge would move
   between phases. It arrives from its own corner. The two arms are section
   4's: a near-square window below 600px has the phone's sheet at its foot,
   not a side panel, so its badge stays in the top-right corner. */
@media (min-width:600px) and (max-width:739px) and (max-height:540px) and (orientation:landscape),
       (max-width:599px) and (max-height:540px) and (min-aspect-ratio:3/2){
  .credits{top:auto;bottom:max(8px,env(safe-area-inset-bottom));right:max(8px,env(safe-area-inset-right))}
  .credits.is-arriving{animation-name:credits-in-foot}
}
@keyframes credits-in-foot{from{opacity:0;transform:translate(16px,12px)}to{opacity:1;transform:none}}
/* A small near-square window (below 440px wide, neither a tall phone nor a
   phone on its side) keeps the lane tags across the top of the screen, and
   there the SAFE tag reaches the badge: at 360x380 its rate runs 14px under
   the badge's left edge. The same badge, a size smaller, clears it down to
   360px; the owner's 463x459 pane is clear by 19px as it is. (`.road>` so it
   outranks the size the phone block sets further down.) */
@media (max-width:439px) and (min-aspect-ratio:2/3) and (max-aspect-ratio:1499/1000){
  .road>.credits{padding:5px 9px 6px}
  .road>.credits small{font-size:6.5px;letter-spacing:1px}
  .road>.credits b{font-size:15px;margin-top:3px}
}
.credits small{display:block;font-size:clamp(7px,.5vw,8.5px);letter-spacing:1.8px;font-weight:800;color:#c8a45e}
.credits b{
  display:block;font-family:var(--title);font-size:clamp(20px,2.2vw,34px);
  margin-top:4px;letter-spacing:-.6px;color:#fff8e6;
  font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1;
}

/* ON A LAPTOP, BESIDE THE BET BAR. The owner, 2026-09-28, once the past
   rounds ran along the top of the screen: "move democredits elswhere" -- to
   the bottom-left corner, by the betting bar -- and the fullscreen key that
   sat beside it gone ("only in hambrug"): fullscreen is the options menu's
   row. So on a laptop the top row is the options button and the rounds, and
   the balance sits with the bet. Where the deck floats as the laptop's bar
   and the badge fits between the screen's edge and the bar, app.js
   (placeCredits) says so with `.at-bar` and hands over where the badge's top
   centres it on the bar (`--bar-top`); the badge takes the options button's
   inset on the left, and arrives from its own corner. Beside the bar it is a
   size more compact, its figures nearer the bar's own, which is what lets it
   fit beside the bar on a 1280px laptop too (placeCredits measures it so). A phone's sheet and a
   tablet's bar span their screen, and a window whose bar leaves the badge no
   room beside it, so those keep the top-right corner above. */
.credits.at-bar{top:var(--bar-top,auto);bottom:auto;left:clamp(10px,1.4vw,18px);right:auto;
  padding:clamp(8px,.9vh,11px) clamp(10px,.8vw,15px) clamp(9px,1vh,12px)}
.credits.at-bar b{font-size:clamp(20px,1.95vw,30px)}
.credits.at-bar.is-arriving{animation-name:credits-in-bar}
@keyframes credits-in-bar{from{opacity:0;transform:translate(-16px,12px)}to{opacity:1;transform:none}}

.outcome{

  position:absolute;top:50%;left:var(--road-centre);

  translate:-50% -50%;rotate:-2.5deg;

  /* THE WHOLE PLATE IS BIGGER, on the owner's word -- "text and this badge
     much bigger". It was min-width clamp(210px,16vw,268px) inside a max-width
     of min(62%,320px), which at 1440x900 drew a 255x85 crash card across a
     656px stretch of asphalt: a plate covering 39% of the road it is stamped
     on, read at arm's length as a caption rather than as the end of a round.

     The max-width is the substance of the change. The road's WIDTH is never a
     custom property -- it survives only as the inline width JS puts on
     `.lane-tags` -- so `vw` is the only handle this stylesheet has on how wide
     the asphalt under the card is, and a flat 320px ceiling ignored it in both
     directions at once. `32vw` tracks the road, and the 420px term takes over
     above 1313px, where 32vw would start outrunning the road on a wide
     monitor.

     THERE WAS A THIRD TERM, `62%`, AND THE NOTE THAT USED TO STAND HERE SAID
     IT "keeps the old relative cap honest at the narrow end". It cannot, and
     never could. A percentage max-width resolves against the containing
     block; the containing block is `.road`; and `.road` is
     `position:absolute;inset:0` on a desktop and a full-width grid cell in the
     narrow layout, so its width is the VIEWPORT's width at every size these
     base rules reach. 62% of that is 62vw, which is larger than 32vw at every
     viewport there has ever been, so the term could never be the smallest of
     the three and the sentence defending it described something that cannot
     happen. Measured in the page, the road's width equals `innerWidth` to the
     pixel at 1920x1080, 1440x900, 1366x768, 1280x800, 1024x600, 900x1400 and
     861x541, and Chrome's computed max-width agrees. `.outcome.won` below
     carried the identical dead leg as `72%` and has lost it for the identical
     reason. */
  min-width:clamp(270px,21vw,345px);max-width:min(32vw,420px);
  padding:clamp(14px,1.8vh,21px) clamp(25px,2.4vw,36px) clamp(15px,1.9vh,22px);
  text-align:center;z-index:4;

  background:
    linear-gradient(105deg,#fff0 28%,#ffffff0d 47%,#fff0 66%),
    linear-gradient(#0d2c39f7,#061a23fb 54%,#03111afd);
  border:1px solid var(--rim,#ff6b5ea6);border-radius:var(--plate-r,16px);
  box-shadow:
    0 22px 46px #00000099,
    inset 0 1px 0 #ffffff2e,inset 0 -1px 0 #00000073,

    0 0 0 4px #04151b59,
    0 0 40px var(--halo,#ff6b5e38);

  outline:1px solid var(--rim-faint,#ff6b5e2e);outline-offset:4px;
  animation:crash-stamp .34s cubic-bezier(.2,.86,.26,1) both;
}

@keyframes crash-stamp{
  0%{opacity:0;rotate:-6.5deg;scale:1.18}
  30%{opacity:1;rotate:-1.1deg;scale:.963}
  56%{rotate:-3.2deg;scale:1.014}
  78%{rotate:-2.15deg;scale:.996}
  100%{opacity:1;rotate:-2.5deg;scale:1}
}

.outcome::before{
  content:'';position:absolute;inset:-3px;z-index:-1;pointer-events:none;
  border:2px solid var(--flash,#ffb4a4c4);border-radius:calc(var(--plate-r,16px) + 3px);
  box-shadow:0 0 26px var(--halo,#ff6b5e38);
  filter:blur(.7px);
  animation:crash-shock .30s cubic-bezier(.16,.72,.28,1) both;
}
@keyframes crash-shock{from{opacity:.7;scale:.97}to{opacity:0;scale:1.22}}

.outcome small{
  /* 8-10px was a caption under a caption. This line carries the only WORDS on
     either card -- END OF THE ROAD, THAT'S A GOOD RIDE, MAX MULTIPLIER
     REACHED -- and at 8px on a 1440 screen it measured 119px of ink beneath a
     42px headline, a ratio the eye files as small print rather than as the
     card's opening line. 10-13px is the same step the headline takes beside
     it, so the relationship between the two is unchanged and only the card
     got louder.

     Tracking has to follow the size or it visibly tightens as the type grows:
     a fixed 2.6px was .33em at 8px and would be .2em at 13px. 3.2px holds the
     spacing between .25em and .32em across the whole range. */
  display:block;margin-bottom:8px;
  font-size:clamp(10px,.8vw,13px);font-weight:800;letter-spacing:3.2px;color:#d6bdb7;
}
.outcome small::before,.outcome small::after{
  content:'';display:inline-block;vertical-align:middle;
  width:clamp(13px,1.5vw,24px);height:1px;margin:0 9px;
  background:linear-gradient(90deg,#0000,var(--rim,#ff6b5ea6));
}
.outcome small::after{background:linear-gradient(270deg,#0000,var(--rim,#ff6b5ea6))}

.outcome strong{
  display:block;font-family:var(--title);font-weight:900;

  /* THE CRASH PLATE GROWS TOO, AND BY LESS. The note under `.outcome.won`
     below calls this card "deliberately the quieter of the two"; that is a
     statement about the RATIO between the two plates, not a rule freezing
     this one at 42px. Growing only the winning card would leave the crash
     card -- the one a player sees far more often -- no longer reading as its
     sibling but as something left behind at the old scale. 38-56px is a 1.33x
     step where the win headline takes 1.55x, so the gap between the two
     widens from 1.38x to 1.61x: the hierarchy the old comment is defending
     comes out sharper than it went in, not flatter.

     Width was never this card's constraint and is not now -- the headline
     here is the six characters of 'CRASH!'. The eyebrow above is what sets
     the plate's width, which is why the min-width moved with it. */
  font-size:clamp(38px,5vw,56px);line-height:.96;color:#ff9c8d;

  letter-spacing:-.3px;text-wrap:balance;overflow-wrap:break-word;

  text-transform:uppercase;
  font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1;

  text-shadow:0 1px 0 #3c0c0b,0 0 30px #ff6b5e5c;
}
.outcome.won{--rim:#f3c257bd;--halo:#f7e68147;--rim-faint:#f3c2573b;--flash:#ffeeb4cc}
/* THE WINNING CARD IS THE BIGGER ONE. It carries one number now -- the money --
   where it used to carry that plus a multiplier restating it, so the space the
   second line vacated goes back into the figure rather than being left as air.
   It is scoped to `.won` and not to `.outcome`, because the crash card is
   deliberately the quieter of the two and inherits none of this.

   The growth is on the type and the padding, not a `scale`, so the rim, the
   1px border and the outline stay hairlines instead of being magnified into
   visible bands -- and the stamp animation, which drives `scale` on its own
   keyframes, is left with sole ownership of that property. */
.outcome.won{
  /* CENTRED ON THE ROAD, because the owner asked for it there: "move this to
     middle not where its is now". There is no `top` or `translate` written
     here at all any more -- the base `.outcome` rule above already centres the
     plate, and the shortest way to say "put it back" is to stop overriding it.

     What stood here was an anchor that hung the plate ASTERN of the car, off
     `--car-foot`, and the reasoning was sound as far as it went: `top:50%` puts
     this plate ON the hero by construction, because the chase camera fixes his
     screen position at .58333 of the road's drawable height at every window
     there is, and a plate centred on 50% of the same box lands on the same
     line. The enlargement above took that from most of the car to all of it --
     measured at 1440x830 on a five-figure payout the card spanned y 327.1-502.9
     against a painted body at 353.8-486.2, and at 1280x800 it covered 97.7% of
     the body. Below the car was the only placement where the two could not
     touch. It is also not the placement that was asked for, and the owner has
     seen both.

     THE COST, stated rather than buried, because the centre really does put the
     card over the car and the car is now the thing that moves. A banked round
     no longer parks the hero: he accelerates and RECEDES up the road, so his
     box shrinks and climbs toward the horizon from the frame the card is
     stamped. He therefore passes UP behind the plate instead of sitting parked
     behind it, and comes out above it small -- but for the first stretch of the
     departure he is behind the card, and over that stretch the pull-away is
     read in the road and the traffic rather than in the car. If that stretch
     ever wants shortening, the lever is the card, not the placement: fading or
     lifting the plate once it has been read hands the car back without moving
     it off the middle.

     `--car-foot` is still published by resize() in app.js. Nothing in this
     stylesheet reads it now. */
  /* `72%` is gone from this max-width, and the long note under the base
     `.outcome` above says why: the containing block is the full-width `.road`,
     so 72% is 72vw and can never be smaller than the 40vw beside it. */
  min-width:clamp(300px,26vw,430px);max-width:min(40vw,560px);
  padding:clamp(18px,2.4vh,30px) clamp(26px,3vw,44px) clamp(20px,2.6vh,32px);
  /* 16px was a fine radius on a 295px plate and reads as a hairline on a
     386px one, so it scales with the card. The `::before` flash already
     tracks it through `calc(var(--plate-r,16px) + 3px)` and needs no change.
     Every narrower block below has to restate this, because `.outcome.won`
     outranks a plain `.outcome{--plate-r:...}` whatever media query it sits
     in -- see the two restatements further down. */
  --plate-r:20px;
}
.outcome.won strong{
  color:#ffeec2;text-shadow:0 1px 0 #453105,0 0 30px #f7e68170;
  /* The money, 40-58px -> 46-90px. 58px is where the owner's screenshot was
     taken and is the number he called too small; 90px is the largest the
     figure can be without moving the point at which a payout wraps. Measured
     in the page at the 560px plate: a five-figure win ('+$12,345.67') needs
     461px of ink against a 474px content box, so it still holds one line,
     exactly as it does today at 58px. 92px breaks that and buys nothing the
     eye can see.

     `min(6.2vw,11vh)` rather than 6.2vw alone. The vw leg reaches the 90px
     cap at 1452px, which is right for a full-height screen -- but the card is
     centred on the road and has the multiplier readout above it, and on a
     SHORT window that clearance is the binding constraint, not the road's
     width. At 1440x700 -- what a 1440x900 screen becomes once browser chrome
     is taken off it -- 6.2vw alone left 20px between a wrapped seven-figure
     card and the readout. The 11vh leg only engages when the window is wider
     than about 1.77:1, takes that 20px back up to a measured 32px, and is inert
     at 1440x900, 1440x830, 1280x800 and 1512x860, where the vw leg is already
     the smaller of the two. */
  font-size:clamp(46px,min(6.2vw,11vh),90px);
}
/* The winning eyebrow is sized on its own rather than inheriting the crash
   card's, because it is the longer string by six characters -- MAX MULTIPLIER
   REACHED against END OF THE ROAD -- and it grows into a wider plate.

   The floor is set at the narrowest viewport this block still reaches, 861px,
   where the plate caps at 344px and the two decorative rules either side of
   the words take 62px of the line between them. Stepped through in the page
   there, the eyebrow holds one line at 8, 9 and 10px and goes to two at 11px
   -- and the thing that wraps first is the trailing rule, not the text, so it
   does not show up as a broken phrase, only as a stray dash under the line.
   10px is the last size that fits, and 62px of that line is spent on two
   decorations, which is what makes the ceiling so low for twenty-two
   characters of 10px type.

   (The colour here has been dead since the Signal palette section, which
   repaints this same selector further down; it is left alone because removing
   it would change nothing and this build is not the only one reading the
   file.) */
.outcome.won small{color:var(--teal-lit);font-size:clamp(10px,.95vw,16px);letter-spacing:3.8px}

.outcome span{
  /* Inert today and sized anyway. Both branches call setText('resultDetail','')
     and `.outcome span:empty` below collapses the line, so nothing here is
     drawn -- but if the detail line ever comes back it must not return at the
     old scale on a card that has grown around it. 19-26px keeps it at the
     same fraction of the headline it had before, and the ~41px of height it
     would add is well inside the clearance the card has to the multiplier at
     every shape measured. */
  display:block;margin-top:9px;
  font-family:var(--title);font-size:clamp(19px,1.8vw,26px);font-weight:800;
  line-height:1.08;letter-spacing:.2px;color:#ffc8ba;
  font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1;
  text-wrap:balance;

  text-shadow:0 1px 0 #00000059;
}

.outcome.won span{color:#ffd98c}
/* Both cards now empty this line rather than removing it, so its top margin
   would otherwise sit under the headline as a strip of dead space. `:empty`
   collapses it on whichever card is not using it, and it costs nothing on the
   day either one wants its detail line back. */
.outcome span:empty{display:none}
.outcome small:empty{display:none}

.outcome.won::after{
  content:'';position:absolute;inset:0;border-radius:inherit;overflow:hidden;
  background:linear-gradient(105deg,#fff0 38%,#fff3cc59 50%,#fff0 62%);
  animation:result-shine .9s ease-out .12s both;pointer-events:none;
}
@keyframes result-shine{from{opacity:0;transform:translateX(-45%)}40%{opacity:1}to{opacity:0;transform:translateX(45%)}}

.deck{
  position:absolute;z-index:4;
  top:clamp(10px,1.6vh,18px);right:clamp(10px,1.1vw,18px);
  width:clamp(272px,20vw,360px);

  max-height:calc(100dvh - clamp(20px,3.2vh,36px));
  background:
    linear-gradient(#0a2430fa,#061a23fc 46%,#04141cfd);
  border:1px solid #f3c25740;border-radius:14px;

  box-shadow:0 18px 48px #0000006b,inset 0 1px 0 #ffe6a82e;
  padding:clamp(11px,1.05vw,15px) clamp(11px,1.05vw,15px) clamp(10px,.95vw,14px);
  display:flex;flex-direction:column;gap:clamp(5px,.7vh,9px);
  overflow:auto;overscroll-behavior:contain;scrollbar-width:thin;
}

@keyframes deck-in{from{opacity:0;transform:translateX(34px)}to{opacity:1;transform:none}}
@keyframes sec-in{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}
.deck{animation:deck-in .5s cubic-bezier(.22,.9,.3,1) both}
.deck>*{animation:sec-in .42s cubic-bezier(.22,.9,.3,1) both;animation-delay:calc(.16s + var(--i,0)*.045s)}

.deck-sec{

  display:flex;align-items:center;justify-content:center;
  margin:clamp(2px,.5vh,6px) 0 clamp(-3px,-.3vh,-1px);
}
/* The header row now carries the options button as well as its label, so it
   is a flex row: hamburger hard left, label beside it. */
.deck-head{margin:0 0 1px;display:flex;align-items:center;gap:9px}
.sec-label{
  font-size:clamp(8px,.56vw,9px);letter-spacing:1.8px;font-weight:800;
  color:#9fc2bf;
}

.garage{
  display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(3px,.3vw,5px);
  background:#0a2732c4;box-shadow:inset 0 0 0 1px #ffffff17;
  border-radius:11px;padding:clamp(5px,.5vw,7px);
}
.car-card{
  padding:clamp(4px,.45vw,6px) 2px clamp(3px,.35vw,5px);
  border-radius:8px;text-align:center;line-height:1;

  background:none;
  box-shadow:none;
  transition:background .18s,transform .16s cubic-bezier(.34,1.56,.64,1),
             box-shadow .2s;
  min-width:0;position:relative;
}

.car-card:not(:disabled):hover{
  background:linear-gradient(#17495a,#103543);

  transform:translateY(-3px);
  box-shadow:inset 0 0 0 1px #ffffff26,0 8px 18px #00000047;
}
.car-card.active{
  background:linear-gradient(#1b4b4e,#10323c);
  box-shadow:inset 0 0 0 1.5px var(--gold);
}

.car-card.active:not(:disabled):hover{
  background:linear-gradient(#1b4b4e,#10323c);
  box-shadow:inset 0 0 0 1.5px var(--gold),0 8px 18px #00000047;
}
.car-card canvas.car-art{
  display:block;width:100%;height:clamp(36px,7vh,64px);
  object-fit:contain;margin-bottom:4px;pointer-events:none;
  transition:transform .2s;
}

@keyframes car-idle{0%,100%{transform:translateY(0)}50%{transform:translateY(-3px)}}
.car-card.active canvas.car-art{animation:car-idle 3.4s ease-in-out infinite}
.car-card b{
  display:block;font-size:clamp(7.5px,.52vw,8.5px);letter-spacing:.9px;

  line-height:1.35;
  font-weight:800;color:#c3ddda;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  transition:color .18s;
}
.car-card.active b{color:#fff8e6}

.drive-controls{margin-top:clamp(3px,.5vh,7px)}

.bet-row,.auto-target{
  display:grid;grid-template-columns:auto minmax(0,1fr) auto;
  gap:clamp(4px,.4vw,7px);align-items:center;
  background:#0a2732c4;box-shadow:inset 0 0 0 1px #ffffff17;
  border-radius:11px;padding:clamp(5px,.5vw,7px);
}

.bet-row>button::before,.auto-target>button::before{
  content:'';position:absolute;inset:0;
  background:linear-gradient(currentColor,currentColor) center/11px 2px no-repeat;
}
#betUp::before,#autoUp::before{
  background:
    linear-gradient(currentColor,currentColor) center/11px 2px no-repeat,
    linear-gradient(currentColor,currentColor) center/2px 11px no-repeat;
}
.bet-row>button,.auto-target>button{
  width:clamp(30px,2.5vw,36px);height:clamp(30px,2.5vw,36px);border-radius:50%;
  background:#164150;color:#dff3ef;
  font-family:var(--title);font-size:clamp(18px,1.4vw,22px);line-height:1;
  display:flex;align-items:center;justify-content:center;
  box-shadow:inset 0 0 0 1px #ffffff1c;
  position:relative;overflow:hidden;
}
.bet-row>button:not(:disabled):hover,.auto-target>button:not(:disabled):hover{background:#1d5566}

.bet-row>button::after,.auto-target>button::after{
  content:'';position:absolute;inset:0;border-radius:50%;
  background:radial-gradient(circle,#ffe6a880,#ffe6a800 62%);
  opacity:0;transform:scale(.25);
}
.bet-row>button:not(:disabled):active::after,.auto-target>button:not(:disabled):active::after{animation:ripple .42s ease-out}
@keyframes ripple{from{opacity:.9;transform:scale(.25)}to{opacity:0;transform:scale(1.5)}}

.bet-value{
  display:flex;align-items:baseline;justify-content:center;
  gap:clamp(2px,.2vw,4px);line-height:1;min-width:0;
  padding:clamp(2px,.25vh,4px) 0 clamp(3px,.35vh,5px);
}
.bet-value i.unit{
  font-style:normal;font-family:var(--title);font-weight:800;flex:none;

  font-size:.56em;color:var(--gold);
  transform:translateY(-.1em);
  transition:transform .3s cubic-bezier(.34,1.56,.64,1),color .16s;
  text-shadow:0 0 12px #f3c25738;
}
.bet-value b{
  font-family:var(--title);font-size:clamp(27px,2.15vw,34px);

  font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1;
  letter-spacing:-.4px;color:#fffaf0;

  text-shadow:0 1px 0 #00000038,0 0 18px #ffe6a81f;
}

.bet-value{font-size:clamp(27px,2.15vw,34px)}

.roll-col{
  display:inline-block;overflow:hidden;height:1em;vertical-align:top;line-height:1;
  width:.5145em;letter-spacing:0;text-align:center;
}

.roll-col.thin{width:.2203em}

.roll-col.blank{width:0}
.roll-strip{
  display:block;font-style:normal;
  transition:transform .34s cubic-bezier(.32,.9,.3,1);
}
.bet-value .roll-strip b{display:block;font-weight:inherit;line-height:1;font-size:inherit}

@keyframes bet-pop{from{transform:scale(1)}38%{transform:scale(1.22)}to{transform:scale(1)}}
.bet-value b{display:inline-block;transition:color .16s}
.bet-value b.bumped{animation:bet-pop .25s cubic-bezier(.34,1.56,.64,1)}

.bet-value:has(b.bumped) i.unit{transform:translateY(-.22em) scale(1.1)}

.bet-row,.auto-target{transition:border-color .18s,background .18s}
.bet-row:has(>button:active),.auto-target:has(>button:active){border-color:#f3c25766}
.bet-row>button:not(:disabled):active,.auto-target>button:not(:disabled):active{transform:scale(.88);background:var(--gold);color:#2e2205}
.bet-row>button,.auto-target>button{transition:background .14s,transform .1s,color .14s}

@keyframes card-pick{from{transform:scale(.9)}to{transform:scale(1)}}
.car-card:not(:disabled):active{transform:scale(.95)}
.car-card.active{animation:card-pick .24s cubic-bezier(.34,1.56,.64,1)}

.credits b{transition:color .3s}
.credits.up b{color:var(--teal-lit)}
.credits.down b{color:var(--coral)}

.play-button,.cash-button{
  width:100%;min-height:clamp(54px,6.2vh,56px);border-radius:11px;

  display:flex;align-items:center;justify-content:center;
  gap:clamp(10px,1vw,16px);
  padding:0 clamp(11px,1vw,15px);

  font-family:var(--title);font-size:clamp(18px,1.4vw,23px);letter-spacing:.6px;
  position:relative;overflow:hidden;
  transition:filter .16s,transform .12s,box-shadow .2s;
}

.play-button{
  background:linear-gradient(var(--go-lit),var(--go) 38%,#2b7a1c);color:var(--go-ink);
  box-shadow:0 6px 18px #3fa62b3d,inset 0 1px 0 #ffffff5c;
}

@keyframes drive-glow{0%,100%{opacity:.34;transform:scaleX(.88)}50%{opacity:.7;transform:scaleX(1)}}
.drive-controls{position:relative}
.drive-controls::before{
  content:'';position:absolute;inset:6px 8px 2px;border-radius:14px;z-index:-1;
  background:radial-gradient(ellipse at 50% 60%,#3fa62b5c,#3fa62b00 70%);
  animation:drive-glow 3.8s ease-in-out infinite;pointer-events:none;
}

body[data-phase=playing] .drive-controls::before{background:radial-gradient(ellipse at 50% 60%,#d2822a5c,#d2822a00 70%)}


@keyframes drive-sheen{
  0%{transform:translateX(-140%) skewX(-18deg)}
  60%,100%{transform:translateX(320%) skewX(-18deg)}
}
.play-button:not(:disabled)::after{
  content:'';position:absolute;top:0;bottom:0;width:32%;
  background:linear-gradient(90deg,#fff0 0%,#ffffff6b 50%,#fff0 100%);
  animation:drive-sheen 3.4s ease-in-out infinite;
  pointer-events:none;
}

@keyframes launch-fill{from{transform:scaleX(0)}to{transform:scaleX(1)}}
.play-button::before{
  content:'';position:absolute;inset:0;transform-origin:left;transform:scaleX(0);
  background:linear-gradient(90deg,#dfffd699,#ffffffb8);
  pointer-events:none;
}

body[data-phase=launching] .play-button::before{animation:launch-fill var(--launch-seconds,2.4s) linear both}

body[data-phase=preparing] .play-button:disabled,
body[data-phase=launching] .play-button:disabled{opacity:1}

.cash-button{
  background:linear-gradient(var(--take-lit),var(--take) 40%,#a8631c);color:var(--take-ink);
  box-shadow:0 6px 18px #d2822a3d,inset 0 1px 0 #ffffff52;
}

@keyframes cash-beat{
  0%,100%{transform:scale(1)}
  46%{transform:scale(calc(1 + var(--heat,0)*.022 + .006))}
}
.cash-button:not(:disabled){

  animation:cash-beat 1.5s ease-in-out infinite;
}

.cash-button:not(:disabled)::before{
  content:'';position:absolute;inset:0;border-radius:11px;
  box-shadow:inset 0 0 0 2px var(--heat-colour,#eda049);
  opacity:calc(.25 + var(--heat,0)*.6);pointer-events:none;
}

:root{--heat-colour:var(--take-lit)}
.stage:has(.lane-tag.hot.active){--heat-colour:#ff5c78}
.stage:has(.lane-tag.safe.active){--heat-colour:#38ed70}

/* The amount on the button is FULL strength. It was .84, which reads as a
   greyed-out secondary detail sitting next to a solid label -- and on the
   cash-out button that detail is the money, which is the one number a player
   is actually deciding on. Dimming it was the button telling him the stake
   matters less than the word CASH OUT. */
.play-button b,.cash-button b{
  font-size:.82em;font-variant-numeric:tabular-nums;letter-spacing:0;
}
.play-button:not(:disabled):hover,.cash-button:not(:disabled):hover{filter:brightness(1.07)}

.play-button:not(:disabled):active,.cash-button:not(:disabled):active{
  transform:scale(.982) translateY(1px);filter:brightness(.97);
}

/* THE OPTIONS MENU, moved from the foot of the deck to its top-left corner and
   turned into a hamburger.

   It used to be a full-width `⋯` strip pinned below the drive button, with its
   own top border and padding, and the links pushed the deck TALLER when it
   opened. That cost height twice over: the strip itself, plus the rule and the
   gap that separated it from the button above. Both are gone -- the control now
   rides in the `BET AMOUNT` header row, which was already there and had empty
   space on its left, so it occupies no vertical space of its own at all.

   The panel below floats rather than expanding in place, which is the other
   half of the saving: opening the menu cannot change the deck's height or shove
   the road around beneath it. */
/* Pinned to the TOP-LEFT OF THE BOARD, opposite the deck and directly above the
   credits badge, which uses the same insets so the two read as one column.
   It lives in `.road` rather than in the deck for that reason: the deck is the
   panel on the right, and this belongs to the screen. */
.deck-extras{
  position:absolute;z-index:5;
  top:clamp(10px,1.6vh,18px);left:clamp(10px,1.4vw,18px);
}
.deck-extras>summary{

  list-style:none;cursor:pointer;

  width:clamp(32px,2.6vw,38px);height:clamp(32px,2.6vw,38px);
  display:flex;align-items:center;justify-content:center;

  border-radius:10px;
  /* The credits badge's surface, so the pair matches down this edge. The
     signal-palette block near the foot of this file restates both in the
     greens this build actually uses; these are the fallback. */
  background:var(--menu-surface);box-shadow:inset 0 0 0 1px var(--menu-line);
  transition:background .16s,box-shadow .16s;
}
/* Three bars, drawn rather than typed. A glyph would ride on the font's
   baseline and sit a pixel or two off centre in a box this small. v5 draws
   them as three elements rather than one block and two shadows, at the same
   places (5px apart, the middle one where the single block was), so that
   hud-fx.css can turn them into an x when the menu opens. */
.burger{
  /* HAIRLINES. 1.6px read as three stubby dashes at this size; 1px is the same
     weight as the deck's own borders and the lane rules on the road, which is
     what makes the button look like part of the interface rather than an icon
     dropped on top of it. The gap grows as the bars thin, so the three stay
     legible as three. */
  display:block;position:relative;width:15px;height:11px;
  color:var(--menu-ink);
  transition:color .16s;
}
.burger>i{position:absolute;left:0;width:100%;height:1px;border-radius:1px;background:currentColor}
.burger>i:nth-child(1){top:0}
.burger>i:nth-child(2){top:5px}
.burger>i:nth-child(3){top:10px}
.deck-extras[open] .burger,.deck-extras>summary:hover .burger{color:var(--menu-hot)}
.deck-extras>summary::-webkit-details-marker{display:none}
.deck-extras>summary:hover,.deck-extras[open]>summary{
  background:var(--menu-surface);
  background:color-mix(in srgb,var(--menu-hot) 12%,var(--menu-surface));
  box-shadow:inset 0 0 0 1px var(--menu-hot);
  box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--menu-hot) 45%,var(--menu-line));
}
.deck-extras>summary:focus-visible{outline:2px solid var(--menu-hot);outline-offset:3px}
/* The panel FLOATS, so opening the menu never changes the deck's height and
   never pushes the road around underneath it. It is anchored to the hamburger
   rather than to the deck so it opens directly beneath the thing that was
   pressed, and `min-width` lets it be wider than its 26px button without
   stretching the header row it lives in. */
.deck-links{
  position:absolute;top:calc(100% + 6px);left:0;z-index:6;
  /* ONE COLUMN OF LINES. It was a two-column grid of padded chips, which made
     a 212px slab of six buttons -- a second control panel parked on the road,
     competing with the deck it was meant to be subordinate to. A menu is a
     list, so it is a list: one item per row, separated by hairlines rather
     than by gaps, with no chip around any of them. */
  display:flex;flex-direction:column;
  min-width:150px;padding:3px 0;
  background:var(--menu-surface);
  border:1px solid var(--menu-line);border-radius:9px;
  box-shadow:0 12px 28px #000000a6;
}
/* A row, not a button. No chip, no border, no radius: the hairline above it is
   the only separator, and the whole row highlights on hover so the target is
   the full width rather than a small pill inside it. Left-aligned, because a
   list of six centred labels has no edge for the eye to run down. */
.deck-links button,.deck-links a{
  display:block;width:100%;text-align:left;
  padding:6px 11px;border-radius:0;background:none;box-shadow:none;
  font-size:9px;letter-spacing:.9px;font-weight:800;
  color:var(--menu-ink);white-space:nowrap;
  transition:background .14s,color .14s;
}
/* The hairline goes ABOVE each row but the first, so the list has five rules
   rather than six and never a stray line against the panel's own edge. */
.deck-links>*+*{border-top:1px solid var(--menu-line)}
.deck-links>*+*{border-top-color:color-mix(in srgb,var(--menu-line) 55%,#0000)}
.deck-links button:not(:disabled):hover,.deck-links a:hover{
  background:var(--menu-surface);
  background:color-mix(in srgb,var(--menu-hot) 12%,transparent);
  color:var(--menu-hot);box-shadow:none;
}

body[data-phase=playing] .garage,body[data-phase=crashing] .garage,
body[data-phase=launching] .garage,
body[data-phase=playing] .bet-row,body[data-phase=crashing] .bet-row,
body[data-phase=launching] .bet-row{
  opacity:.52;transform:scale(.985);transform-origin:top center;
  filter:saturate(.7);
}
.garage,.bet-row{
  transition:opacity .34s ease,transform .34s ease,filter .34s ease;
}

.deck button:disabled{opacity:1}
.deck .garage button:disabled,
.deck .bet-row>button:disabled,.deck .auto-target>button:disabled{
  opacity:.72;
}

body[data-phase=playing] .car-card.active,body[data-phase=launching] .car-card.active,
body[data-phase=crashing] .car-card.active{opacity:1}

@keyframes deck-win{
  0%{box-shadow:0 18px 48px #0000006b,inset 0 1px 0 #ffe6a82e,inset 0 0 0 0 #f7e68100}
  30%{box-shadow:0 18px 48px #0000006b,inset 0 1px 0 #ffe6a82e,inset 0 0 52px 0 #f7e68166}
  100%{box-shadow:0 18px 48px #0000006b,inset 0 1px 0 #ffe6a82e,inset 0 0 0 0 #f7e68100}
}

body[data-phase=won] .deck{animation:deck-in .5s cubic-bezier(.22,.9,.3,1) both,deck-win 1.1s ease-out}

@keyframes deck-shake{
  0%,100%{transform:translateX(0)}
  20%{transform:translateX(-1px)}48%{transform:translateX(1px)}
  76%{transform:translateX(-.5px)}
}
body[data-phase=crashing] .deck{animation:deck-in .5s cubic-bezier(.22,.9,.3,1) both,deck-shake .18s ease-out}

dialog{
  border:0;border-radius:7px;padding:clamp(22px,3vw,36px);
  width:min(520px,92vw);max-height:88dvh;overflow:auto;

  position:fixed;inset:0;margin:auto;
  background:var(--sea);color:var(--text);
}
dialog::backdrop{background:#04191ccc}
dialog .eyebrow{display:block;font-size:8px;letter-spacing:2.6px;font-weight:800;color:var(--teal-lit)}
dialog h2{font-family:var(--title);font-size:clamp(28px,3.4vw,40px);line-height:.98;margin:9px 0 15px;font-weight:900}
dialog ol{margin:0 0 15px;padding-left:17px;display:grid;gap:9px;font-size:12px;line-height:1.55;color:#d3ece7}
dialog ol b{color:var(--sand)}
dialog p{font-size:12px;line-height:1.6;color:#d3ece7;margin-bottom:11px}
dialog label{display:block;font-size:7px;letter-spacing:1.8px;font-weight:800;color:var(--dim);margin:13px 0 5px}
dialog input,dialog code{
  display:block;width:100%;padding:9px 11px;border:0;border-radius:4px;
  background:#06282c;color:var(--text);font-family:ui-monospace,monospace;font-size:11px;
  overflow-wrap:anywhere;
}
dialog .play-button{margin-top:17px;justify-content:center;gap:9px}
/* THE HIT RECT WAS THE GLYPH. Measured at every viewport in the sweep, this
   button reports 12.3 x 21 px -- the advance width and line box of a single
   multiplication sign -- against a 44x44 floor. It is 7% of the area a finger
   is entitled to, and it is the only way out of HOW TO PLAY and FAIR PLAY on
   a touch screen, where there is no Esc key.

   A 44x44 flex box with the glyph centred, pinned at top:0 right:0 so the box
   grows into the dialog's own corner padding rather than pushing anything.
   The glyph itself moves 2.85px right and 0.50px down: its centre was at
   (19.15, 21.50) from the corner and is now at (22, 22). That is inside the
   width of the stroke it is drawn with, and it is the whole cost of the
   change -- the dialog's heading, eyebrow and body are laid out against the
   card's padding and never against this button. */
.dialog-close{position:absolute;z-index:2;top:0;right:0;width:44px;height:44px;display:flex;align-items:center;justify-content:center;font-size:21px;line-height:1;color:var(--dim)}
.fine-print{font-size:9px!important;line-height:1.6;color:#8fb8b3!important}
#verifyResult{font-size:11px;color:var(--teal-lit);margin-top:9px}

#toast{
  position:fixed;left:50%;bottom:22px;transform:translate(-50%,14px);
  background:#04191c;color:var(--text);padding:11px 19px;border-radius:100px;
  font-size:11px;font-weight:700;opacity:0;pointer-events:none;transition:opacity .2s,transform .2s;z-index:60;
}
#toast.show{opacity:1;transform:translate(-50%,0)}

/* THE TOUCH LAYOUT, and it is a POINTER question rather than a width one.

   This block was keyed on `max-width:860px` alone, which is the right test for
   a phone and the wrong one for everything else that is touched. An iPad in
   portrait is 768px wide and took it; the same iPad turned landscape is 1024px
   and fell straight through to the base rules, which park the deck as a
   floating panel against the top-right corner. So the controls jumped from the
   foot of the screen to the side of it on a rotation, on the same device, with
   the same thumbs -- and a panel pinned to a corner is reachable with a mouse
   and is not reachable with a hand holding the other edge of the slab. The
   owner's instruction is the whole of the rule: "on iPad how it was before,
   like it's on phone, never on side, on any width".

   `(pointer:coarse)` is the complement of the laptop dock's own
   `(hover:hover) and (pointer:fine)` further down, so the two can never both
   match and no width has to be named to keep them apart. Every touch device
   now takes the foot of the screen whatever its width or orientation, and the
   floating side deck is left to mouse-driven machines too narrow for the dock.

   The `(max-width:860px)` arm stays beside it and is not redundant: a narrow
   window on a desktop reports a fine pointer and still needs this layout. */
@media(max-width:860px),(pointer:coarse){
  /* THE SHEET FLOATS, exactly as the laptop's bar does, and that is the whole
     of this change. The owner's question is the brief: "isnt ipad and phone
     control same design trasparent design as laptop?" He is right that they
     were two designs. The laptop deck is a glass panel over the night sky; the
     phone and the iPad had an opaque green-black slab bolted to the bottom.

     THE SLAB WAS STRUCTURAL, NOT COSMETIC, which is why the fix starts here
     rather than in a colour. This block used to make `.stage` a two-row grid
     and `.road` a relative grid item, so the CANVAS stopped at the deck's top
     edge: measured, 602px of canvas on an 844px phone and 747px on a 1024px
     iPad. Behind the deck there was no sky at all, only the page's own
     #030504, so painting the deck translucent would have shown flat black
     rather than stars. Those three declarations are deleted rather than tuned
     -- `.stage{display:grid;grid-template-rows:minmax(0,1fr) auto}`,
     `.road{position:relative;inset:auto}` and `position:static;width:auto`
     here -- so `.stage` falls back to the base `height:100dvh;position:relative`
     and `.road` to the base `position:absolute;inset:0`. The canvas is now the
     full viewport at every touch shape, 844px and 1024px at those two, and
     there is a photographed sky under the panel for the glass to be glass
     about.

     `--dock:sheet` IS READ BY resize() IN app.js, and it is a second value
     rather than the bar's own because the two docks differ in width. Both take
     the foot of the board, so both publish `--dock-inset` and both stop the
     road short of the panel. But a bar is narrower than the screen and sizes
     the road at `min(w*.55, h*1.25)`, while a sheet spans it and must keep
     this layout's `w*.93`. Measured with `--dock:bar` forced onto the sheet:
     the road collapsed 362.70px -> 214.50px on a 390px phone and 714.24px ->
     422.40px on a 768px iPad. That is the trap, and the token is what avoids
     it -- `roadW` and `--road-centre` are byte-identical to the old layout at
     all thirteen touch shapes measured.

     THE BOTTOM GUTTER IS PAID FOR OUT OF THE PADDING, not out of the road, and
     that is the one number in this block worth arguing about. Every pixel of
     gutter is a pixel of `--dock-inset` and therefore a pixel off the road,
     which on this project is not a trade that gets made by default. 8px is
     what makes the panel read as floating rather than as a bottom sheet, and
     `env(safe-area-inset-bottom)` takes over above it so an iPhone's 34px of
     home indicator is the gutter instead of being paid for twice -- once in
     the gutter and again in `padding-bottom:max(10px,env(...))`, which is what
     the old declaration on this line did. The density tokens below then hand
     the 8px back: see the budget beside each set. Measured end to end, road
     height old -> new: 602 -> 601.78 at 390x844, 689 -> 689.34 at 430x932,
     498 -> 498.31 at 360x740, 426 -> 425.67 at 375x667, 654 -> 653.53 at
     414x896, 357 -> 357 at 320x568. Par to within half a pixel, and not one
     phone loses a whole one. The tablets GAIN 13px -- 747 -> 759.89 at
     768x1024, 492 -> 505.08 at 1024x768, 745 -> 758.44 at 1366x1024 --
     because their deck was never paying this block's padding at all (see the
     tokens below).

     THE OLD FIGURES ARE WHOLE NUMBERS AND THE NEW ONES ARE NOT, which is a
     fact about the measurement rather than about the layout, and it is the one
     trap in reading this list. The road's height is `h` in resize(), and in
     the old build `.road` was a grid item, so `h` came from
     `board.clientHeight` -- which is rounded to an integer. Today `.road` is
     `inset:0` on the whole viewport and `h` is `H - inset + 1` against a
     fractional panel, so it keeps its decimals. Measuring the OLD `.road`
     with `getBoundingClientRect` instead gives 601.78, 689.34, 498.31,
     425.67, 653.53, 746.89, 492.08 and 745.44 -- which look like an exact
     match for the new numbers and are not one, because the renderer never saw
     them. Compare the integers above; they are what the old road was actually
     drawn to.

     `width:min(1216px,calc(100% - var(--sheet-side)))` with `--sheet-side:28px`
     is the laptop bar's own `min(1216px,calc(100% - 28px))`, with the 28 lifted
     into a token because one width cannot afford it -- see
     `@media(max-width:340px)`. 14px of sky down each side is the other half of
     "floating", and unlike the gutter it costs the road nothing: the sheet
     branch of `roadW` is `min(w*.93, w*.96)` and never reads the deck, so the
     road's width and centre are unchanged at every shape. At 1366px the
     1216px cap takes over and the tablet sheet is literally the laptop bar's
     width.

     THE DENSITY IS TOKENS RATHER THAN DECLARATIONS, and that is not a style
     preference. The skin that consumes them has to sit after the Signal
     palette section -- which restyles `.deck` at the same specificity and
     would otherwise win -- and that puts the consuming rule after the two
     narrow blocks that tune this density. A custom property does not care: it
     resolves by the cascade on `.deck` itself, so a later-matching
     `@media(max-width:700px)` still wins even though the rule that reads it is
     hundreds of lines further down.

     This is also what finally kills a piece of dead code that had been here
     the whole time. `padding:9px 11px max(10px,env(safe-area-inset-bottom));
     gap:6px` used to be these two lines and has NEVER applied anywhere,
     because the Signal palette's `.deck{padding:18px;gap:10px}` is later at
     equal specificity. Measured on the build before this change, an iPad deck
     reported `padding:18px` and `gap:10px` and a safe-area inset of zero -- it
     has never paid for its home indicator, and with the gutter it now does.

     11px/20px and 8px: the first two are the laptop bar's own `padding-block`
     and `padding-inline`, taken literally, because "same design as laptop" is
     the request and this is the part of it that is a number. 8px stands in for
     a bar whose `row-gap:5px` and `column-gap:var(--bar-gap)` have no single
     equivalent in a column. Block and inline are separate tokens rather than
     one `padding` shorthand because they are tuned against different things:
     the block pair is the road's height budget, the inline pair is the drive
     button's one-line width, and the narrowest phone needs to move one without
     touching the other. The budget at 768x1024, where this set applies:
     18+18 of padding and three 10px gaps becomes 11+11 and three 8px gaps, so
     the deck goes 277.11px -> 269.11px, and 20px - 8px of gutter + 1px of tuck
     is the 13px the road gains.

     `max-height` is now a FOOTPRINT budget, hence `- var(--sheet-gutter)`. The
     cap's job has always been "the panel may not eat more than this share of
     the screen"; bottom-anchored, what the panel costs the road is its height
     PLUS its gutter, so the gutter has to come out of the cap or the cap means
     8px more than it says. It binds at exactly one measured shape -- 1100x500,
     an iPad in Split View -- where the deck goes 235px -> 227px and the road
     265px -> 266px instead of 265px -> 258px. */
  .deck{
    --dock:sheet;
    --sheet-gutter:max(8px,env(safe-area-inset-bottom));--sheet-side:28px;
    --sheet-pad-block:11px;--sheet-pad-inline:20px;--sheet-gap:8px;
    position:absolute;z-index:4;
    left:50%;translate:-50% 0;right:auto;top:auto;
    bottom:var(--sheet-gutter);
    width:min(1216px,calc(100% - var(--sheet-side)));
    max-height:calc(47dvh - var(--sheet-gutter));

    animation:none;
  }
  .deck>*{animation-delay:calc(.1s + var(--i,0)*.03s)}

  .lane-tag{padding:7px 3px 6px}
  .lane-tag em{font-size:16px;margin:0 0 1px}
  .lane-tag small{font-size:8px;letter-spacing:.5px}
  .lane-tag b{font-size:12px;margin-top:2px}

  .lane-tag .mark{display:none}
  /* THE TOAST HANGS OFF THE SHEET, not off the bottom of the screen, because
     the road no longer ends where the panel starts. (So did the credits badge
     until v5 moved it to the top-right corner, where nothing docks; what is
     left of its rule here is its size.) Both were positioned against a box
     that is now the full viewport, so the flat `clamp(34px,5.5vh,50px)` this
     replaces would have put the credits badge BEHIND the panel. Not by its
     34px floor, which is the easy thing to assume and is wrong: 5.5vh of an
     844px phone is 46.42px, between floor and ceiling, and 46.42px is what
     the old rule resolves to there. The floor only takes over at 618px of
     viewport height or less, the ceiling at 910px or more. Restoring that rule on the new layout at 390x844, against
     the live sheet -- top 600.78, bottom 836.00, height 235.22 -- puts the
     badge's foot at y=797.59, which is 196.81px down inside the sheet. Even
     the floor read of it, a literal `bottom:34px`, only moves the foot to
     y=810.00, 209.22px in. Both readings bury the badge, which is why the
     line exists; the arithmetic is written out because it is the argument for
     the line, not decoration around it.

     `--dock-inset` is published by resize() as the panel's whole footprint,
     gutter included, and the 12px above it is the laptop dock's own
     clearance, restated here rather than shared because the two blocks cannot
     both match. Measured: the badge's bottom edge sits exactly 12.00px above
     the sheet's top edge at 390x844 and at 768x1024.

     The toast keeps its own 22px, which is the number it has everywhere else
     in this file; the dock query further down sets 14px for the bar and still
     wins there. Before this line the toast painted straight over the deck on a
     phone, which was invisible only because the deck was opaque. */
  /* The 44px of the options button beside it: 6 + 7px label + 4 + 19px
     number + 8. */
  .credits{padding:6px 11px 8px;border-radius:9px}
  #toast{bottom:calc(var(--dock-inset,0px) + 22px)}
  .credits b{font-size:19px}
  .readout{top:clamp(78px,12vh,104px)}

  /* The phone plate is PERCENTAGE-bound, not cap-bound: at 390px the asphalt
     under the card's line is about 290px, so a flat 222px card was covering
     three quarters of it and a flat 268px winning card 93%. Both grow, but
     the ceilings stay inside the road -- 72% of a 390px phone is 281px, which
     is the width at which the winning plate just touches the asphalt's edges
     without overhanging onto the shoulder. The 360px/420px terms do nothing
     on a phone and everything on a 768px tablet, whose road is far wider:
     there they cap the card instead of the percentage, which is why one pair
     of numbers covers both shapes. */
  .outcome{
    /* HALF THE INSET UP, and without this line the result card lands on the
       car. `top` resolves against `.road`, and `.road` used to BE the drawn
       road -- 601.78px at 390x844, so 50% put the card's centre at 300.9. Now
       `.road` is the full 844px viewport while the road drawn inside it is
       still 601.78px tall, so a bare 50% would put the card at 422px against a
       hero the renderer parks at `geometry.h*.70` = 421.25px. Subtracting half
       the footprint recentres the card on the road rather than on the screen:
       measured, `calc(50% - 121.609px)` = 300.4px at 390x844, within half a
       pixel of the 300.9px where it has always been. At 768x1024 it computes
       to 379.4px against today's 373.4px, which is the road's own centre
       moving down by half the 13px the road gained there.
       The dock query must never take this rule -- the bar's card is signed off
       at a plain 50% -- which is why it lives inside this query and not in the
       base rule. */
    top:calc(50% + var(--road-top,0px)/2 - var(--dock-inset,0px)/2);
    left:var(--road-centre);right:auto;translate:-50% -50%;
    min-width:0;width:min(64%,360px);max-width:none;
    /* The inline padding has to be restated here, which it never had to be
       before. The base rule's is clamp(25px,2.4vw,36px), and 2.4vw of a phone
       is single digits, so on every phone it resolves to its 25px FLOOR: 50px
       of padding inside a card that is only 205px wide at 320px. Measured
       there with the base padding in place, the content box is 158px and END
       OF THE ROAD wraps onto two lines; at 17px of padding the box is 174px
       and it holds one. The floor is the right number for a desktop plate and
       far too generous for this one -- 4.4vw keeps the same proportion of the
       card that 2.4vw keeps of a laptop's. */
    padding:clamp(12px,1.6vh,16px) clamp(17px,4.4vw,24px) clamp(13px,1.7vh,17px);
  }
  .outcome strong{font-size:clamp(34px,8.6vw,46px)}
  /* The eyebrow SHRINKS here where everything else grows, and the two
     decorative rules either side of it shrink with it. At 13px of rule plus
     9px of margin each, those rules cost 62px of a line that is only 240px
     long on a phone -- enough that even the short eyebrow, THAT'S A GOOD
     RIDE, was wrapping onto two lines once the type went up. 9px of rule on
     6px margins gives the words back 20px, and 9-12px of type on 2.4px of
     tracking fits the long eyebrow on one line at 360px and at 390px. */
  .outcome small{margin-bottom:7px}
  .outcome small::before,.outcome small::after{width:9px;margin:0 6px}
  /* Restated for the same specificity reason as the narrower block below: this
     one sizes by `width`, so the winning card needs its own width here or the
     desktop min-width/max-width pair would take over. `--plate-r` is in the
     same position: the base rule now puts 20px on `.outcome.won`, which
     outranks any plain `.outcome` radius whatever the media query, so without
     the restatement the desktop's bigger corner would leak onto every phone. */
  .outcome.won{
    min-width:0;width:min(72%,420px);max-width:none;
    padding:clamp(13px,1.8vh,18px) clamp(20px,5vw,28px) clamp(14px,1.9vh,19px);
    --plate-r:16px;
  }
  /* The 36px floor is set by the narrowest phone, not by taste. It only
     applies below 333px, where 10.8vw stops being the larger term, and 320px
     is the one width where the floor decides anything: the plate is 230px
     there, which leaves 190px of line, and a five-figure payout measures
     5.1px of ink per 1px of type. 40px wanted 204px and broke +$12,345.67
     across two lines on a screen where it fits on one today; 36px needs 184px
     and does not. Every phone from 360 up is on the 10.8vw leg and is
     unaffected either way. */
  .outcome.won strong{font-size:clamp(36px,10.8vw,56px)}
  .outcome.won small{font-size:clamp(9px,2.6vw,12px);letter-spacing:2.4px}
  .outcome.won span{font-size:clamp(20px,5vw,26px)}

  .garage{grid-template-columns:repeat(6,1fr);gap:3px;border-radius:9px;padding:4px}
  .car-card{padding:3px 1px 2px;border-radius:7px}
  .car-card canvas.car-art{height:clamp(32px,6.2dvh,50px);margin-bottom:3px}

  /* The narrow layout drops the section labels, but the header row also holds
     the options hamburger, which has to survive the collapse -- it is the only
     way into the rules, sound and reset. So the row itself stays as a bare
     container for that button and only its LABEL goes. */
  .deck-sec:not(.deck-head){display:none}
  .deck-head{margin:0;min-height:0}
  .deck-head .sec-label{display:none}

  .bet-row,.auto-target{border-radius:9px;padding:4px}
  .bet-row>button,.auto-target>button{width:32px;height:32px;font-size:19px}
  .bet-value{font-size:23px;padding:1px 0 2px}
  .bet-value b{font-size:23px}

  .play-button,.cash-button{

    /* 24px flat, and it was over its own limit at the bottom of the range.
       On a 320px-wide phone GETTING READY… + $1,000.00 holds one line at 23px
       and wraps at 24px, and `overflow:hidden` does not actually clip that
       wrap -- the flex items wrap, `min-height` is only a floor, so the
       BUTTON grows instead. Measured at the old 24px: the button goes 46px ->
       58px and the deck 211px -> 223px, for the 2.4 seconds the launch label
       is up, and back again afterwards. That is a layout shift tied to a game
       phase, and the 12px it takes comes out of the road, which this project
       does not spend on panels.

       22px is a whole pixel below the last size that fits, and it ends that
       jump -- at 22px the deck reports one height through every phase.
       6.2vw then crosses 22px at 355px, so every phone from 360 up reads
       LARGER than it does today rather than smaller: 375 -> 23.3, 390 ->
       24.2, 414 -> 25.7, 430 -> 26.7. The 28px cap leaves 9px of air above
       and below the line box inside the 52px button at 540-700px wide and
       13px inside the 60px button at 768-860px; 30px would cut that to 7px
       against a 10px corner radius.

       `min-height:56px` used to sit on this line and is gone rather than
       retuned: the Signal palette section further down sets
       `.play-button,.cash-button{min-height:60px}` at the same specificity
       and later in the file, so this declaration has had no effect on
       anything for as long as that section has existed. The live heights are
       that 60px, and the 52px and 46px in the two <=700px blocks beside it. */
    font-size:clamp(22px,6.2vw,28px);border-radius:10px;
    /* The label and the amount stay TOGETHER in the middle, as they are on the
       wide layout. This block used to push them to opposite ends with
       `space-between` and `gap:0`, which on a full-width button left the word
       hard against the left padding and the money hard against the right --
       two separate things at arm's length rather than one phrase. The narrow
       layout is exactly where the button is widest relative to its text, so it
       is also where the split read worst. Keeping the base rule's centring and
       its gap means the pair reads the same at every width. */
  }

  .play-button b,.cash-button b{font-size:1em}

}

@media(max-width:860px) and (max-height:700px){
  /* The gutter comes out of every cap, for the reason written beside the
     sheet: bottom-anchored, what the panel costs the road is its height plus
     its gutter, so a cap that does not subtract the gutter promises 8px more
     road than it delivers. The fallback 0px keeps this honest on the two
     layouts that set no gutter at all -- the short-landscape side deck and the
     laptop bar, neither of which reaches this block. */
  .deck{max-height:calc(43dvh - var(--sheet-gutter,0px))}
  .readout>b{font-size:clamp(52px,14.3vw,76px)}
}

@media(max-width:860px) and (max-height:700px) and (orientation:portrait){
  /* Two columns on the short portrait screen: the target stepper, then AUTO
     PLAY beside it. */
  .auto-row{grid-template-columns:minmax(0,1fr) auto;align-items:center}
  .auto-target{grid-column:auto}
  .auto-row>#autoBtn{grid-column:auto}
  .wide-only{display:none}
  .car-card b{display:none}
  .car-card canvas.car-art{height:clamp(26px,5dvh,38px);margin-bottom:0}

  /* `gap:4px` became `--sheet-gap:4px` so it reads like the rest of the
     density, and it is inert either way: every shape this block can match is
     narrower than 700px (portrait, under 700px tall, so narrower still) and
     therefore also matches the two `(max-width:700px)` blocks further down,
     which are later and win. The cap takes the gutter for the usual reason. */
  .deck{--sheet-gap:4px;max-height:calc(max(45dvh,258px) - var(--sheet-gutter,0px))}
  .play-button,.cash-button{min-height:44px}

  .auto-toggle{padding:7px 8px}

  .play-button,.cash-button{min-height:50px}

  .deck{padding-block:7px max(8px,env(safe-area-inset-bottom))}
}

@media(max-width:860px) and (max-height:520px) and (orientation:portrait){
  /* The gutter out of the cap, as everywhere else. */
  .deck{max-height:calc(55dvh - var(--sheet-gutter,0px))}
  .car-card canvas.car-art{height:clamp(20px,4.4dvh,30px)}
  .play-button,.cash-button{min-height:40px;font-size:17px}
  .deck{gap:3px}
}

@media(min-width:600px) and (max-width:960px) and (orientation:landscape) and (max-height:540px),
      (max-width:599px) and (max-height:540px) and (min-aspect-ratio:3/2){
  .stage{display:block}
  .road{position:absolute;inset:auto;top:0;right:0;bottom:0;left:0}

  .deck{
    /* THESE FOUR RESETS ARE LOAD-BEARING, and they exist because this block is
       LATER in the file than the touch sheet above it and therefore inherits
       everything that block sets on `.deck`. Without them a short landscape
       phone carries `left:50%`, `translate:-50% 0`, `bottom:<gutter>` AND
       `--dock:sheet` into a panel that is supposed to be pinned to the
       top-right corner: measured with only the sheet's rules in place, the
       side deck went from [608.1, 8, 227.9x271] to [14, 111, 816x271] -- a
       full-width strip across the bottom of a 390px-tall screen -- with
       `--dock:sheet` on it, `--dock-inset` reading 279px of that 390px, and
       the road widened from 348.25px to 784.92px to match a bar that was not
       there.
       `--dock:none` is a spelled-out "not docked" rather than `initial`, so
       anyone grepping for the token finds every layout that has an opinion
       about it; resize() treats anything that is not bar or sheet as undocked.
       Verified after the reset: 844x390, 740x360 and 900x500 all report
       `--dock` none, `--dock-inset` 0px, and a deck, road, roadW, credits and
       result card byte-identical to the build before this change. */
    --dock:none;
    left:auto;translate:none;bottom:auto;
    position:absolute;top:8px;right:8px;
    width:clamp(184px,27vw,238px);max-height:calc(100dvh - 16px);
    background:linear-gradient(#0a2430fa,#04141cfd);
    border:1px solid #f3c25740;border-radius:12px;
    box-shadow:0 14px 40px #00000066,inset 0 1px 0 #ffe6a82e;
    padding:8px 9px;gap:4px;
  }
  .garage{grid-template-columns:repeat(3,1fr);gap:4px;border-radius:9px;padding:3px}
  .car-card{padding:5px 2px 4px;border-radius:7px}
  .car-card canvas.car-art{height:clamp(22px,9dvh,34px);margin-bottom:3px}
  .car-card b{font-size:7.5px;letter-spacing:.7px}

  /* The narrow layout drops the section labels, but the header row also holds
     the options hamburger, which has to survive the collapse -- it is the only
     way into the rules, sound and reset. So the row itself stays as a bare
     container for that button and only its LABEL goes. */
  .deck-sec:not(.deck-head){display:none}
  .deck-head{margin:0;min-height:0}
  .deck-head .sec-label{display:none}

  .bet-row,.auto-target{padding:3px;border-radius:9px}
  .bet-row>button,.auto-target>button{width:26px;height:26px;font-size:16px}
  .bet-value{font-size:21px;padding:0}
  .bet-value b{font-size:21px}
  .credits{padding:6px 11px 8px}

  .outcome{
    left:var(--road-centre);right:auto;translate:-50% -50%;
    top:50%;bottom:auto;
    min-width:clamp(206px,24vw,242px);width:auto;max-width:40%;
    padding:9px 18px 10px;--plate-r:12px;
  }
  /* The eyebrow is pinned to 9px here rather than taking the base rule's new
     10-13px. This block's card is capped at a third of a 900px-wide screen,
     which leaves about 190px of line once the two decorative rules are paid
     for, and MAX MULTIPLIER REACHED at 10px needs more than that. 9px on
     2.2px of tracking fits it with roughly 15px of margin, and a short
     landscape screen is the one shape where the eyebrow losing a pixel costs
     nothing -- there is no room above the card for a second line of it. */
  .outcome small{margin-bottom:4px;font-size:9px;letter-spacing:2.2px}
  .outcome small::before,.outcome small::after{width:12px;margin:0 7px}
  .outcome strong{font-size:clamp(34px,4.4vw,40px)}
  /* The winning card is bigger here too, but it is sized against THIS block's
     ceiling rather than the desktop one. Both of these have to be restated:
     `.outcome.won` outranks the plain `.outcome` rules above on specificity,
     so without them the desktop width and type would win on a phone and put a
     380px card on a 40%-wide board. */
  .outcome.won{
    /* `width` IS THE DEFECT, and it is not written in this block. The narrow
       block above puts `width:min(72%,420px)` on `.outcome.won`, which beats
       this block's plain `.outcome{...width:auto...}` on specificity whatever
       media query either of them sits in, so the card was pinned to its ceiling
       whatever it contained and the floating side deck was standing on the
       payout. Measured with that in place: at 680x400 the card's right edge sat
       at 503.6 against a deck left edge of 488, and at 736x414 at 531.6 against
       529.3 -- and `.deck` is later in the DOM at the same z-index, so what the
       deck painted over was the money. Restoring content sizing draws the same
       card 235px wide instead of 324px, clearing the deck by 11.7px at 680x400
       and 25.0px at 736x414.

       The third max-width term is then the ceiling for the payouts that really
       are that wide, because content sizing on its own would let a long one
       grow into the deck. The deck's left edge is
       `100vw - 8px - clamp(184px,27vw,238px)`, and a card centred on
       `--road-centre` needs road-centre + W/2 + 8px to stay inside it, which is
       the expression written out. `--road-centre` is published by resize() in
       px and is NOT always half the viewport: below 680px of width the road
       gives up the centre line rather than the deck's clearance, and the term
       follows it because it reads the property rather than assuming `50vw`. It
       resolves to 280px at 680x400 and 306.56px at 736x414, and is inert at
       900x500 (392px), at 960x540 (452px) and at 568x320, where 56% is 318.08px
       against its 320.4px. All three legs of the min() bind somewhere in this
       block's range -- 56% below about 579px of width, the calc from 680px to
       about 774px, and the flat 324px everywhere else -- and below about 437px
       the calc drops under this rule's own 226px min-width and stops binding,
       which is a landscape window narrower than any device reports. A flat
       lower cap instead of the calc was tried and does not work: at 900x500 a
       five-figure card needs 304px of content. */
    min-width:clamp(226px,27vw,268px);width:auto;
    max-width:min(56%,324px,calc(2*(100vw - 8px - clamp(184px,27vw,238px) - var(--road-centre)) - 16px));
    padding:12px 22px 13px;
    /* Both of these are REQUIRED, and for the same reason the widths above
       are: `.outcome.won` beats a plain `.outcome` on specificity whatever
       media query either sits in, so without the restatement the desktop
       rule's 20px corner would land on a card a third this size. */
    --plate-r:14px;
  }
  /* 48% -> min(56%,324px), and the min-width is what actually does the
     growing: 186-224px -> 226-268px, which is what the common case, a
     two-figure win, measures. The old max-width never bound anything -- the
     min-width was small enough that the card always sized itself to its text
     -- so the number to get right is the CEILING for the long strings, and
     48% was not it. At 900x500 the floating deck squeezes the road to 384px
     and the asphalt at the card's line to about 307px, and 48% of the
     viewport is a 432px ceiling over that: a width the card could only reach
     by hanging off both shoulders.

     324px is the ceiling, taken from that 307px of asphalt plus the shoulder
     the rotation already overhangs. The 56% below it is there for the other
     end of this block's range, and it is not decoration: a flat 36% -- which
     is 324px at 900 and the number the asphalt alone argues for -- resolves
     to 205px at 568x320, under this rule's own 226px min-width, and measured
     there it wrapped MAX MULTIPLIER REACHED onto two lines and made the plate
     NARROWER than it is today. 56% is 318px at 568, where the deck leaves the
     road about 360px, so the plate keeps the same share of its road that the
     desktop one has of its own.

     The figure caps at 50px, which those widths pay for. Measured across
     568x320, 640x360, 740x400, 900x500 and 960x540, every eyebrow and every
     payout up to five figures sits on one line; only +$1,000,000.00 wraps,
     and only on the two widest of those. 50px is a third larger than the 38px
     this card carries today. */
  .outcome.won strong{font-size:clamp(42px,5.6vw,50px)}
  /* Said again for `.won`, because `.outcome.won small` beats this block's
     `.outcome small` on specificity and would otherwise take the base rule's
     10px floor -- the one size that does not fit this card's line. */
  .outcome.won small{font-size:9px;letter-spacing:2.2px}
  .outcome span{margin-top:5px;font-size:clamp(15px,1.9vw,19px)}
  .credits b{font-size:19px}

  .play-button,.cash-button{
    font-size:clamp(15px,1.9vw,19px);min-height:clamp(42px,12vh,50px);border-radius:10px;
    justify-content:center;gap:clamp(8px,1.4vw,14px);
  }

  .readout{top:clamp(68px,18vh,84px)}
  .readout>b{font-size:clamp(46px,11.7vh,65px)}


  #rulesBtn{font-size:0}
  #rulesBtn::before{content:'RULES';font-size:7px;letter-spacing:.35px}
}

.auto-row{
  display:grid;grid-template-columns:1fr 1fr;
  gap:clamp(4px,.4vw,6px);
}
.auto-target{

  grid-column:1/-1;
}
/* AUTO PLAY is the only toggle in this row now that fast mode is gone, so it
   takes the full width rather than sitting in a half-row beside a hole. */
.auto-row>#autoBtn{grid-column:1/-1}

.auto-value{
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:1px;min-width:0;line-height:1;
}
.auto-value small{

  font-size:7px;letter-spacing:1.1px;font-weight:800;color:#6f9e9a;
}
.auto-value b{
  font-family:var(--title);font-weight:800;
  font-size:clamp(17px,1.3vw,21px);color:var(--text);
  font-variant-numeric:tabular-nums;
}

.auto-value b.off{color:var(--dim)}

.auto-toggle{
  padding:clamp(7px,.7vw,10px) 2px;border-radius:8px;
  background:#123a47a8;box-shadow:inset 0 0 0 1px #ffffff14;
  font-size:clamp(9px,.66vw,11px);font-weight:800;letter-spacing:.9px;color:#cfe8e4;
  transition:background .14s,color .14s,transform .16s cubic-bezier(.34,1.56,.64,1),box-shadow .18s;
}
.auto-toggle:not(:disabled):hover{background:#1d5566;transform:translateY(-2px)}
.auto-toggle:not(:disabled):active{transform:scale(.93)}

.auto-toggle.on{
  background:linear-gradient(#1ad0bf,#0e8d84);color:#03272a;
  box-shadow:0 0 0 1px #6ff0e2aa,0 0 16px #12b3a659;
}


@media(max-width:860px) and (orientation:portrait),(pointer:coarse) and (orientation:portrait){
  .auto-toggle{padding:9px 10px;letter-spacing:1.1px}
}

@media(max-width:860px),(pointer:coarse), (max-width:960px) and (orientation:landscape) and (max-height:540px){
  /* AUTO PLAY SURVIVES THE COLLAPSE. Once a round is under way the narrow deck
     folds down to the one button that still does anything, which is right for
     the bet amount and the garage -- a stake cannot be changed mid-ride and a
     car cannot be swapped -- but wrong for the auto row. That toggle is live
     for the whole round: AUTO PLAY is most often armed part-way through a ride
     so the next one starts by itself. Hiding it meant the one screen where the
     controls are scarcest was also the only one where you could not reach it,
     and the wide layout has never hidden it at all.

     `.auto-row` is excluded here rather than given a `display` of its own, so
     it keeps whatever the base layout gives it and there is no second copy of
     its geometry to maintain. The bet amount, the garage, the section labels
     and the options disclosure all still fold away. */
  body[data-phase=preparing] .deck>:not(.drive-controls):not(.auto-row),
  body[data-phase=launching] .deck>:not(.drive-controls):not(.auto-row),
  body[data-phase=playing] .deck>:not(.drive-controls):not(.auto-row),
  body[data-phase=crashing] .deck>:not(.drive-controls):not(.auto-row){display:none}

  body[data-phase=preparing] .drive-controls,
  body[data-phase=launching] .drive-controls,
  body[data-phase=playing] .drive-controls,
  body[data-phase=crashing] .drive-controls{margin-top:0}
}

@media(max-width:860px),(pointer:coarse), (max-width:960px) and (orientation:landscape) and (max-height:540px){
  body[data-phase=won] .deck{animation:deck-win 1.1s ease-out}
  body[data-phase=crashing] .deck{animation:deck-shake .18s ease-out}
}

@media(prefers-reduced-motion:reduce){
  *,*::before,*::after{animation:none!important;transition:none!important}
}

.deck-links a{text-decoration:none}


/* Signal palette: neutral black surfaces, green go, yellow bank, red stop. */
:root{
  --deep:#030504;--sea:#101410;--slate:#202720;
  --go:#38ed70;--go-lit:#76ff9e;--go-ink:#062510;
  --take:#ffe640;--take-lit:#fff18b;--take-ink:#302700;
  --stop:#ff4052;--stop-lit:#ff7985;--stop-ink:#260408;--crash-red:#ff4052;
  --gold:#ffe640;--teal:#38ed70;--teal-lit:#8dffaa;--sand:#fff18b;
  --coral:#ff4052;--amber:#ffe640;--mint:#38ed70;
  --text:#f3f7f0;--dim:#9ba89d;
  --title:Impact,'Arial Narrow',sans-serif;--body:Arial,Helvetica,sans-serif;
}
.road{background:#000}
button:focus-visible,a:focus-visible,summary:focus-visible{outline:2px solid var(--mint);outline-offset:4px}
.deck{
  background:#101410;border:1px solid #354136;border-radius:18px;
  box-shadow:0 12px 36px #0008;padding:18px;gap:10px;
}
.sec-label{color:var(--dim);font-size:10px;letter-spacing:1.6px}
.bet-row,.auto-target{background:#080b08;border:1px solid #2e382e;box-shadow:none}
.bet-row>button,.auto-target>button{background:#202820;color:var(--mint);box-shadow:none;min-width:40px;min-height:40px;border-radius:8px}
.bet-row>button:not(:disabled):hover,.auto-target>button:not(:disabled):hover{background:#314232}
.bet-value .unit{color:var(--mint);text-shadow:none}
.bet-value b{color:var(--text);text-shadow:none}
.auto-value small{color:var(--dim)}
.auto-value b{color:var(--amber)}
.auto-value b.off{color:var(--dim)}
.auto-toggle{min-height:40px;background:#202820;color:#cbd4c9;border:1px solid #354136;box-shadow:none;border-radius:8px}
.auto-toggle:not(:disabled):hover{background:#314232}
.auto-toggle.on{background:#38ed7020;color:var(--mint);border-color:var(--mint);box-shadow:none}
.play-button,.cash-button{border-radius:10px;min-height:60px;background:var(--go);color:var(--go-ink);box-shadow:none;text-shadow:none}
.cash-button{background:var(--take);color:var(--take-ink)}
.play-button:not(:disabled):hover{background:var(--go-lit)}
.cash-button:not(:disabled):hover{background:var(--take-lit)}
.drive-controls::before,.play-button::before,.play-button::after,.cash-button::before,.cash-button::after{display:none}
/* The options menu in THIS build's palette, set once as the four hooks the menu
   reads rather than as a rule per surface. Everything else -- the button, the
   panel, the hairlines, both hover states -- follows from these, so a build
   that repaints its deck repaints its menu with it.

   The values are the deck's own: #101410 on #354136 is exactly what `.deck`
   above is painted with, and mint is this build's accent. */
:root{
  --menu-surface:#101410;
  --menu-line:#354136;
  --menu-ink:#b6c4b5;
  --menu-hot:var(--mint);
}
/* Rows, not chips. These two used to give every item a 36px slab of #202820,
   which is what made the menu read as a second control panel; the list draws
   its own hairlines and highlights the full row instead. */
.deck-links>a,.deck-links>button{background:none;color:var(--menu-ink);box-shadow:none}
.deck-links>a:hover,.deck-links>button:not(:disabled):hover{
  background:var(--menu-surface);
  background:color-mix(in srgb,var(--menu-hot) 12%,transparent);color:var(--menu-hot);box-shadow:none}
.lane-tag{background:linear-gradient(var(--tint),#0000 90%);transition:opacity .15s}
/* Where the road runs on past its far end (a tall phone), the tags sit ON the
   road rather than at the top of the screen, and a tint that starts at full
   strength on the tag's top edge reads as a box pasted on the lanes. So it
   rises out of the road as well as falling back into it. */
.lane-tags.run-on .lane-tag{background:linear-gradient(#0000,var(--tint) 34%,#0000 90%)}
.lane-tag em{font-family:var(--body);font-weight:900;font-size:clamp(17px,1.8vw,27px);letter-spacing:1px}
.lane-tag.hot em{color:var(--coral)}
.lane-tag.warm em{color:var(--amber)}
.lane-tag.safe em{color:var(--mint)}
.lane-tag:disabled{opacity:1}
.mark{background:#0007}
.readout>b{color:var(--text);text-shadow:0 2px 8px #000;letter-spacing:.01em}
.readout>b small{color:var(--amber)}
#laneStatus{color:var(--mint)}
.road.is-counting #laneStatus,.road.is-draining #laneStatus{color:var(--amber);animation:none}
.credits{color:var(--text)}
.credits small{color:var(--dim)}
.outcome{background:#16090b;border-color:var(--coral);box-shadow:0 10px 30px #0008;--rim:#ff4052;--halo:#ff405220}
.outcome strong{color:var(--coral);text-shadow:none}
.outcome span,.outcome small{color:#ffc2c8}
.outcome.won{background:#0c1c0f;--rim:#38ed70;--halo:#38ed7020;border-color:var(--mint)}
.outcome.won strong{color:var(--mint);text-shadow:none}
.outcome.won span,.outcome.won small{color:#bfffcf}
.outcome::after{display:none}
.stage:has(.lane-tag.hot.active){--heat-colour:var(--coral)}
.stage:has(.lane-tag.warm.active){--heat-colour:var(--amber)}
.stage:has(.lane-tag.safe.active){--heat-colour:var(--mint)}
dialog{background:#101410;border:1px solid #536253;color:var(--text);border-radius:18px}
dialog::backdrop{background:#000c}
dialog h2{color:var(--mint)}
dialog p,dialog ol{color:#cbd4c9}
dialog input,dialog code{background:#080b08;border-color:#354136;color:var(--text)}
.fine-print{color:var(--dim)!important}
.dialog-close{color:var(--coral)}
#toast{background:#172319;border:1px solid #38ed7055;color:var(--text)}
/* Keep gameplay compositing cheap: no continuously repainting glow or blur. */
.deck,.deck>*,.lane-tag,.outcome,.outcome::before,.outcome::after,.readout>b,.drive-controls,.play-button,.cash-button{animation:none!important}
@media(max-width:700px){
  /* THE PHONE'S DENSITY, and every number in it is the gutter being paid for.
     This was `padding:12px 14px max(10px,env(safe-area-inset-bottom));gap:6px;
     border-radius:16px 16px 0 0;background:#101410;max-height:52dvh`. The
     radius and the background are gone because the sheet now wears the laptop
     bar's own 18px corner and its glass; what survives is the density, as
     tokens, because the rule that consumes them sits after this block.

     9px/9px against the old 12px/10px, and 5px against the old 6px. The deck
     has four visible children on a phone and therefore three gaps, so that is
     (22 - 18) + (6 - 5)*3 = 7px, and 7px is what the sheet gives back for an
     8px gutter. With the +1px tuck under the panel's top border the road comes
     out level: measured 602px -> 601.78px at 390x844, 689 -> 689.34 at
     430x932, 498 -> 498.31 at 360x740, 426 -> 425.67 at 375x667, 654 ->
     653.53 at 414x896. Par to within half a pixel at every phone measured --
     three of the five give up a fraction, two pick one up, and the largest
     move in either direction is 0.47px at 414x896. The old figures are whole
     numbers because the old road was sized from `board.clientHeight`; see the
     note beside the sheet for why that matters when reading this list.

     On real hardware the gutter is the home indicator rather than 8px, and the
     phone pays 2px for it: with `env(safe-area-inset-bottom)` forced to 34 at
     390x844, the road reads 575.78px against today's 577.78px. That is 0.35%,
     and it buys a panel that clears the indicator instead of sitting on it.

     The inline padding goes 14px -> 13px, which changes no height at all; it
     is there because the sheet is 28px narrower than the old full-bleed deck
     and the content row should not lose the whole 28px on top of that.
     Measured across 341, 345, 360, 375, 390, 414 and 430px wide, the drive
     button holds ONE row for every label it can show -- including GETTING
     READY… + $1,000.00, the widest -- and the deck reports the same height in
     every phase. The one width where 13px was not enough is handled in its own
     block below; see the note at `@media(max-width:340px)`.

     `max-height` is the footprint budget now, so the gutter comes out of it --
     see the note beside the sheet. It binds at no phone measured. */
  .deck{--sheet-pad-block:9px;--sheet-pad-inline:13px;--sheet-gap:5px;max-height:calc(52dvh - var(--sheet-gutter,0px))}
  .lane-tag em{font-size:17px;letter-spacing:.2px}
  .lane-tag small{font-size:7px;letter-spacing:.7px}
  .lane-tag b{font-family:var(--body);font-size:12px}
  .play-button,.cash-button{min-height:52px}
}
@media(max-width:700px) and (max-height:600px){
  /* THE SMALLEST PHONE PAYS THE GUTTER TWICE OVER, because it starts from a
     deck that is already squeezed. This was `padding-block:8px;gap:4px`, and a
     sheet at that density would have cost 320x568 seven pixels of road -- the
     one shape in the sweep that came out negative. 6px and 3px is
     (16 - 12) + (4 - 3)*3 = 7px back, and measured the deck goes 211px ->
     204px and the road 357px -> 357px. Par, like every other phone.

     6px of padding-block is tight against an 18px corner radius and it is the
     right trade here: this block exists for a 568px-tall screen already giving
     36% of itself to controls, and on this project the surplus goes to the
     game. If it ever reads cramped by eye, the lever is the gutter rather than
     the padding -- 8px -> 5px buys 3px back at the cost of the panel sitting
     closer to the edge -- never the road. */
  .deck{--sheet-pad-block:6px;--sheet-gap:3px;max-height:calc(60dvh - var(--sheet-gutter,0px))}
  .bet-row>button,.auto-target>button,.auto-toggle{min-height:36px}
  .play-button,.cash-button{min-height:46px}
}
/* THE 320px PHONE BUYS ITS SIDE GUTTER BACK, and this is the one place the
   float had to give something up. The sheet is inset 14px down each side, and
   on a 320px screen those 28px come straight out of the drive button: measured
   there, GETTING READY… + $1,000.00 needs 277px of button to hold one row, and
   the default sheet leaves it 264px. It did not wrap -- `overflow` does not
   clip this -- the two FLEX ITEMS stacked instead, taking the button 46px ->
   52px and the deck 204px -> 210px for the 2.4 seconds the launch label is up.
   That is exactly the phase-tied layout shift the `font-size:clamp(22px,...)`
   comment above was written to kill, and the side gutter had re-introduced it.

   12px of gutter and 10px of inline padding give the button 286px, 9px clear
   of the 277px it needs, against the 290px it has on the build before this
   change. 6px of sky down each side is still a float and still shows the panel
   as a panel; a 320px screen is simply not wide enough for the laptop's 14px.

   340px is the boundary and it is measured, not rounded: the requirement is
   pinned at 277px for every width below 355px, where `6.2vw` finally passes
   the 22px floor, and the default 28px gutter stops clearing it at about
   333px. 340 leaves the first width that falls through to the default -- 341px
   -- a button of 285px, 8px clear. That margin is deliberate: the condensed
   face is preloaded, but the Impact and Arial Narrow fallbacks behind it are
   wider than anything measured here.

   Type size was the other candidate and it is the wrong one. At the default
   sheet's 264px the pair holds one row at 20px and breaks at 21px, so keeping
   the gutter would have cost the smallest phone two whole points off its main
   button -- shrinking the thing you press to protect 8px of margin. */
@media(max-width:340px){
  .deck{--sheet-side:12px;--sheet-pad-inline:10px}
}
/* v5: the options button's hairline too, now that the two sit either side of
   the top of the screen as a pair. */
.credits{background:#101810;border-color:#354136;box-shadow:inset 0 0 0 1px #354136}
.bet-value>.unit{color:var(--mint)}

/* Compact controls: no brand header or decorative signal strip. */
.bet-value i.unit{font-size:1em;line-height:1;transform:none;transition:none}
.bet-value:has(b.bumped) i.unit{transform:none}

/* The reference's heavy condensed face, served with the game on both hosts. */
@font-face{font-family:'Barlow Condensed';font-style:normal;font-weight:900;font-display:swap;src:url('./assets/fonts/barlow-condensed-900.ttf') format('truetype')}
/* BET's face, from the owner's Crocodile Temple: Fredoka Bold, Latin only
   (assets/README.md). */
@font-face{font-family:'Fredoka';font-style:normal;font-weight:700;font-display:swap;src:url('./assets/fonts/fredoka-700.woff2') format('woff2')}
:root{--title:'Barlow Condensed',Impact,'Arial Narrow',sans-serif}
.lane-tag em{font-family:var(--title);font-weight:900;font-size:clamp(28px,3.5vw,48px);letter-spacing:.2px;color:#fffdf5}
.lane-tag.hot em,.lane-tag.warm em,.lane-tag.safe em{color:#fffdf5}
.lane-tag small{font-size:clamp(10px,1.05vw,15px);letter-spacing:1px}
.lane-tag b{font-family:var(--title);font-weight:900;font-size:clamp(20px,2.2vw,30px);opacity:1;line-height:1}
@media(max-width:700px){.lane-tag em{font-size:clamp(24px,6vw,36px)}.lane-tag small{font-size:9px;letter-spacing:.5px}.lane-tag b{font-size:21px}}
@media(orientation:landscape) and (max-height:540px){.lane-tag em{font-size:26px}.lane-tag small{font-size:9px}.lane-tag b{font-size:20px}}

/* THE SHEET'S SKIN: the laptop bar's glass, on a phone and an iPad.

   This is the half of the owner's question that is about paint rather than
   structure. Every value below is COPIED from the dock query at the bottom of
   this file rather than shared with it, and that is deliberate. The two
   queries can never both match -- `(pointer:coarse)` is the complement of the
   dock's `(hover:hover) and (pointer:fine)`, and `(max-width:860px)` the
   complement of its `(min-width:861px)` -- so nothing is gained by hoisting
   them into tokens except the risk of moving a number the owner has already
   signed off on. The bar was diffed property by property after this block
   landed, at 1440x900, 1440x830, 1366x768, 961x541 and 861x541: deck rect,
   road width, `--road-centre`, `--dock-inset`, padding, gap, border, radius,
   shadow, every control fill and the result card all come back IDENTICAL.
   Eight duplicated rules is the price of that guarantee.

   WHY THE BLOCK SITS HERE, between the Signal palette and the dock. It has to
   be after the Signal section's `.deck{background:#101410;border:1px solid
   #354136;border-radius:18px;box-shadow:0 12px 36px #0008}`, which is (0,1,0)
   like this rule and would otherwise win on source order -- that is exactly
   what has been killing the touch block's own skin declarations 600 lines
   above. Being later than the Signal section also puts it later than the
   short-landscape block, which is why its query has to exclude that shape by
   hand rather than relying on position.

   THE FIVE ARMS ARE "the touch layout, minus short landscape", written without
   `not()`. The short-landscape block is `(max-width:960px) and
   (orientation:landscape) and (max-height:540px)`, so each arm contradicts it
   in one term: arms 1 and 3 require a height of at least 541, arms 2 and 4
   require portrait, and arm 5 requires a width of at least 961. Checked shape
   by shape, each arm put through `matchMedia` on its own in a touch-emulated
   page: 390x844 and 768x1024 take arms 1, 2, 3 and 4; 1024x768, 1180x820 and
   1366x1024 take arms 3 and 5. Arm 1 reaches NONE of those three, and cannot
   -- it asks for `max-width:860px` and they are all wider. The arms overlap
   far more than "one arm per shape" would suggest, which is the point: the
   redundancy is what makes the union safe to reason about, and no shape is
   carried by a single arm except the last. 1100x500 -- an iPad in Split View,
   coarse, landscape and short, which the short-landscape block does NOT catch
   because it is wider than 960 -- takes arm 5 and nothing else. At every one
   of those shapes `--dock:sheet` and the glass skin below arrive together or
   not at all, which is the property that actually has to hold. 844x390,
   740x360 and 900x500 match no arm, correctly, and measured identical to the
   build before this change.

   THE FOUR SIGNED-OFF CONTRAST FIGURES SURVIVE THE MOVE, and that is the thing
   that had to be verified rather than assumed, because the sheet is a
   different shape over a different part of the photograph. Measured from real
   screenshots, laptop bar at 1440x830 first and then the range across
   390x844, 430x932, 360x740, 320x568, 768x1024, 1024x768, 1180x820 and
   1366x1024: well outline against the well 2.394 -> 2.397-2.415; stepper face
   against the well 1.606 -> 1.590-1.609; the stake figure 19.248 ->
   19.019-19.027; the mint unit 16.537 -> 16.340-16.347. Every label clears
   4.5:1 with room: CASH OUT AT in `--dim` is the binding one at 8.337-8.376
   live, and 7.685 with the panel forced over a saturated white background --
   the star case. The mint +/- glyph on a stepper face reads 8.355-8.380
   against the bar's own 8.364.

   The gradient is NOT re-tuned for the new aspect, and the dock's own comment
   says why: every term of `radial-gradient(62% 162% at 50% 4%, ...)` is a
   percentage of the same box, so the corners land on the transparent last stop
   at any width or height. A composited RGB triple only means something here if
   the sample point is named, because the gradient is centred at `50% 4%` and
   its alpha drops away fast either side of that: on ONE row, 4px below the
   panel's top edge at 390x844, the fill reads (13,14,17) on the panel's
   horizontal centre line and (4,7,16) at 15% of its width from the left --
   same row, same instant, nine levels of red apart. Measured from real
   screenshots AT THAT CENTRE POINT, ten captures 400ms apart and every
   capture identical: (13,14,17) at 390x844, (13,13,17) at 768x1024, and
   (13,14,17) on the 1440x830 bar, which is the agreement the paragraph is
   claiming.

   1024x768 is deliberately not in that list, and the reason is the better
   half of the argument. There the point lands over a lane glow instead of
   over sky, so the BACKDROP cycles (1,6,21) -> (17,22,36) with the scene and
   the fill cycles (12,13,16) -> (15,16,19) with it; no fixed triple for that
   shape reproduces, and quoting one would be inventing a still frame. What
   the swing shows instead is the thing worth knowing. Hide the panel, sample
   the same pixel for the raw backdrop, and the fill moves 3 levels for the
   backdrop's 16 -- 0.19 of a level per level -- so the panel is laying down
   0.8 coverage of #101010, the declared `cc`, at that point on every shape
   measured. THAT is the invariant: the panel's own contribution, not the
   composite. The composite only looks constant on the three shapes whose
   backdrop happens to be still, and reading those three as proof of
   invariance is luck being mistaken for a measurement.

   The one honest difference is the rim. On the laptop the bar is 1216px over a
   792px road, so its ends sit on open sky; on a phone the sheet is 362px over
   a 362.70px road, so the hairline's whole length sits on the road's last row
   and picks up the verge. Sampled with the panel hidden, the row 3px above
   the top border is road across the sheet's entire span at 390x844 -- its two
   ends land in the red and the green lane glow -- while the same row at
   1440x830 leaves the bar's ends on sky, (0,2,12) and (0,1,11).

   The figure to quote for that is the TOP EDGE alone, and it is worth saying
   why, because the whole-perimeter mean says something different and softer.
   Taking every border pixel against the pixel 3px outside it, corners
   excluded 20px in, 868 to 2,470 samples a frame over eight frames 350ms
   apart, the touch shapes come out on BOTH sides of the bar rather than
   below it: 768x1024 1.701, 1024x768 1.710, 390x844 1.711, the bar 1.723,
   360x740 1.735, 320x568 1.765. That average is not measuring the effect
   described above, because the sheet's four edges sit on four different
   things and its bottom edge -- hard against the foot of the screen, over
   nothing -- runs 1.87 to 1.94 everywhere and swamps the top. Restricted to
   the top edge, every touch shape IS below the bar, which is the rim
   behaviour this paragraph is about: 1.574 on the bar against 1.394 at
   390x844, 1.435 at 768x1024, 1.489 at 360x740, 1.497 at 320x568 and 1.504
   at 1024x768. Do not read a "worst shape" out of the perimeter column: its
   three lowest figures move by up to 0.017 frame to frame and their order
   changes with them. On the top edge the phone genuinely is the floor --
   390x844 ranged 1.379-1.416 over those eight frames and never touched
   768x1024's 1.424-1.444 -- while the middle of that list, 360x740, 320x568
   and 1024x768, is one overlapping cluster around 1.49-1.50.

   That softer top edge is the +1px tuck doing its job and a consequence of
   the sheet being road-width, not a defect; if it ever reads as fringing the
   move is to widen the sheet past the road, never to drop the tuck, which
   would open a hairline of sky.

   No `backdrop-filter`, here or anywhere: banned on this project on measured
   frame-rate grounds. Everything below paints once into the panel's own paint.

   The bar's four-column `grid-template-areas` is deliberately NOT ported. It
   needs 861px of width and the sheet keeps this layout's flex column. What was
   asked for is the look, and the look is the glass, the hairline and the
   wells. */
@media (max-width:860px) and (min-height:541px),
       (max-width:860px) and (orientation:portrait),
       (max-width:599px) and (max-aspect-ratio:1499/1000),
       (pointer:coarse) and (min-height:541px),
       (pointer:coarse) and (orientation:portrait),
       (pointer:coarse) and (min-width:961px){
  .deck{
    background:radial-gradient(62% 162% at 50% 4%,#101010cc 0%,#0a0a0aab 42%,#06060636 72%,#06060600 100%);
    border:1px solid #ffffff36;border-radius:18px;
    box-shadow:inset 0 1px 0 #ffffff1f;
    padding:var(--sheet-pad-block) var(--sheet-pad-inline);gap:var(--sheet-gap);
  }
  .bet-row,.auto-target{background:#000000c9;border:1px solid #ffffff4a;box-shadow:none}
  .bet-row>button,.auto-target>button{background:#ffffff30;box-shadow:none}
  .bet-row>button:not(:disabled):hover,.auto-target>button:not(:disabled):hover{background:#ffffff4d}
  .auto-toggle{background:#000000c9;border:1px solid #ffffff4a;box-shadow:none;border-radius:11px;color:#ececec}
  .auto-toggle:not(:disabled):hover{background:#00000091}
  .auto-toggle.on{background:#38ed7020;color:var(--mint);border-color:var(--mint)}
  .play-button,.cash-button{border:0}
}

/* The laptop dock: the deck stops being a panel pinned to the top-right corner
   and becomes a glass bar FLOATING over the foot of the road.

   The query is shaped to name a laptop and nothing else. `(hover:hover) and
   (pointer:fine)` is the part that does the real work: an iPad reports a
   coarse primary pointer even in landscape at 1180px wide, so it keeps the
   floating side deck it has today and only a mouse-driven machine gets the
   bar. The two width/height arms then keep this block from ever overlapping
   the two narrow layouts above -- `(max-width:860px)` and the short-landscape
   `(max-width:960px) and (max-height:540px)` -- so those layouts are not
   fighting this one for the same properties and stay exactly as they were.

   This block sits after the Signal palette section on purpose: that section
   restyles `.deck` at the same specificity, so only source order can win.

   The bar floats rather than taking a row of its own, and that is what makes
   the glass mean anything: the road, the sky and the lane glow keep running
   underneath and around it, so a translucent panel has something to be
   translucent ABOUT. An opaque strip under the canvas would have nothing
   behind it to show. Because the canvas is full height again, the bar also
   costs the game no road, which is the point -- surplus space goes to the
   game.

   Every size below is chosen to hold the bar's height CONSTANT across phases.
   Nothing inside it may grow when DRIVE becomes CASH OUT, and the drive cell
   holds exactly one button now, so the main button's rect is the same whether
   or not auto play is armed.

   The order across the bar puts the two things the game is actually played
   with -- the bet and the button that spends it -- in the MIDDLE, on the
   screen's centre line, directly under the big multiplier and the road's own
   centre. The auto controls are the quieter flanks either side: the cash-out
   target on the left, AUTO PLAY on the right, both in the control row, with
   nothing above them to invent a heading for. */
@media (min-width:961px) and (hover:hover) and (pointer:fine),
       (min-width:861px) and (min-height:541px) and (hover:hover) and (pointer:fine){
  .deck{
    /* Read by resize() in app.js, which sizes and centres the road for the
       docked bar instead of taking the phone layout's near-full-width branch. */
    --dock:bar;
    --bar-gap:clamp(10px,1.2vw,18px);

    /* Centred on the road, clear of all four edges so the sky shows around it. */
    position:absolute;z-index:4;
    left:50%;translate:-50% 0;right:auto;top:auto;
    bottom:clamp(10px,1.8vh,18px);
    width:min(1216px,calc(100% - 28px));
    max-height:none;overflow:visible;

    /* Glass, over the SKY. The road stops at this bar's top edge and the
       moon-sky plate runs on behind and around it, so what sits under the
       panel is near-black night, not neon lanes.

       The fill this replaces -- linear-gradient(#1a233a8c,#10172a99) inside a
       #ffffff2b border -- was written as a LIFT: a cool tint meant to read as
       a panel against bare sky. Measured against the plate it actually sits
       on, that lift is the whole of the owner's "doesn't match the
       background". The graded sky under the bar's footprint is luminance 3.5;
       the old fill composited to 20.7 along the label row and 15.1 at its
       foot, four to six times its surround, in a frame where nothing else
       below the road is more than about 1.5x what is beside it. In a
       near-black field a 6x step is not glass, it is a lit slab. The border
       was the louder half of it: #ffffff2b over that sky composites to
       luminance 60, seventeen times the sky, and the photograph has no
       straight lines below the road for a 1216x96 outlined rectangle to
       belong to.

       The HUE was never the fault, and that is worth writing down so the next
       reader does not "fix" it again. The graded sky here is itself hue ~230
       at 96% saturation; the old #1a233a was hue 223 at 55% -- within seven
       degrees of the sky and less saturated than it. What the navy clashed
       with was this build's OWN panels, which the Signal palette section
       above paints green-black: `.credits` #101810, the deck and the options
       menu #101410. The credits badge sits immediately above and just
       outside this bar's left end, so that was a side-by-side mismatch and
       not a remembered one. Hence #0d130f and #0a0e0a below: hue 120, the
       badge's own family.

       The fill is a RADIAL, and its job is to give the panel a middle without
       giving it a STEP. It lifts to about 4.3x the average sky under the bar's
       footprint -- measured against the very pixels beneath it, 3.96x and
       3.05x at two points 90px either side of the centre line, which is where
       the bet and the button sit and the two things that have to be found
       instantly -- and falls away through the 42% and 72% stops to arrive at
       the corners at exactly the value of the sky beside them. So there is no
       perimeter where the fill jumps, and no ring the fill alone would draw.
       What draws the shape is the hairline four paragraphs down; what the fill
       does is hand that hairline a panel to be the edge OF.

       THE LAST STOP HAD TO MOVE FOR THAT, `#00000052` -> `#05070500`, and it
       is the one substantive change to the fill. Black at .32 over a sky of
       two or three levels does not fade out, it SUBTRACTS: measured at
       1440x830 against the same pixels with the fill switched off, the old
       last stop put the bottom-left corner at 0.55x and the bottom-right at
       0.84x of the sky around them. A panel that ends darker than its surround
       is a hole, and a rim around a hole is a wire round a gap -- the same
       pasted-on failure the owner rejected the first time, only dimmer. A
       transparent last stop interpolates premultiplied, so the fill's ALPHA
       reaches zero at the corner instead of its colour reaching black: both
       bottom corners now measure 1.00x, dead flush, and no point on the panel
       is below 1.00x any more. The 0%, 42% and 72% stops are untouched, and
       the panel is pixel-identical wherever they govern -- 14.94 at the origin
       either way, 13.94 and 14.01 at the two probes 90px out -- so the
       paragraph above still holds word for word. The corners still dissolve.
       They have only stopped digging.

       The ellipse is sized so the corners land exactly on that last stop.
       With the origin at 50% 4%, the far corner is (0.5w, 0.96h) away and the
       radii are 0.62w and 1.62h, so it sits at
       sqrt((0.5/0.62)^2 + (0.96/1.62)^2) = 1.0005 of the ellipse. Every one
       of those four terms is a percentage of this same box, so that number is
       invariant: the corners keep dissolving whatever the bar's width or
       height becomes, and nothing here needs re-tuning if a taller stepper or
       a second label row ever grows it.

       The drop shadow stays deleted rather than being brought back. `0 8px
       22px #00000059` is black at .35 over luminance 3.5: the most it can
       subtract is about one level, which is below the threshold of being
       visible at all. It cost a paint and bought nothing.

       WHAT SEPARATES THE BAR FROM THE SKY IS ONE HAIRLINE, and this is the
       half of the last pass the owner sent straight back: "betting system
       seems to [not be] enough difference so maybe add cool border or
       something like that for me to differentiate". That pass had read his
       earlier note -- image 3 does not match backgrounds very well -- as an
       instruction to DISSOLVE the panel, and set this border to `#0000`.
       Measured on that build at 1440x830, the border row came out between 1.1
       and 7.3 against a sky running 1.9 to 8.6: on the right-hand half the
       border pixel was darker than both the panel inside it and the sky
       outside it. There was no edge to find. He is describing the build
       accurately.

       `#f3c25716` is the same 1px of border with the file's own gold in it at
       .086, and it measures 19.1 to 30.1 the whole way round at 1440x830
       against that same 1.9-to-8.6 sky -- against the 44.2 to 54.9 the
       rejected `#ffffff2b` draws at the identical probes. So it is a little
       over 40% of the step he threw out, and warm where that was cool white.
       In absolutes rather than ratios, which is the honest instrument down
       here: measured over the whole footprint in a live frame the sky's 95th
       percentile is 8.0 to 8.7 and its 99th is 22.5 to 32.2, so 19-30 is where
       the sky's own brightest ordinary pixels already are, and 45-55 is past
       the 99th at every viewport this query admits. The old border was a drawn
       line in a field that has none. This one is the value of the brightest
       night the photograph contains, carried round a shape.

       ONE UNIFORM DECLARATION, AND THE RADIAL GRADES IT. The fill is
       brightest at top and bottom centre and fades to nothing at the ends, so
       a border composited over it does the same without a gradient being
       written anywhere: at 1440x830, 19.1 at the right flank, 20.3 at the
       left, 20.3-20.6 along the top, 23.0 at the bottom left and 30.1 at the
       bottom centre. On the shorter laptops the grade is DEEPER rather than
       shallower -- at 961x541 and 861x541 the flanks read 11.3 to 15.3 where
       the top and bottom still read 19.6 to 30.1 -- because the ellipse is a
       percentage of a box whose aspect has changed, and a bar whose ends stay
       quieter than its middle is the behaviour that was wanted anyway.

       `border-image` is the obvious way to grade a rim deliberately and it is
       the wrong one: it ignores `border-radius` and paints the SQUARE corner.
       Measured, it took the pixel at (112,719) -- which is outside the rounded
       shape entirely and should be sky -- from 2.4 to 34.7.

       WARM, AND NOT THE DECK'S OWN GREEN-GREY. Measured over the whole
       footprint in a live frame, the sky under this bar is RGB (1.4, 4.2,
       16.5): blue-black with essentially no red in it. `#354136`, which is
       what `.deck` and the options menu are outlined with elsewhere in this
       build, is the same family as the fill that was disappearing -- one more
       green-black thing on a blue-black photograph. `#f3c257` already lives
       inside this bar (`.bet-row:has(>button:active)` flashes a stepper's well
       gold) and is the win plate's OUTER ring through `--rim-faint`, while
       carrying no game meaning of its own: mint is safe, amber is bank, coral
       is crash, and gold is structure. (The win plate's INNER rim is mint, not
       gold -- the Signal section overrides `--rim` on `.outcome.won` and
       leaves `--rim-faint` alone -- so this matches the plate's outer ring and
       nothing else.)

       The inset top light turns warm with it, `#cfe0cf17` -> `#f3c2571a`, so
       the top edge and the rim are one colour instead of two. It is the same
       brightness it was: measured along the bar's top row at 1440x830, 25.9 /
       33.3 / 24.0 where the cool one gave 26.1 / 33.4 / 23.4.

       The border keeps its 1px and has only its colour back. `border:0`, or a
       2px rim, would change the bar's height, which app.js measures into
       `--dock-inset` and hands back to the road -- harmless in itself, but a
       silent drift in the road's height and in where the badge and the toast
       sit. Checked rather than assumed: `--dock-inset` reads 110.9375px at
       1440x830 with this rim, which is what it read without one, and 102px at
       both 961x541 and 861x541. The border box is bit-for-bit what it was. If
       the rim ever reads hot on a Retina panel -- every number above is dpr 1,
       and 1px of CSS is 2 device pixels at dpr 2 -- the move is down the alpha
       to `#f3c25712`, never up the width.

       Still no `backdrop-filter`: it is a measured frame-rate killer over
       this canvas and is banned on this project. Everything above paints once
       into the bar's own paint, with no filter, mask or opacity, so the bar
       adds no compositing layer over the game. */
    /* TRANSPARENT, with a findable edge, and the contrast spent INSIDE.

       This panel has now been asked about three times and the first two
       answers were both wrong in the same way: they tried to make the BAR
       stand out from the sky. It was navy first, which read as a blue-grey
       rectangle pasted on, then an opaque green-black borrowed from
       `.credits`, which read as green -- the badge is 150px wide and this is
       1216px, and a slab that size has no small amount of hue.

       What was actually being asked for was contrast between the CONTROLS and
       the panel, not between the panel and the night. Everything inside had
       been tuned to whisper against a fill that was itself nearly invisible:
       the steppers sat at 7% white, the wells at 15% borders, and the whole
       assembly came out as one flat value that had to be hunted for. That is
       the fix, and it is below in the control rules rather than here.

       So the fill goes back to the radial that dissolves at its corners --
       neutral now, equal channels at every stop, because the green in the old
       one was the colour that was rejected. It ends fully transparent, so
       there is no perimeter where the fill steps and no rectangle to trace,
       and the stars behind it stay readable through the panel.

       The border is the one thing that goes UP, from 8.6% gold to 21% white.
       At 8.6% over this sky it was a rumour; the owner asked for it "a little
       more visible" and this is a little. It stays a hairline and stays
       neutral, so the edge is findable without the panel becoming a box drawn
       on a photograph that has no straight lines in it.

       Still no `backdrop-filter`: banned on this project on measured
       frame-rate grounds. */
    background:radial-gradient(62% 162% at 50% 4%,#101010cc 0%,#0a0a0aab 42%,#06060636 72%,#06060600 100%);
    border:1px solid #ffffff36;border-radius:18px;
    box-shadow:inset 0 1px 0 #ffffff1f;

    padding-block:11px;
    padding-inline:20px;

    display:grid;
    /* Named areas rather than nesting, because the deck's children are flat
       siblings in the markup and the markup does not change. `auto` is a CSS
       keyword, so the target column is named `target`.

       The flanks are mirror images now -- one column and one gap on each side
       of the centre pair -- so the padding is symmetric and the pair's
       midpoint falls on the screen's centre line on its own. */
    grid-template-areas:".      betlabel drive ."
                        "target bet      drive autoplay";
    grid-template-columns:minmax(0,1.7fr) minmax(0,2.3fr) minmax(0,3.2fr)
                          minmax(0,1.7fr);
    grid-template-rows:auto auto;
    column-gap:var(--bar-gap);
    row-gap:5px;
    align-items:center;
  }

  /* `.auto-row` is a grid of its own in the base rules, but here its two
     children sit at opposite ends of the bar -- the target on the left flank,
     AUTO PLAY on the right. `display:contents` dissolves the wrapper so they
     become items of the deck's own grid and can each be placed by name. */
  .auto-row{display:contents}

  .deck>.deck-sec.deck-head{grid-area:betlabel}
  .deck>.bet-row{grid-area:bet}
  .deck>.drive-controls{grid-area:drive}
  /* The base rules span these across the whole auto grid, which is wrong once
     that grid is gone; the explicit areas have to beat them. */
  .auto-row>.auto-target{grid-area:target;grid-column:target}
  .auto-row>#autoBtn{grid-area:autoplay;grid-column:autoplay}

  /* BET AMOUNT is the only label the bar needs. The AUTO heading went with
     fast mode: one stepper that says CASH OUT AT on its own face does not need
     a second word above it, and dropping it keeps the glass quiet. */
  .deck>.deck-sec:not(.deck-head){display:none}
  .deck-sec{margin:0;min-height:0;display:flex;align-items:center;justify-content:center}
  .deck-head{margin:0;justify-content:center}
  .sec-label{display:inline}

  /* Both flank controls sit in the control row. The target stepper sets that
     row's height; AUTO PLAY then STRETCHES to match it rather than keeping the
     40px it has on every other layout, so the three controls share one top and
     one bottom edge and the right flank stops reading as a smaller thing
     parked low. The palette section's `min-height` has to be released for the
     stretch to take. */
  .auto-row>.auto-target{align-self:end}
  .auto-row>.auto-toggle{align-self:stretch;min-height:0;height:auto}
  .wide-only{display:inline}

  /* A little air on the pair's two OUTER sides only -- equal on both, so the
     midpoint does not move -- to read the bet and the button as one unit set
     slightly apart from the quieter flanks. */
  .deck>.deck-sec.deck-head,.deck>.bet-row{margin-left:6px}
  .deck>.drive-controls{margin-right:6px}

  /* Wells, not slabs. The fields inside the bar are cut back DOWN into it --
     darker than the panel around them, with a hairline of light -- rather
     than being lighter slabs stacked on top of it.

     They carry MORE of the work than they used to, and that is why the alpha
     moved. The panel is now a lift under the centre pair and very nearly
     nothing at the flanks, so a control out on the flank cannot borrow its
     contrast from the panel: at the radial's 72% stop, #00000066 would leave
     a dim glyph sitting over a star at 4.08:1, under the 4.5:1 line.
     #000000b8 is the alpha that holds every stop at 5:1 or better, and it is
     also what keeps the flank controls reading as controls once the panel has
     dissolved out from under them.

     The comment this replaces justified that darkness with "the moon low on
     the screen", and the next reader should not spend time on that case
     because it cannot happen: the plate's moon sits at 0.306 of the plate's
     own height, the placement is always cover-fit and vertically centred, and
     the plate is never shorter than the viewport, so the moon is never below
     0.306 of the screen -- far above this bar at any size. What the wells
     actually sit on is point stars: 0.04% of the pixels behind the bar are
     brighter than luminance 180. That is a much smaller budget to defend than
     the old note claimed, which is exactly what made darkening the PANEL safe
     at the same time as darkening these.

     The hairline goes #ffffff1f -> #cfe0cf26: a step up in weight, because
     these are shapes in their own right now rather than cut-outs in a slab,
     and in the build's green-neutral rather than pure white so it belongs to
     the same family as the panel's own top light. */
  /* THE WELLS AND THE STEPPERS, which is where the contrast was really wanted:
     "btns inside color like more different so i can see better".

     The fill stays DARK and gets darker. That is not a compromise -- it is what
     carries the labels wherever the sky behind the bar is bright, the moon low
     in the frame being the case that matters, and a lighter well would trade
     the text's legibility for the well's own outline. The outline is bought
     somewhere cheaper instead: the border goes 15% to 29%, and neutral, so each
     control is a drawn box rather than a slightly different shade of night.

     The steppers are the ones that were really lost. #ffffff12 is 7% white on a
     panel that is itself nearly transparent over black -- the + and - were
     floating on nothing. At 19% they are visibly raised out of the well they
     sit in, and the hover step from 18% to 30% is now a change you can see
     rather than one you can measure. */
  .bet-row,.auto-target{background:#000000c9;border:1px solid #ffffff4a;box-shadow:none}
  .bet-row>button,.auto-target>button{background:#ffffff30;box-shadow:none}
  .bet-row>button:not(:disabled):hover,.auto-target>button:not(:disabled):hover{background:#ffffff4d}
  /* The wells' own fill and corner radius, so the toggle reads as one of the
     family rather than as a button dropped beside them. It is a well rather
     than a faint light fill for the same reason its neighbours are: on a
     lifted panel a pale fill leaves its own label short of 4.5:1, and the
     contrast has to come from under the text, not from the panel's alpha. */
  .auto-toggle{background:#000000c9;border:1px solid #ffffff4a;box-shadow:none;border-radius:11px;color:#ececec}
  /* The hover lifts by the same 0.12 of alpha it always did, from the well's
     new floor rather than the old one. */
  .auto-toggle:not(:disabled):hover{background:#00000091}
  /* The armed state keeps the mint outline it has everywhere else. */
  .auto-toggle.on{background:#38ed7020;color:var(--mint);border-color:var(--mint)}

  /* The round-time dimming of the bet row stays, but it may only dim, not
     MOVE. Its `scale(.985)` is a cosmetic shrink, and on the old floating deck
     it cost nothing; here the bet row is the left half of the centred pair, so
     shrinking it walks the pair's left edge inward by ~2px the moment a round
     starts and drags the midpoint off the screen's centre line. Scaling on Y
     alone keeps the whole dimming effect and leaves the horizontal geometry --
     and therefore the centring -- fixed for the entire round. */
  body[data-phase=playing] .bet-row,body[data-phase=crashing] .bet-row,
  body[data-phase=launching] .bet-row{transform:scaleY(.985)}

  /* The drive cell spans both rows, so DRIVE / CASH OUT is as tall as the
     label and its control together, and it holds ONE button: the main one.
     STOP AUTO PLAY is hidden here because it used to appear beside the main
     button and squeeze it the moment auto play was armed -- the ride button
     must not change when you press AUTO PLAY. Nothing is lost: AUTO PLAY is
     itself a toggle that disarms on a second press, and its lit state says it
     is armed. */
  .drive-controls{margin-top:0;height:100%;display:block}
  /* The label is sized HERE rather than in the base rule, which is the whole
     of why this is a separate declaration. The base
     `font-size:clamp(18px,1.4vw,23px)` is shared with two other layouts that
     cannot take the increase: the touch side-deck, which at 1366-1440px wide
     is only 272-360px across and is already half a pixel over its own wrap
     limit at 1.4vw, and the two dialog buttons (GOT IT, VERIFY LAST ROUND),
     which carry no amount beside them and have no reason to grow. The dock
     is the layout the owner is looking at and the only one with room.

     The drive cell is 68px tall at the tightest viewport this block admits
     and 72px at 1440, and the base clamp was putting 18-20px of type in it.
     That is why the button read empty: 21px of ink with 21px of air above and
     below it. 21-29px is a 17% rise at the floor and 32% through the middle
     of the laptop range, and the amount rises with it because `b` is set in
     `em` -- $1,000.00 goes 14.8px -> 17.2px at the floor and 16.5px -> 21.8px
     at 1440.

     Each number against a measured ceiling, taking GETTING READY… + $1,000.00
     as the binding pair (it is the widest of the six the button can show, at
     9.98px of content per 1px of type against CASH OUT + $1,000,000.00's
     8.53px). 861x541 is the tightest cell this query admits: stepped
     through in the page there, that pair still holds one line at 22px and
     wraps at 23px. 21px is therefore one whole pixel below the last size that
     fits, which is the margin a first paint wants -- the condensed face is
     preloaded, but if it ever failed to arrive the stack falls back to Impact
     and then Arial Narrow, both wider than anything measured here.
     1.85vw reaches 21px at 1135px and
     29px at 1568px, so the fluid leg spans the real laptop range and is never
     the binding value at either end. Above 1244px the bar is pinned at its
     1216px cap and the ceiling is flat at 34.3px, so the 29px cap clears it
     by 18%.

     Nothing here can change the bar's height: the button takes its height
     from the grid rows, which are set by the label row and the 40px steppers,
     and `min-height` is released to 0 just below. The bar must not move when
     DRIVE becomes CASH OUT, and at 29px the line box is 34.8px in a 72px
     cell, so it does not. */
  .play-button,.cash-button{width:100%;min-height:0;height:100%;font-size:clamp(21px,1.85vw,29px)}

  /* DRIVE / CASH OUT / the red wait state stay SOLID -- the one opaque thing
     on the glass, so the button you are here to press reads instantly. The
     palette section already paints them; this only stops the glass treatment
     above from reaching them. */
  .play-button,.cash-button{border:0}

  /* The toast clears the floating bar instead of sitting under it.
     `--dock-inset` is published by resize() in app.js as the bar's footprint
     (px from the bottom of the road to the bar's top), and falls back to 0 so
     this is safe before that lands. */
  #toast{bottom:calc(var(--dock-inset,0px) + 14px)}
}

/* THE TABLET IN LANDSCAPE IS THE LAPTOP TURNED SIDEWAYS, and until this block
   it was being handed a phone's layout because `(pointer:coarse)` is the only
   thing the sheet asks for.

   WHAT WAS WRONG, measured. At 1366x1024 the sheet is 1216px wide -- the
   laptop bar's own width, to the pixel -- and stacks bet, auto and drive down
   a column, so it stands 258.56px tall and `--dock-inset` reads 266.56px.
   That is 26% of the screen's height given to three controls on a screen wide
   enough to lay them side by side, and it leaves the road 758.44px deep. The
   same panel on a mouse-driven 1366x1024 window costs 113.66px and leaves
   911.34px. The controls themselves tell the same story: DRIVE comes out
   1174 x 60 and AUTO 1174 x 40, single buttons a metre wide on a tablet.
   On real hardware it is worse by the home indicator -- `env(safe-area-inset
   -bottom)` is 20px on every iPad that has one, in BOTH orientations, so the
   gutter goes 8px -> 20px and the inset 266.56 -> 278.56.

   WHAT THIS BLOCK DOES. One row instead of three, which is the same content
   in the same glass with `flex-direction`, `grid-template-columns` and the
   gap changed, and nothing else. Measured after, idle and mid-round alike
   because the phase fold leaves the row a row:

     viewport    inset             road depth          roadW      w:h
     1366x1024   266.56 ->  92.00  758.44 -> 933.00   1270 ->  751  1.67 -> 0.81
     1180x820    264.81 ->  92.00  556.19 -> 729.00   1097 ->  649  1.97 -> 0.89
     1133x744    264.25 ->  92.00  480.75 -> 653.00   1054 ->  623  2.19 -> 0.95
     1024x768    263.92 ->  92.00  505.08 -> 677.00    952 ->  563  1.89 -> 0.83
     1100x500    235.00 ->  92.00  266.00 -> 409.00   1023 ->  511  3.85 -> 1.25
      960x541    254.33 ->  92.00  287.67 -> 450.00    893 ->  528  3.10 -> 1.17

   Between 137.7 and 174.6px of road depth back at every landscape tablet, and
   the width:depth ratio lands in the 0.81-0.95 band the laptop bar (0.82) and
   the portrait tablets (0.80-0.94) already live in. 1100x500 also stops
   CLIPPING: the sheet's `max-height:calc(47dvh - gutter)` binds at 227px
   there and cut DRIVE off 16.4px below the panel's bottom edge, into a scroll
   with no affordance; at 84px the cap does not bind and `scrollHeight`
   equals `clientHeight`.

   `--dock:bar` IS THE POINT OF THE BLOCK, not a side effect. Once the deck is
   a bar the road should be sized like one, and the bar's `min(w*.55, h*1.25)`
   is what produces the 751px above; left on the sheet's `.93` the same panel
   gives 1270px over 933px, 1.36, still outside the band. Setting the token
   here is safe because NO rule in this file reads `var(--dock)` -- grep it --
   so it reaches resize() in app.js and nothing else. The sheet's own skin,
   its glass, its gutter and its `--dock-inset` arithmetic all stay exactly as
   they are; `--dock-inset` is measured off the panel's rect, not derived from
   the token, so it follows the new height by itself.

   THE TWO ARMS ARE THE LAPTOP DOCK'S OWN QUERY with `(hover:hover) and
   (pointer:fine)` swapped for `(pointer:coarse)` and landscape added, and
   they are two rather than one to stay clear of the short-landscape block at
   `(max-width:960px) and (orientation:landscape) and (max-height:540px)`.
   That block pins the deck to the top-right corner and resets `--dock:none`,
   and this block is LATER in the file, so an overlap would put `--dock:bar`
   and `flex-direction:row` on a side panel -- the fault the four resets in
   that block were written to stop. Arm 1 asks for 961px, which no
   short-landscape shape can reach; arm 2 asks for 541px of height, which none
   can reach either. Verified shape by shape: 900x500 and 844x390 report
   `--dock` none, a deck rect of [654,8,238,271] and [608,8,228,271], and a
   road of 384.00 x 501 and 348.25 x 391 -- identical to the build without
   this block. 861x600 and 900x600 take arm 2 and go 2.37 -> 0.93 and
   2.48 -> 0.97.

   `.deck-head` goes rather than folding to a zero-height row: on this build
   it holds only `BET AMOUNT`, which the touch block already hides, so in a
   column it was an invisible item paying an 8px gap and in a row it would pay
   a 12px one. The hamburger the comment 600 lines above worries about is not
   in it -- `.deck-extras` lives inside `.road`.

   `--sheet-gap:12px` against the column's 8px: the bar's own `column-gap` is
   `clamp(10px,1.2vw,18px)`, which reads 16.39px at 1366px, and 12px is what
   keeps three control groups apart across a row without the widest of them
   (DRIVE, 764px here) losing width it uses. */
/* THE THIRD ARM IS A BUG FIX, and the bug was in the two above it. A coarse
   landscape screen 744-860px wide reached neither of them -- arm 1 wants
   961px, arm 2 wants 861px -- and it is too tall for the short-landscape
   block, so it kept the full-width sheet. That was survivable until the
   stepper block below raised the bet and auto rows by 12px: measured at
   744x600, 800x600 and 860x600 the sheet's scrollHeight went 253 -> 265
   against an unchanged clientHeight of 248, and DRIVE -- the button that
   starts the round -- fell out of the bottom of the deck into a scroll nobody
   would think to look for. 800x570 was worse, 265 against 235.

   These shapes are Stage Manager windows and iPad split-screen, which is to
   say a landscape tablet with less room, and the bar is exactly what they
   want: measured after, the deck goes 258px -> 82px of a 600px screen and
   DRIVE is back inside it at all five shapes. The road gains what the deck
   gives up, which is the whole reason the bar exists.

   `min-height:541px` IS THE WHOLE SAFETY OF THIS ARM, and 481px -- which is
   what it said first -- collapsed the game. The short-landscape corner panel
   at `(max-width:960px) and (orientation:landscape) and (max-height:540px)`
   above takes a band this arm must never reach into. Both blocks target bare
   `.deck` at specificity 0,1,0 and this one is ~1100 lines later, so at 481px
   it won `--dock:bar` -- but it did NOT override the corner panel's geometry,
   `position:absolute; top:8px; right:8px; width:clamp(184px,27vw,238px)`.
   The deck stayed a 238px panel in the top-right corner while resize() read
   it as a bar across the foot, and `inset = frame.bottom - panel.top` became
   almost the whole screen.

   Measured at 900x500 with the 481px floor: deck rect [654,8,238,98],
   `--dock-inset` 492px of a 500px viewport, roadW 11.3px and road depth 9px
   -- an eleven-pixel road with 3.75px lanes, and `if(y>geometry.h)return` in
   canvas.onclick then killing lane steering everywhere below y=9, which is
   the entire screen. 800x520 and 744x490 gave the same 11.3 x 9, and 960x540
   with it. At 541px the arm stops short of the band and all four fall back to
   the corner panel they belong on.

   THE TWELVE SHAPES THIS WAS FIRST MEASURED ON ALL MISSED IT, because not one
   of them was both coarse-landscape AND 540px or shorter: 744x600, 800x600,
   860x600 and 800x570 all clear 540 and behave exactly as intended. A shape
   in the band is not synthetic -- an iPad in Stage Manager and a Chromebook
   in split screen both land there, and the two comments in this file that
   name 900x500 name it as a corner-panel shape.

   541 also lines this arm up with the glass-skin block's own `(min-height:541px)`
   arms, so a deck that becomes a bar here is a deck that gets the glass. */
@media (pointer:coarse) and (orientation:landscape) and (min-width:961px),
       (pointer:coarse) and (orientation:landscape) and (min-width:861px) and (min-height:541px),
       (pointer:coarse) and (orientation:landscape) and (min-width:744px) and (min-height:541px){
  .deck{--dock:bar;--sheet-gap:12px;flex-direction:row;align-items:center}
  .deck-head{display:none}
  .bet-row,.auto-row{flex:0 1 auto;min-width:0}
  .auto-row{grid-template-columns:auto auto}
  .auto-row>.auto-target,.auto-row>#autoBtn{grid-column:auto}
  .drive-controls{flex:1 1 0;margin-top:0;min-width:0}
}

/* THE TARGETS THAT COST THE ROAD NOTHING, and they are the two worst in the
   build. The options hamburger measures 32 x 32 at 744, 768, 820, 1024, 1133
   and 1180px wide and 35.52 x 35.52 at 1366 -- it is `clamp(32px,2.6vw,38px)`
   and never reaches its own ceiling on a tablet -- and it is the only route
   to HOW TO PLAY, FAIR PLAY, SOUND, MUSIC and RESET. The menu rows behind it
   measure 148 x 23. Both are absolutely positioned inside `.road`, so 44px
   here is free: `--dock-inset` does not move and the road keeps every pixel.
   Left at `clamp` for mice, because 38px is a signed-off size beside a 38px
   credits badge and a coarse pointer is the only thing that needs 44. */
@media (pointer:coarse){
  .deck-extras>summary{width:44px;height:44px}
  .deck-links button,.deck-links a{min-height:44px;display:flex;align-items:center}
}
/* THE STEPPERS COST 12px OF ROAD, AND THAT IS THE ARGUMENT. `min-width:40px;
   min-height:40px` in the Signal palette section gives the bet and auto
   steppers a measured 40 x 40 and the AUTO toggle a 40px height at every
   touch shape -- 4px under the floor, on the controls a player pokes at most.
   Raising them to 44 grows `.bet-row` and `.auto-target` from 50px to 54px
   each, so the deck grows 12px and the road loses 12px: 759.89 -> 747.89 at
   768x1024, 1100.08 -> 1088.08 at 1024x1366, 868.34 -> 856.34 at 744x1133,
   758.44 -> 746.44 at 1366x1024. That is 1.1-1.6% of the road, and on this
   project road is not spent lightly -- but 40x40 is below a floor, not a
   surplus, and the tablet is the shape with the most depth to give.

   `min-width:744px` is why the PORTRAIT phones are not in that list, and it
   is measured rather than picked. At 320x568 the same change costs 24px, not
   12: the `(max-width:700px) and (max-height:600px)` block puts the steppers
   at 36px, so each of the two rows gains 8px and the road goes 357 -> 333,
   6.7% of a screen already giving 36% of itself to controls. 744px is the
   narrowest iPad viewport there is, iPad mini portrait, so every phone held
   upright is untouched.

   IT DOES NOT MISS EVERY PHONE, and an earlier version of this note claimed
   it did. A phone on its SIDE is wider than 744px -- 844x390 and 900x500 both
   are -- so it takes this block and its deck grows 271 -> 283. The road there
   is not touched at all, because both shapes are on the short-landscape
   corner panel where `--dock` is `none` and `--dock-inset` stays 0px: the
   deck is a floating panel beside the road, not a bar under it, so 12px of
   panel is 12px of panel and nothing else. Measured before and after at both
   shapes: roadW, road depth and `--dock-inset` are identical. */
@media (pointer:coarse) and (min-width:744px){
  .bet-row>button,.auto-target>button{min-width:44px;min-height:44px}
  .auto-toggle{min-height:44px}
}

/* Size labels from their projected lane, not the full browser window. */
.lane-tags{--lane-angle:0rad;--label-lane-width:120px}
.lane-tags .lane-tag{padding:8px 2px 7px;transform-origin:50% 0}
.lane-tags .hot{transform:skewX(calc(-1 * var(--lane-angle)))}
.lane-tags .safe{transform:skewX(var(--lane-angle))}
.lane-label{display:block;transform:perspective(420px) rotateX(18deg);transform-origin:50% 0}
.lane-tags .lane-tag em{font-size:clamp(20px,calc(var(--label-lane-width) * .22),36px);margin:2px 0 3px}
.lane-tags .lane-tag small{font-size:clamp(8px,calc(var(--label-lane-width) * .065),11px);letter-spacing:.6px;white-space:nowrap}
.lane-tags .lane-tag b{font-size:clamp(16px,calc(var(--label-lane-width) * .15),24px);margin-top:4px}
.road>.sky-backdrop,.road>#game,.road>.car-layer{position:absolute;inset:0;z-index:0}
.road>.sky-backdrop,.road>.car-layer{pointer-events:none}

/* THE NEON BAR. One bar, three things in it, left to right: the BET AMOUNT
   panel (header, − / $value / + / ½ / 2×), the BET button, and the
   AUTO CASH OUT panel (header, − / OFF / +, AUTO PLAY). The owner's brief was
   "too overcrowded and text too big", so every role has ONE size, set once
   below as a token, and each layout only changes the numbers.

   Everything here is written `.deck `-prefixed so it beats the older layers
   above at the same specificity by source order; where an older rule is more
   specific (the gold `:active`, the `:not(:disabled):hover` lifts) the selector
   here carries one more class. The rim is a masked ::before ring rather than
   `border-image`, which ignores border-radius and paints the square corner.
   No backdrop-filter: banned on this project on measured frame-rate grounds. */

/* 1. Tokens and components, everywhere. */
.deck{
  --panel:#000000b8;--panel-line:#ffffff2e;
  --well:#0a0c0fd9;--well-line:#ffffff33;
  --key:#1a1e24;--key-line:#ffffff22;--key-hot:#262c34;
  --ink:#eef1f4;--muted:#b9c1cb;
  --head-size:11px;--row-h:46px;--key-w:46px;--key-gap:8px;--key-font:20px;
  --val-font:22px;--chip-h:40px;--chip-font:13px;
  --drive-font:28px;--drive-wait-font:20px;--drive-min:56px;
  --panel-pad:10px 12px 12px;--panel-gap:8px;
}
/* THE BAR'S TWO COLOURS. The owner, 2026-09-26: "better color for betting
   system, sometimes colors are off". Its keys wore two accents that belonged
   to neither button: the bet keys a neon mint that was neither BET's green nor
   the Safe lane's, the AUTO CASH OUT keys and its "x" a lemon that was not
   CASH OUT's gold, and AUTO PLAY the mint again. And every key that could not
   act dimmed to .35 -- the mint going to a dark bottle green and the lemon to
   olive, which is the "sometimes": it showed only once a key was at its end or
   a round was on.

   Now each panel takes the colour of the button it belongs to: the bet
   panel BET's green (#16ce4c, the Safe lane's own, see the drive buttons
   below), AUTO CASH OUT and AUTO PLAY CASH OUT's gold (#f0c14b). A key
   that cannot act is grey on a darker key at full strength, never its colour
   faded; ½ and 2× stay ink. */
.deck{--bet-tint:#16ce4c;--cash-tint:#f0c14b;--key-off:#58606a;--key-off-bg:#14171c}
/* Red at the Wild end, yellow in the middle, green at the Safe end: the lanes'
   own three colours at 35%, as a 2px ring laid over the deck's transparent
   border. Full strength, then 60%, read "too colourful" (the owner). */
.deck::before{
  content:"";position:absolute;inset:-2px;border-radius:inherit;padding:2px;pointer-events:none;z-index:0;
  background:linear-gradient(90deg,#ff405259,#ffe64059 50%,#38ed7059);
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);-webkit-mask-composite:xor;
  mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);mask-composite:exclude;
}
.deck>*{position:relative;z-index:1}

.deck>.bet-row,.deck>.auto-row{
  display:flex;flex-direction:column;align-items:stretch;gap:var(--panel-gap);padding:var(--panel-pad);margin:0;min-width:0;
  background:var(--panel);border:1px solid var(--panel-line);border-radius:16px;box-shadow:none;transform:none;
}
/* Both panels take a neutral hairline; the rim is the only colour round them. */
.deck>.bet-row,.deck>.auto-row{border-color:#ffffff26}
/* Mid-round the bet panel does not dim, and it does not shrink. The bet the
   round is riding on stays in full white in its well -- the owner, 2026-09-26,
   of a grey $1.00: "make sure dollar appear normal ... when game starts" --
   and only the keys, which cannot act until the round is over, take their
   disabled look. (It dimmed to .52 as a panel, and the locked field to .6 of
   that again.) */
body:is([data-phase=launching],[data-phase=playing],[data-phase=crashing]) .deck>.bet-row{transform:none;opacity:1;filter:none}

.deck .sec-label{
  display:block;margin:0;font:700 var(--head-size)/1.2 var(--body);letter-spacing:.16em;
  text-transform:uppercase;color:var(--muted);text-align:center;white-space:nowrap;
}

.deck .bet-stepper,.deck .auto-target{
  display:flex;align-items:stretch;align-self:stretch;gap:var(--key-gap);height:var(--row-h);min-width:0;
  padding:0;margin:0;background:none;border:0;box-shadow:none;border-radius:0;transform:none;
}
.deck .bet-stepper>button,.deck .auto-target>button{
  flex:0 0 var(--key-w);width:var(--key-w);min-width:0;height:100%;min-height:0;padding:0;
  display:grid;place-items:center;position:relative;overflow:hidden;
  border-radius:10px;background:var(--key);border:1px solid var(--key-line);box-shadow:none;
  color:var(--bet-tint);font:900 var(--key-font)/1 var(--title);letter-spacing:0;
  transition:background .14s,transform .1s;
}
#betDown::before,#betUp::before,#autoDown::before,#autoUp::before{
  content:'';position:absolute;inset:0;
  background:linear-gradient(currentColor,currentColor) center/14px 2px no-repeat;
}
#betUp::before,#autoUp::before{
  background:linear-gradient(currentColor,currentColor) center/14px 2px no-repeat,
             linear-gradient(currentColor,currentColor) center/2px 14px no-repeat;
}
#betHalf,#betDouble{color:var(--ink)}
#autoDown,#autoUp{color:var(--cash-tint)}
.deck .bet-stepper>button:not(:disabled):hover,.deck .auto-target>button:not(:disabled):hover{background:var(--key-hot)}
.deck .bet-stepper>button:not(:disabled):active,.deck .auto-target>button:not(:disabled):active{transform:scale(.94);background:#30373f}
.deck .auto-target>button::after{display:none}
.deck .bet-stepper>button:disabled,.deck .auto-target>button:disabled{opacity:1}
/* Through :is() for the ids' weight: `#autoDown,#autoUp` and `#betHalf,#betDouble`
   set each key's colour by id, and a disabled key is grey whichever it is. */
.deck :is(#betDown,#betUp,#betHalf,#betDouble,#autoDown,#autoUp):disabled{
  color:var(--key-off);background:var(--key-off-bg);border-color:#ffffff12}

.deck .bet-value,.deck .auto-value{
  flex:1 1 auto;min-width:0;height:100%;display:flex;flex-direction:row;align-items:center;justify-content:center;
  gap:0;padding:0 6px;margin:0;background:var(--well);border:1px solid var(--well-line);border-radius:10px;
  font:900 var(--val-font)/1 var(--title);color:var(--ink);box-shadow:none;transform:none;cursor:text;
  transition:border-color .14s,box-shadow .14s;
}
.deck .bet-value .unit{font:inherit;color:var(--bet-tint);flex:none;margin:0 .04em 0 0;transform:none;text-shadow:none;transition:none}
/* app.js sizes each field to its own text in `ch`, so the "$" and the "×" sit
   against the digits the way "$1.00" does in the reference. */
.deck .bet-value input,.deck .amount-entry input{
  appearance:none;width:auto;min-width:2ch;max-width:100%;height:100%;min-height:0;padding:0;margin:0;
  border:0;border-radius:0;background:none;box-shadow:none;color:inherit;font:inherit;
  text-align:center;font-variant-numeric:tabular-nums;-webkit-text-fill-color:currentColor;
}
.deck .amount-entry{display:flex;align-items:center;justify-content:center;gap:1px;height:100%;min-width:0;max-width:100%}
.deck .amount-entry input::placeholder{color:var(--ink);opacity:1}
.deck .amount-entry b{flex:none;font:inherit;color:var(--cash-tint)}
/* The focus ring goes on the well, not on a field only as wide as its digits. */
.deck input:focus-visible{outline:none;background:none}
.deck .bet-value:focus-within{border-color:var(--bet-tint);box-shadow:inset 0 0 0 1px var(--bet-tint)}
.deck .auto-value:focus-within{border-color:var(--cash-tint);box-shadow:inset 0 0 0 1px var(--cash-tint)}
.deck input:disabled{opacity:.6}
.deck .bet-value input:disabled{opacity:1}
.deck .bet-value:has(input:disabled){cursor:default}

.deck .auto-toggle{
  display:flex;flex-direction:row;align-items:center;justify-content:space-between;gap:10px;
  height:var(--chip-h);min-height:0;padding:0 8px 0 12px;margin:0;
  border-radius:10px;background:var(--well);border:1px solid var(--well-line);color:var(--ink);
  font:700 var(--chip-font)/1 var(--body);letter-spacing:.14em;text-transform:uppercase;white-space:nowrap;
  box-shadow:none;transform:none;transition:background .15s,border-color .15s,color .15s;
}
/* The knob is a positioned background layer, so it SLIDES across the track
   (background-position transitions) instead of jumping. It stays light on
   both states, the way a hardware switch does; the mint track says on. */
.deck .auto-toggle::after{
  content:"";flex:none;width:40px;height:22px;border-radius:11px;
  background:radial-gradient(circle,#e6ebf0 7px,transparent 7.5px) 0 50%/22px 22px no-repeat #2c323a;
  transition:background-position .2s cubic-bezier(.3,.8,.3,1),background-color .2s;
}
.deck .auto-toggle.on{border-color:var(--cash-tint);color:var(--cash-tint);background:#f0c14b14}
.deck .auto-toggle.on::after{background-position:18px 50%;background-color:var(--cash-tint)}
/* A softer auto panel: rounder keys, well and toggle, and a quieter label. */
.deck .auto-target>button,.deck .auto-value,.deck .auto-toggle{border-radius:12px}
.deck .auto-toggle{font-size:12px;letter-spacing:.12em;color:#d5dbe2}
.deck .auto-toggle.on{color:var(--cash-tint)}
.deck .auto-toggle:not(:disabled):hover{background:var(--key);transform:none}
.deck .auto-toggle.on:not(:disabled):hover{background:#f0c14b24}
.deck .auto-toggle:not(:disabled):active{transform:scale(.98)}

/* BET AND CASH OUT ARE THE CROCODILE TEMPLE'S BUTTON. The owner, 2026-09-26,
   with a picture of the Temple's BET: "better yellow and green colour for bets
   and bet like this font". So both take that button whole: its face, Fredoka
   Bold, in capitals spaced .06em, in its near-black green ink; a flat fill lit
   a little from the top; a 3px darker lip along the foot and a 1px light line
   under the top edge; a soft shadow under the button. In RedLine's roles BET
   is the green and CASH OUT the gold, and CASH OUT keeps the Temple's gold
   (#f0c14b). BET took the green the Temple's cash-out button turns
   (#add974) for one release, and the owner, 2026-09-27: "green color or
   betting panel should be more like green road". That green is a pale lime,
   a yellower hue than the road's, so BET is now the Safe lane's own: the
   glow road.js lights its tubes with (TUBES[2].glow, rgb(22,206,76)), with
   a lighter hover and a darker lip and lighter top line taken from it as
   the Temple's were from its green.
   The tokens are shared with hud-fx.css, whose ghost faces carry the same
   fill and lip while one button turns into the other.
   Fredoka is a round face and runs about half as wide again as the condensed
   one the sizes below were set for, so every layout's --drive-font and
   --drive-wait-font are taken at --drive-k of themselves: "CASH OUT
   $1,000.00" holds one line in the centre column at 1440 as it did, and BET's
   capitals stand a fifth of the button's height, as in the Temple's. */
.deck{
  --drive-face:'Fredoka',var(--body);--drive-ink:#1a2d10;--drive-k:.78;
  --drive-light:linear-gradient(180deg,#ffffff30,#ffffff00 55%,#0000000d);
  --drive-drop:0 10px 22px -10px #010a09b3;
  --bet-face:var(--drive-light) #16ce4c;--bet-face-hot:var(--drive-light) #2fd560;
  --bet-lip:inset 0 -3px 0 #0e8631,inset 0 1px 0 #73e294;
  --cash-face:var(--drive-light) #f0c14b;--cash-face-hot:var(--drive-light) #f5cd63;
  --cash-lip:inset 0 -3px 0 #c8912d,inset 0 1px 0 #ffe7a3;
}
.deck>.drive-controls{display:grid;align-self:stretch;align-items:stretch;margin:0;min-width:0;height:auto}
.deck .play-button,.deck .cash-button{
  width:100%;height:100%;min-height:var(--drive-min);padding:0 10px;border:0;border-radius:16px;
  display:flex;align-items:center;justify-content:center;gap:.3em;flex-wrap:wrap;
  font:700 calc(var(--drive-font) * var(--drive-k))/1.05 var(--drive-face);letter-spacing:.06em;text-transform:uppercase;
  color:var(--drive-ink);text-shadow:none;
}
/* THE MONEY ON THE BUTTONS. The owner, 2026-09-26: "dollars more visual and
   numbers on bet a little bigger, not too round". The words stay the Temple's
   Fredoka. The amount is set in the game's own heavy condensed face -- the
   multiplier's and the wells', with its long-barred "$" -- square-shouldered
   where Fredoka's figures are round (and where they were drawn at a weight of
   900 the file does not have, so the browser fattened them further), and at
   1.24 times the words, so the money is the biggest thing on the button. The
   condensed figures are narrower than Fredoka's, so every payout up to
   "CASH OUT $100,000.00" still holds one line in the centre column at 1440;
   only the $1,000,000.00 ceiling (a $1,000 bet at 1,000x) takes a second
   line there, in a button 100px tall.

   Its "$" is the figures' own near-black ink, at their full size. It was a
   deep green on BET and a bronze on CASH OUT for one release, and the owner
   (2026-09-26, of the green one): "dollar looks bad, it's opposite of what I
   want" -- lighter than the figures on a light button, so LESS visible, where
   they had asked for it to be more. hud-fx.css gives the amount's ghosts (the
   roll and the face swap) the same face. */
.deck .play-button b,.deck .cash-button b{
  font:900 1.24em/1 var(--title);letter-spacing:.01em;font-variant-numeric:tabular-nums;
}
/* On the words' baseline rather than centred on them, which would sink the
   larger figures below the words. The buttons wrap, so each is a multi-line
   flex box and `align-content` centres the line itself in the button. */
.deck .play-button,.deck .cash-button{align-items:baseline;align-content:center}
.deck .play-button{background:var(--bet-face);box-shadow:var(--bet-lip),var(--drive-drop)}
.deck .play-button:not(:disabled):hover{background:var(--bet-face-hot);filter:none}
/* CASH OUT carries the longer label ("CASH OUT $1,000.00"), so it runs at .8
   of the BET size and holds one line in the centre column. */
.deck .cash-button{
  font-size:calc(var(--drive-font) * var(--drive-k) * .8);
  background:var(--cash-face);box-shadow:var(--cash-lip),var(--drive-drop);
}
.deck .cash-button:not(:disabled):hover{background:var(--cash-face-hot);filter:none}
.deck .cash-button:disabled{opacity:.55;box-shadow:none}
.deck .play-button:disabled{opacity:.55}
body:is([data-phase=preparing],[data-phase=launching]) .deck .play-button:disabled{opacity:1}
body:is([data-phase=preparing],[data-phase=launching]) .deck .play-button{font-size:calc(var(--drive-wait-font) * var(--drive-k))}

/* 2. Phone and every touch screen: a sheet at the foot, AUTO CASH OUT on top
   (it stays through the round), the bet panel, then BET. A tablet (744px+ by
   541px+) starts here and is taken onto the bar by section 6, and a phone held
   upright is made two rows in every phase by section 3c.
   Like the laptop's bar it floats OVER the road ("this should be on road"):
   `--road-under:1` has resize() paint the asphalt and tubes on to the canvas
   bottom beneath it, each layout keeping its own road width at the sheet's
   top edge, and the fill is the laptop's glass rather than a near-opaque
   slab. The car, its speeds and the traffic still stop at the sheet (`h`). */
@media (max-width:860px), (pointer:coarse){
  .deck{
    --dock:sheet;--road-under:1;--head-size:10px;--row-h:46px;--key-w:40px;--key-gap:6px;--key-font:18px;--val-font:23px;
    --chip-h:44px;--chip-font:12px;--drive-font:28px;--drive-wait-font:18px;--drive-min:48px;
    --panel-pad:6px 8px 8px;--panel-gap:6px;
    position:absolute;top:auto;right:auto;left:50%;translate:-50% 0;transform:none;
    bottom:max(8px,env(safe-area-inset-bottom));width:min(720px,calc(100% - 20px));
    max-height:none;overflow:visible;
    display:grid;grid-template-columns:minmax(0,1fr);grid-template-areas:"autocash" "bet" "drive";grid-template-rows:auto;
    gap:6px;padding:8px;align-items:stretch;border:2px solid #0000;border-radius:20px;
    background:radial-gradient(62% 162% at 50% 4%,#0e1013e6 0%,#0b0d10dd 42%,#08090ba6 72%,#08090b66 100%);
    box-shadow:0 12px 34px -14px #000c;
  }
  /* The area is "autocash" and not "auto": `grid-area:auto` is the keyword for
     automatic placement and can never name an area. */
  .deck>.auto-row{
    grid-area:autocash;display:grid;grid-template-columns:minmax(0,1fr) auto;
    grid-template-areas:"head head" "target autoplay";gap:var(--panel-gap);
  }
  .deck .auto-row>.sec-label{grid-area:head}
  .deck .auto-row>.auto-target{grid-area:target;align-self:stretch}
  .deck .auto-row>#autoBtn{grid-area:autoplay;height:var(--row-h);min-height:0;padding:0 8px 0 10px;gap:8px}
  /* Narrow: the toggle reads AUTO beside its pill. The full "AUTO PLAY" stays
     in the span, visually hidden, so it is still the button's accessible name;
     the ::before text is given an empty alternative so it is not read twice. */
  .deck .auto-toggle span{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
  .deck .auto-toggle::before{content:"AUTO";content:"AUTO" / ""}
  .deck>.bet-row{grid-area:bet}
  .deck>.drive-controls{grid-area:drive}
  .deck .play-button,.deck .cash-button{height:auto;padding:8px 10px}
  .deck button:focus-visible{outline:2px solid #c4ffdb;outline-offset:2px}
  body:is([data-phase=preparing],[data-phase=launching],[data-phase=playing],[data-phase=crashing]) .deck{grid-template-areas:"autocash" "drive"}
}

/* 3. A narrow window 600-860px wide, or a touch screen 600-743px wide: the two
   panels side by side, BET across the foot. (Tablets from 744px up take the
   one-row bar in section 6, which overrides all of this.) */
@media (min-width:600px) and (max-width:860px), (min-width:600px) and (pointer:coarse){
  .deck{
    --head-size:11px;--chip-font:13px;--val-font:24px;--drive-font:30px;--chip-h:44px;--key-w:44px;
    grid-template-columns:minmax(0,1.15fr) minmax(0,1fr);grid-template-areas:"bet autocash" "drive drive";
    gap:10px;padding:12px;border-radius:22px;
  }
  .deck>.auto-row{display:flex;flex-direction:column}
  .deck .auto-row>#autoBtn{height:var(--chip-h);min-height:44px;padding:0 8px 0 12px;gap:10px}
  .deck .auto-toggle span{position:static;width:auto;height:auto;overflow:visible;clip-path:none}
  .deck .auto-toggle::before{content:none}
  body:is([data-phase=preparing],[data-phase=launching],[data-phase=playing],[data-phase=crashing]) .deck{grid-template-areas:"autocash autocash" "drive drive"}
}
/* Below 660px the tablet's 44px keys would leave the bet well under 100px. */
@media (min-width:600px) and (max-width:659px){
  .deck{--key-w:40px;--key-gap:4px;--val-font:20px}
}
/* 3b. MID-ROUND ON THE SHEET: once the bet panel has folded away, AUTO CASH OUT
   is ONE 46px row -- [−][well][+] and the AUTO PLAY toggle beside it -- where
   it was a header over the stepper over the toggle ("make different design so
   it does not take up as much height, maybe blocks next to each other"). The
   header's words move INTO the well as a 9px caption over the value, so the
   field still says what it is. Idle, won and lost keep the header row, which
   sits level with the bet panel's own. The phase set is the fold's, so the
   sheet is one height from preparing to crashing.

   The arms are the sheet and nothing else: a mouse window up to 860px wide
   that is not short-landscape, and a touch screen under 744px that is not
   short-landscape. The tablets' bar (coarse, 744px+ by 541px+), the 840x456
   fold and the landscape phone's side panel all fall outside them. */
@media (max-width:860px) and (pointer:fine) and (min-height:541px),
       (max-width:860px) and (pointer:fine) and (orientation:portrait),
       (max-width:599px) and (pointer:fine) and (max-aspect-ratio:1499/1000),
       (max-width:743px) and (pointer:coarse) and (min-height:541px),
       (max-width:743px) and (pointer:coarse) and (orientation:portrait){
  body:is([data-phase=preparing],[data-phase=launching],[data-phase=playing],[data-phase=crashing]) .deck>.auto-row{
    display:grid;grid-template-columns:minmax(0,1fr) auto;grid-template-areas:"target autoplay";
    align-items:stretch;gap:var(--panel-gap);
  }
  body:is([data-phase=preparing],[data-phase=launching],[data-phase=playing],[data-phase=crashing]) .deck .auto-row>.sec-label{display:none}
  body:is([data-phase=preparing],[data-phase=launching],[data-phase=playing],[data-phase=crashing]) .deck .auto-row>.auto-target{grid-area:target;align-self:stretch}
  body:is([data-phase=preparing],[data-phase=launching],[data-phase=playing],[data-phase=crashing]) .deck .auto-row>#autoBtn{grid-area:autoplay;height:var(--row-h);min-height:0}
  /* 3px of side padding, not 6: the caption is 87px and a 360px phone's well
     is 96px. */
  body:is([data-phase=preparing],[data-phase=launching],[data-phase=playing],[data-phase=crashing]) .deck .auto-value{
    flex-direction:column;gap:3px;padding:0 3px;font-size:17px;
  }
  /* The caption is decoration for sighted players: the field's accessible
     name is its own aria-label, and the "/ ''" keeps this out of it. */
  body:is([data-phase=preparing],[data-phase=launching],[data-phase=playing],[data-phase=crashing]) .deck .auto-value::before{
    content:"AUTO CASH OUT";content:"AUTO CASH OUT" / "";
    font:700 9px/1 var(--body);letter-spacing:.1em;color:var(--muted);white-space:nowrap;
  }
  body:is([data-phase=preparing],[data-phase=launching],[data-phase=playing],[data-phase=crashing]) .deck .auto-value .amount-entry{height:auto}
  body:is([data-phase=preparing],[data-phase=launching],[data-phase=playing],[data-phase=crashing]) .deck .auto-value input{height:auto}
}

/* 3c. A PHONE'S SHEET IS ONE HEIGHT IN EVERY PHASE. The owner, 2026-09-25:
   "first betting should be same length as after betting, at first only show
   BET on bottom and the minus plus line with bet amount", and "make sure after
   and before games lanes do not change". Before a round the sheet was three
   rows -- AUTO CASH OUT, the bet panel with its quick bets, BET -- and 290px
   tall at 393x695; once a round started it folded to 136px, and resize() moved
   the whole road (its far end went from 51px to 146px down the screen).

   Now it is two rows in every phase. Before a round: [−][BET AMOUNT $1.00][+]
   [½][2×] over BET, with the header moved into the well as a caption, the way
   3b does it for AUTO CASH OUT, and no quick bets. Mid-round: 3b's one-row AUTO
   CASH OUT over CASH OUT. Both rows are one 46px stepper in a 62px panel, so
   the sheet measures 136px either way and the road never moves.

   AUTO CASH OUT and AUTO PLAY show mid-round, where the target has always been
   live, and also between rounds while auto play is armed, so the toggle that
   stops it never disappears between the rounds it starts.

   Phones only: the sheet's arms from 3b below 600px, where the deck is a
   single column, and any window below 600px that is not at least 3:2 --
   near-square, too narrow for section 4's side panel beside a road. The
   600-860px sheet keeps its two panels side by side. */
@media (max-width:599px) and (min-height:541px),
       (max-width:599px) and (orientation:portrait),
       (max-width:599px) and (max-aspect-ratio:1499/1000){
  .deck{grid-template-areas:"bet" "drive"}
  .deck .bet-row>.sec-label{display:none}
  /* Wrapped rather than turned into a column: the caption takes a whole line
     of its own, and the "$" and the amount stay side by side under it. */
  .deck .bet-value{flex-wrap:wrap;align-content:center;row-gap:3px}
  .deck .bet-value::before{
    content:"BET AMOUNT";content:"BET AMOUNT" / "";flex:0 0 100%;text-align:center;
    font:700 9px/1 var(--body);letter-spacing:.1em;color:var(--muted);white-space:nowrap;
  }
  .deck .bet-value input{height:auto}
  /* 3b's one-row AUTO CASH OUT without its phase condition, because on a phone
     it only ever shows in that form now. */
  .deck>.auto-row{display:none;grid-template-columns:minmax(0,1fr) auto;grid-template-areas:"target autoplay";align-items:stretch}
  .deck .auto-row>.sec-label{display:none}
  .deck .auto-row>#autoBtn{height:var(--row-h);min-height:0}
  .deck .auto-value{flex-direction:column;gap:3px;padding:0 3px;font-size:17px}
  .deck .auto-value::before{
    content:"AUTO CASH OUT";content:"AUTO CASH OUT" / "";
    font:700 9px/1 var(--body);letter-spacing:.1em;color:var(--muted);white-space:nowrap;
  }
  .deck .auto-value .amount-entry,.deck .auto-value input{height:auto}
  body:is([data-phase=preparing],[data-phase=launching],[data-phase=playing],[data-phase=crashing]) .deck>.auto-row{display:grid}
  /* Separate rules, so a browser without :has() drops only these. */
  .deck:has(#autoBtn.on){grid-template-areas:"autocash" "drive"}
  .deck:has(#autoBtn.on)>.auto-row{display:grid}
  .deck:has(#autoBtn.on)>.bet-row{display:none}
}

/* 4. A short, narrow landscape phone keeps a side panel: more road that way.
   It is not docked, so nothing is painted under it, and it keeps the solid
   fill the sheets had (restated, because section 2 now paints them glass).

   ONLY WHERE THE ROAD STILL HAS ROOM BESIDE IT: 600-739px wide, or below that
   a screen at least half again as wide as it is tall -- which every phone on
   its side is (568x320, 640x360 and 667x375 are all 16:9). A near-square
   window used to land here as well, because "landscape" is only width over
   height: the owner's in-app browser at 463x459 put the 288px panel over the
   road and left the road 167px wide with the SAFE lane under the panel. Below
   600px such a window takes the phone's two-row sheet (3c) instead, and the
   short-landscape block in the older half of this file, the glass look, 3b's
   one-row AUTO CASH OUT and the result's side-panel width follow the same two
   arms. */
@media (min-width:600px) and (max-width:739px) and (max-height:540px) and (orientation:landscape),
       (max-width:599px) and (max-height:540px) and (min-aspect-ratio:3/2){
  .deck{
    --dock:none;--road-under:0;--head-size:0;--row-h:46px;--key-w:40px;--key-gap:6px;--val-font:18px;
    background:radial-gradient(70% 140% at 50% 0%,#0f1114ee,#0b0d10e6 60%,#08090bd9);box-shadow:0 10px 30px #000a;
    --chip-h:44px;--chip-font:11px;--panel-pad:6px;--drive-min:48px;--drive-font:28px;--drive-wait-font:18px;
    top:8px;right:max(8px,env(safe-area-inset-right));bottom:auto;left:auto;translate:none;
    width:288px;padding:8px;gap:6px;
    grid-template-columns:minmax(0,1fr);grid-template-areas:"autocash" "bet" "drive";
    max-height:calc(100dvh - 16px);overflow:auto;border:1px solid var(--panel-line);border-radius:16px;
  }
  .deck::before{display:none}
  .deck .sec-label{display:none}
  .deck>.auto-row{display:grid;grid-template-columns:minmax(0,1fr) auto;grid-template-areas:"target autoplay"}
  .deck .auto-row>#autoBtn{height:var(--row-h);min-height:0}
  body:is([data-phase=preparing],[data-phase=launching],[data-phase=playing],[data-phase=crashing]) .deck{grid-template-areas:"autocash" "drive"}
}
/* Where the stepper row has no room for "AUTO" beside the pill (a 320px phone,
   the 288px side panel) the label stacks over a smaller pill, so the cash-out
   field keeps room for "2.50×". */
@media (max-width:359px),
       (min-width:600px) and (max-width:739px) and (max-height:540px) and (orientation:landscape),
       (max-width:599px) and (max-height:540px) and (min-aspect-ratio:3/2){
  .deck .auto-row>#autoBtn{flex-direction:column;justify-content:center;gap:5px;padding:0 7px}
  .deck .auto-toggle span{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
  .deck .auto-toggle::before{content:"AUTO";content:"AUTO" / "";font-size:10px;letter-spacing:.12em;margin-right:-.12em}
  .deck .auto-toggle::after{width:32px;height:18px;border-radius:9px;background-image:radial-gradient(circle,#e6ebf0 6px,transparent 6.5px);background-size:18px 18px}
  .deck .auto-toggle.on::after{background-position:14px 50%}
  /* Five boxes in the bet row: "$1000.00" at 18px is 72px of text, and the
     well here is 80px (the side panel) to 86px (320px). */
  .deck{--key-w:40px;--key-gap:4px;--val-font:18px}
  .deck .bet-value,.deck .auto-value{padding:0 2px}
}

/* 5. Wide, short landscape (a phone on its side, a short window): the bar,
   compact. It restates its own position because a fine-pointer window
   861-960px wide and 540px or less tall reaches it without section 2.
   On a screen this short the bar was a quarter of the height (the owner:
   "on this small screen the betting system seems too big"), so it drops the
   panel headers, runs one 34px row per panel -- the auto panel as the phone's
   [-][OFF][+][AUTO] -- and keeps the chips only from 500px tall up. It
   floats over the road in the laptop's glass, the road painted on beneath
   it (`--road-under:1`; its width at the bar's edge is this layout's own). */
@media (min-width:740px) and (max-height:540px) and (pointer:coarse),
       (min-width:740px) and (max-width:960px) and (max-height:540px){
  .deck{
    --dock:bar;--road-under:1;--row-h:34px;--key-w:34px;--key-gap:5px;--chip-h:26px;--head-size:10px;--chip-font:12px;--val-font:20px;
    --drive-font:20px;--drive-wait-font:15px;--drive-min:0px;--panel-pad:4px 6px;--panel-gap:4px;
    position:absolute;top:auto;right:auto;left:50%;translate:-50% 0;transform:none;
    bottom:max(8px,env(safe-area-inset-bottom));width:calc(100% - 24px);max-height:none;overflow:visible;
    display:grid;grid-template-columns:minmax(0,1.4fr) minmax(0,1fr) minmax(0,1.15fr);
    grid-template-areas:"bet drive autocash";grid-template-rows:auto;align-items:stretch;
    gap:10px;padding:6px 8px;border:2px solid #0000;border-radius:18px;
    background:radial-gradient(62% 162% at 50% 4%,#0e1013e6 0%,#0b0d10dd 42%,#08090ba6 72%,#08090b66 100%);
    box-shadow:0 12px 34px -14px #000c;
  }
  .deck .sec-label{display:none}
  .deck>.bet-row{grid-area:bet}
  .deck>.drive-controls{grid-area:drive}
  .deck>.auto-row{grid-area:autocash;display:grid;grid-template-columns:minmax(0,1fr) auto;grid-template-areas:"target autoplay";gap:var(--panel-gap);align-content:center}
  .deck .auto-row>.auto-target{grid-area:target;align-self:stretch}
  .deck .auto-row>#autoBtn{grid-area:autoplay;height:var(--row-h);min-height:0;flex-direction:column;justify-content:center;gap:4px;padding:0 7px}
  .deck .auto-toggle span{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
  .deck .auto-toggle::before{content:"AUTO";content:"AUTO" / "";font-size:10px;line-height:1;letter-spacing:.12em;margin-right:-.12em}
  .deck .auto-toggle::after{width:32px;height:18px;border-radius:9px;background-image:radial-gradient(circle,#e6ebf0 6px,transparent 6.5px);background-size:18px 18px}
  .deck .auto-toggle.on::after{background-position:14px 50%}
  .deck .play-button,.deck .cash-button{height:100%;padding:0 10px}
  .deck .bet-value,.deck .auto-value{padding:0 4px}
  #toast{bottom:calc(var(--dock-inset,0px) + 14px)}
  body:is([data-phase=preparing],[data-phase=launching],[data-phase=playing],[data-phase=crashing]) .deck{
    grid-template-columns:minmax(0,1.4fr) minmax(0,1fr);grid-template-areas:"drive autocash";
  }
}

/* 740-799px wide (a Galaxy-sized phone on its side): the auto well is 75px,
   so the digits step down a size to hold "1000.00×". */
@media (min-width:740px) and (max-width:799px) and (max-height:540px){
  .deck{--val-font:17px}
  .deck .bet-value,.deck .auto-value{padding:0 2px}
}

/* 6. THE BAR: the laptop, and every tablet -- a coarse pointer 744px or more
   wide and 541px or more tall, either way up ("on iPad, overlay like on
   laptop"). LAST, so it wins.

   It floats over the foot of the screen and the road runs on UNDER it to the
   canvas bottom: `--road-under:1`, read by resize() in app.js. The laptop also
   declares `--lane-fit:1`, which fixes the road's foot at the original 960px
   ("lanes' width shouldn't match betting system width"); a tablet does not, and
   keeps its own signed-off road width at the bar's top edge.

   THE BAR IS CENTRED AS A WHOLE, ALWAYS: `left:50%; translate:-50% 0` and
   nothing else ("betting panel should always be centered as a whole"). BET
   sits on the centre line because the two flanks are the SAME width, not
   because anything shifts the bar. The columns are lengths:

     --bet-w   the bet panel: the window's share of 1 : .86 : 1, capped at
               `--flank-max` (320px) and never below `--bet-min`, which is
               what the panel's five boxes need with "$1000.00" in the well
     --auto-w  the AUTO CASH OUT panel: the same width as the bet panel. At
               320px its row sits centred with room either side, the
               composition of the approved 1040px bar at a slightly smaller
               scale; the 200px panel it replaces was "too little and cramped
               right side"
     --drive-w BET: what the two flanks leave, capped at `--drive-max`

   So the bar is `max-content` -- about 983px at 1440 -- and neither end can
   pass `--bar-margin` at any width. Only the narrowest tablets (744-899px),
   below, give up equal flanks. */
@media (min-width:961px) and (hover:hover) and (pointer:fine),
       (min-width:861px) and (min-height:541px) and (hover:hover) and (pointer:fine),
       (pointer:coarse) and (min-width:744px) and (min-height:541px),
       (pointer:coarse) and (min-width:961px){
  .deck{
    --dock:bar;--lane-fit:1;--road-under:1;
    --head-size:10px;--row-h:36px;--key-w:36px;--key-gap:5px;--key-font:16px;
    --val-font:clamp(20px,1.55vw,24px);--chip-h:28px;--chip-font:11px;
    --drive-font:clamp(26px,2.5vw,36px);--drive-wait-font:clamp(18px,1.7vw,24px);--drive-min:0px;
    --panel-px:10px;--panel-pad:6px var(--panel-px) 8px;--panel-gap:4px;
    --bar-margin:20px;--bar-px:10px;--bar-gap:10px;
    /* BET's cap is the approved 1040px bar's BET, 299.48px. The bet well's
       floor holds "$1000.00" (4.02em of digits, unit, padding and border,
       measured) -- the largest bet there is. */
    --flank-max:320px;--drive-max:calc(996px*.86/2.86);
    --bet-well:calc(4.1*var(--val-font) + 14px);
    --bet-min:calc(4*var(--key-w) + 4*var(--key-gap) + var(--bet-well) + 2*var(--panel-px) + 2px);
    --bar-avail:calc(100vw - 2*var(--bar-margin) - 2*var(--bar-px) - 4px - 2*var(--bar-gap));
    --bet-w:clamp(var(--bet-min),var(--bar-avail)/2.86,var(--flank-max));
    --auto-w:var(--bet-w);
    --drive-w:min(var(--drive-max),var(--bar-avail) - var(--bet-w) - var(--auto-w));
    /* The OFF well: 150px, shrinking only as far as a floor that holds
       "1000.00×" (4.75em with its padding and border, measured). */
    --auto-well:150px;--auto-well-min:max(96px,calc(4.8*var(--val-font)));
    position:absolute;z-index:4;left:50%;right:auto;top:auto;transform:none;translate:-50% 0;
    bottom:clamp(12px,1.8vh,20px);
    width:max-content;max-width:none;max-height:none;overflow:visible;
    display:grid;grid-template-columns:var(--bet-w) var(--drive-w) var(--auto-w);
    grid-template-areas:"bet drive autocash";grid-template-rows:auto;
    gap:var(--bar-gap);padding:8px var(--bar-px);align-items:stretch;
    border:2px solid #0000;border-radius:22px;
    background:radial-gradient(62% 162% at 50% 4%,#0e1013e6 0%,#0b0d10dd 42%,#08090ba6 72%,#08090b66 100%);
    box-shadow:0 12px 34px -14px #000c;
  }
  .deck>.bet-row{grid-area:bet}
  .deck>.drive-controls{grid-area:drive;margin:0}
  .deck>.auto-row{grid-area:autocash;display:flex;flex-direction:column}
  .deck .auto-row>.auto-target{align-self:stretch}
  /* The [−][OFF][+] row sits centred in its panel with the well at its own
     width, not stretched across the panel; the AUTO PLAY row below spans it. */
  .deck .auto-target{justify-content:center}
  .deck .auto-value{flex:0 1 var(--auto-well);min-width:var(--auto-well-min)}
  .deck .auto-row>#autoBtn{align-self:stretch;height:var(--chip-h);min-height:0;padding:0 8px 0 12px;gap:10px}
  .deck .auto-toggle span{position:static;width:auto;height:auto;overflow:visible;clip-path:none}
  .deck .auto-toggle::before{content:none}
  /* `align-content`: where BET is narrow enough for "$1,000.00" to wrap under
     its word, the two lines sit together in the middle of the button rather
     than each taking half its height. One line is unaffected. */
  .deck .play-button,.deck .cash-button{height:100%;min-height:0;padding:0 10px;align-content:center}
  #toast{bottom:calc(var(--dock-inset,0px) + 14px)}
}
/* A laptop 861-960px wide: five boxes leave the bet well 66px at 40px keys,
   short of "$1000.00". Narrower keys, smaller digits. */
@media (min-width:861px) and (max-width:960px) and (min-height:541px) and (hover:hover) and (pointer:fine){
  .deck{--key-w:36px;--key-gap:4px;--val-font:18px}
  .deck .bet-value,.deck .auto-value{padding:0 4px}
}
/* A short laptop window: the bar trims its rows. Mouse-sized only -- the iPad
   (coarse) keeps its touch targets below. Keys stay 36px wide, the floor the
   betting test holds laptops to. */
@media (min-width:961px) and (max-height:700px) and (hover:hover) and (pointer:fine),
       (min-width:861px) and (min-height:541px) and (max-height:700px) and (hover:hover) and (pointer:fine){
  .deck{
    --row-h:34px;--key-w:36px;--chip-h:28px;--chip-font:11px;--head-size:9px;
    --panel-px:8px;--panel-pad:4px var(--panel-px) 6px;--panel-gap:4px;--drive-font:clamp(22px,2.2vw,30px);
    --bar-px:8px;padding:6px var(--bar-px);
  }
}
@media (min-width:961px) and (max-height:600px) and (hover:hover) and (pointer:fine),
       (min-width:861px) and (min-height:541px) and (max-height:600px) and (hover:hover) and (pointer:fine){
  .deck .sec-label{display:none}
}
/* THE TABLET, both ways up: the laptop's bar at touch sizes -- 44px keys,
   rows, chips and toggle -- over its own road (`--lane-fit:0`), which still
   runs on under the glass. The flanks are equal as on the laptop, about 320px
   (the bet panel's own floor at 44px keys is 314-326px), with a 160px OFF
   well; BET takes the rest up to 340px. One row in EVERY phase, as on the
   laptop: the touch layouts above fold the bet panel away once a round starts
   (`.deck>:not(.drive-controls):not(.auto-row){display:none}` near the
   phase-fold comment, and the sheet's own "autocash drive" areas), and a
   tablet takes neither -- the panel stays, dimmed and disabled like the
   laptop's, so the bar is one height from idle to lost and resize() never
   hears about a phase. The fold's selector is (0,4,1), and so is the
   `.bet-row` rule here; this one is later, and that is what it relies on.

   PORTRAIT stays `--dock:sheet` for resize(): the road there keeps the touch
   layout's `.93` width (capped at `h*1.25`); landscape keeps the bar's
   `min(w*.55, h*1.25)`. Both land in the signed-off 0.60-0.95 width:depth
   band. The gutter clears an iPad's 20px home indicator. */
@media (pointer:coarse) and (min-width:744px) and (min-height:541px),
       (pointer:coarse) and (min-width:961px){
  .deck{
    --lane-fit:0;
    --row-h:44px;--key-w:44px;--key-gap:6px;--key-font:18px;--chip-h:44px;--chip-font:12px;
    --head-size:10px;--val-font:clamp(19px,1.5vw,22px);
    --drive-font:clamp(30px,3.1vw,44px);--drive-wait-font:clamp(18px,1.9vw,26px);
    --panel-px:10px;--panel-gap:6px;--bar-gap:12px;
    --drive-max:340px;
    --auto-well:160px;--auto-well-min:max(110px,calc(4.8*var(--val-font)));
    bottom:max(clamp(12px,1.8vh,20px),env(safe-area-inset-bottom,0px));
  }
  body:is([data-phase=preparing],[data-phase=launching],[data-phase=playing],[data-phase=crashing]) .deck{
    grid-template-columns:var(--bet-w) var(--drive-w) var(--auto-w);grid-template-areas:"bet drive autocash";
  }
  body:is([data-phase=preparing],[data-phase=launching],[data-phase=playing],[data-phase=crashing]) .deck>.bet-row:not(.drive-controls,.auto-row){display:flex}
}
@media (pointer:coarse) and (orientation:portrait) and (min-width:744px) and (min-height:541px){
  .deck{--dock:sheet}
}
/* 744-899px (iPad mini to iPad Pro 11 upright, a landscape tablet in Stage
   Manager): two 44px-key bet panels and BET do not fit, so equal flanks are
   given up here and only here. The keys go to the phone's 40px width (still
   44px tall), the digits step down and the margins tighten; the bet panel is
   exactly as wide as its content, the auto panel is at least 240px with a
   130px well, and BET takes the rest: 180px at 744, 204px at 768, 270px at
   834. The bar is still centred as a whole, so BET sits half the flanks'
   difference (16px) right of centre, which is accepted. 28px type and 6px
   padding keep CASH OUT $1,000,000.00 inside BET on two lines. */
@media (pointer:coarse) and (min-width:744px) and (max-width:899px) and (min-height:541px){
  .deck{
    --key-w:40px;--key-gap:4px;--val-font:18px;--panel-px:6px;
    --bar-margin:8px;--bar-px:8px;--bar-gap:8px;--drive-font:28px;
    --bet-well:calc(4.1*var(--val-font) + 8px);--bet-w:var(--bet-min);
    --auto-well:130px;--auto-well-min:96px;
    --auto-w:max(240px,calc(2*var(--key-w) + 2*var(--key-gap) + var(--auto-well) + 2*var(--panel-px) + 2px));
  }
  .deck .bet-value,.deck .auto-value{padding:0 3px}
  .deck .play-button,.deck .cash-button{padding:0 6px}
}
/* 6b. THE BET PANEL IN TWO ROWS, BESIDE AUTO CASH OUT. The owner, 2026-09-26:
   "remove quick bets". Where the bet panel stands beside the AUTO CASH OUT
   panel -- the laptop's and the tablets' bar, and the 600-860px sheet -- the
   quick bets were its second row, level with AUTO PLAY, and without them the
   panel was a header and one row over an empty band. ½ and 2× take that row
   now, half the panel each, so the two panels match row for row:

       BET AMOUNT        AUTO CASH OUT
       [−][$1.00][+]     [−][ OFF ][+]
       [ ½ ][ 2× ]       [AUTO PLAY ●]

   The rows are the auto panel's own (--row-h over --chip-h, --panel-gap
   apart), so neither panel is taller than before and the bar, the sheet and
   the road under them do not move. The panel keeps its width; the well takes
   the room ½ and 2× leave. The phones' sheet, the fold, the side panel and
   the short landscape bar keep their one row. */
@media (min-width:961px) and (hover:hover) and (pointer:fine),
       (min-width:861px) and (min-height:541px) and (hover:hover) and (pointer:fine),
       (pointer:coarse) and (min-width:744px) and (min-height:541px),
       (pointer:coarse) and (min-width:961px),
       (min-width:600px) and (max-width:860px) and (pointer:fine) and (min-height:541px),
       (min-width:600px) and (max-width:860px) and (pointer:fine) and (orientation:portrait),
       (min-width:600px) and (max-width:743px) and (pointer:coarse) and (min-height:541px),
       (min-width:600px) and (max-width:743px) and (pointer:coarse) and (orientation:portrait){
  .deck .bet-stepper{
    display:grid;grid-template-columns:var(--key-w) minmax(0,1fr) minmax(0,1fr) var(--key-w);
    grid-template-rows:var(--row-h) var(--chip-h);gap:var(--panel-gap) var(--key-gap);height:auto;
  }
  .deck .bet-stepper>.bet-value{grid-column:2/4}
  .deck .bet-stepper>#betHalf{grid-column:1/3;width:auto}
  .deck .bet-stepper>#betDouble{grid-column:3/5;width:auto}
}


/* 7. WIN AND CRASH, with no card. The owner's references: "YOU WIN" over the
   payout in heavy white type with a green lip and green sparkles bursting
   round it; one slanted word, CRASHED, in white with a red glow and red shards.
   The old rotated plate is taken apart here rather than above: its padding,
   border, outline, rotation, shadows and the ::before flash / ::after shine
   all go. The block sits at the centre of the ROAD above the dock -- half the
   dock's inset up from the screen's centre -- on the bar as on the sheet
   (the readout is hidden while it shows, so there is room); the side panel
   has no inset and stays at 50%, left of the panel.

   v5: THE BLOCK HAS NO ENTRANCE OF ITS OWN ANY MORE. Its parts arrive one
   after another, in the manner of the owner's Crocodile Temple ("that level of
   animations"): the letters of the eyebrow jump up one by one, the payout
   counts up and stamps, the line under it rises in at the stamp; CRASHED
   jumps up into place, whole, and its line rises in under it. The win's
   letters and the count are drawn by result-fx.js in elements of its own
   (`fx-*`, aria-hidden) over app.js's text, which goes transparent only while
   they run; the timeline is written out at the head of that file.
   `animation:none!important` because the Signal section kills `.outcome`
   animation with !important and the base rule still names the old plate's
   stamp. Nothing here repaints once it has landed. */
.outcome,.outcome.won{
  background:none;border:0;outline:0;box-shadow:none;padding:0;rotate:0deg;
  min-width:0;width:max-content;max-width:min(90vw,900px);
  text-align:center;pointer-events:none;--plate-r:0;
  top:var(--result-centre);
  --result-centre:calc(50% + var(--road-top,0px)/2 - var(--dock-inset,0px)/2);
  --word-size:clamp(56px,7.5vw,108px);
  --line-size:clamp(12px,1vw,16px);
}
.outcome::before,.outcome::after,.outcome.won::after{display:none}
.outcome small::before,.outcome small::after{display:none}
.outcome{animation:none!important}

/* THE WIN, IN TIERS. app.js writes `data-tier` off the multiplier the line
   under the payout prints: 1 under 2x, 2 from 2x, 3 from 5x, 4 from 20x, and
   max at the 1,000x cap, and names the eyebrow YOU WIN, BIG WIN (3), HUGE WIN
   (4) or MAX WIN. The owner likes this win, so its look is untouched -- mint
   YOU WIN over white numerals on a green lip, CASHED OUT AT n.nnx, mint
   sparks -- and only its timing is new:

       0 ms  the eyebrow's letters jump up, 25ms apart (result-fx.js)
     120     the payout appears and counts up from $0.00: .55s at tier 1,
             .8s at 2, 1.2s at 3, 1.4s at 4 and max (result-fx.js)
     --stamp (120ms + the count) the payout stamps, a sheen crosses it, the
             sparks burst, CASHED OUT rises in; rays from tier 2 up, a
             counter-turning set and an afterglow from tier 3 up. Nothing
             flies to the credits badge: its number counts up by itself

   --stamp is the same sum as TIERS in result-fx.js (the tests hold them
   together). The rays are the one light effect, and only for the bigger wins. */
.outcome.won{
  background:radial-gradient(60% 55% at 50% 50%,#38ed7026,#0000 70%);
  --stamp:.67s;--rays-o:.34;
  --win-lip:0 2px 0 #9df5b8,0 5px 0 #2fbf5d,0 8px 0 #146b32,0 12px 30px #38ed7066;
}
.outcome.won[data-tier="2"]{--stamp:.92s}
.outcome.won[data-tier="3"]{--stamp:1.32s;--rays-o:.44}
.outcome.won:is([data-tier="4"],[data-tier="max"]){--stamp:1.52s;--rays-o:.54}
.outcome.won small{
  display:block;position:relative;margin:0 0 .02em;font:900 var(--word-size)/1 var(--title);letter-spacing:.02em;
  color:var(--mint);text-shadow:0 0 18px #38ed7080,0 2px 0 #0a3d1c;
}
/* The reference's 3D lip, done in stacked shadows under white numerals. The
   count (`fx-count`) is drawn in the same face and lip over the payout, which
   is transparent while it runs, and in tabular figures like the payout, so
   the hand-back at the stamp is invisible. */
.outcome.won strong,.outcome.won fx-count{
  font:900 clamp(90px,12vw,172px)/.95 var(--title);color:#f6fff8;letter-spacing:-.01em;white-space:nowrap;
  text-shadow:var(--win-lip);
}
.outcome.won strong{
  position:relative;transform-origin:50% 62%;
  animation:win-payout-in .18s ease-out .12s both,win-stamp .24s cubic-bezier(.3,.6,.3,1) var(--stamp);
}
.outcome.won.long strong{font-size:clamp(64px,8vw,116px)}
.outcome.won fx-count{position:absolute;inset:0;font-size:inherit;pointer-events:none}
.outcome.won.is-counting strong{color:transparent;text-shadow:none}
.outcome.won>span{
  display:block;margin-top:.9em;font:700 clamp(12px,1vw,16px)/1.2 var(--body);letter-spacing:.22em;
  color:#bfffcf;text-transform:uppercase;text-shadow:0 1px 2px #000c;
  animation:win-line-in .34s cubic-bezier(.2,.7,.3,1) var(--stamp) both;
}
@keyframes win-payout-in{from{opacity:0;scale:.86}to{opacity:1;scale:1}}
/* Up to 1.14, back past its size with a slight squash, home: 240ms. */
@keyframes win-stamp{0%{scale:1}34%{scale:1.14}66%{scale:1.01 .96}100%{scale:1}}
@keyframes win-line-in{from{opacity:0;translate:0 .8em}to{opacity:1;translate:0 0}}

/* The eyebrow's letters (result-fx.js), laid exactly where app.js's word is
   drawn: each rises from half a line below, lands a touch high and settles
   with a short squash. The word itself is transparent while they move. */
.outcome.won.is-jumping small{color:transparent;text-shadow:none}
.outcome.won fx-glyphs{position:absolute;inset:0;pointer-events:none}
.outcome.won fx-glyph{
  position:absolute;top:0;color:var(--mint);text-shadow:0 0 18px #38ed7080,0 2px 0 #0a3d1c;
  transform-origin:50% 100%;animation:glyph-jump .34s backwards;animation-delay:calc(var(--i) * 25ms);
}
@keyframes glyph-jump{
  0%{opacity:0;transform:translateY(.5em) scale(.94,1.08);animation-timing-function:cubic-bezier(.2,.7,.35,1)}
  55%{opacity:1;transform:translateY(-.08em) scale(.98,1.03);animation-timing-function:cubic-bezier(.5,0,.7,.5)}
  78%{opacity:1;transform:translateY(0) scale(1.06,.92);animation-timing-function:cubic-bezier(.2,.6,.3,1)}
  100%{opacity:1;transform:none}
}

/* THE RAYS, from tier 2: soft mint light behind the block, a static conic
   fill faded out by a radial mask, that fades in at the stamp and turns a
   little as it goes (transform and opacity only). More, brighter and joined
   by a counter-turning set from tier 3, where an afterglow also lingers:
   a soft mint pool that rises at the stamp and settles, and then holds still.
   It never reaches the edges of the screen. */
.outcome fx-rays,.outcome fx-glow{
  position:absolute;left:50%;top:58%;z-index:-1;translate:-50% -50%;pointer-events:none;display:none;
}
.outcome fx-rays{
  width:170%;aspect-ratio:1;opacity:0;
  background:repeating-conic-gradient(#8dffaa00 0deg,#8dffaa 4deg 7deg,#8dffaa00 11deg 30deg);
  -webkit-mask-image:radial-gradient(closest-side,#000 16%,#0008 44%,#0000 70%);
  mask-image:radial-gradient(closest-side,#000 16%,#0008 44%,#0000 70%);
}
.outcome.won:not([data-tier="1"]) fx-rays:first-of-type{
  display:block;animation:win-rays 2.6s cubic-bezier(.2,.7,.3,1) var(--stamp) both;
}
.outcome.won:is([data-tier="3"],[data-tier="4"],[data-tier="max"]) fx-rays{
  background:repeating-conic-gradient(#8dffaa00 0deg,#8dffaa 4deg 7deg,#8dffaa00 11deg 24deg);
}
.outcome.won:is([data-tier="3"],[data-tier="4"],[data-tier="max"]) fx-rays+fx-rays{
  display:block;width:135%;rotate:9deg;--rays-turn:-22deg;
  background:repeating-conic-gradient(#ffffff00 0deg,#d9ffe6 3deg 5deg,#ffffff00 8deg 36deg);
  animation:win-rays 2.4s cubic-bezier(.2,.7,.3,1) calc(var(--stamp) + .08s) both;
}
.outcome fx-glow{
  width:140%;height:115%;border-radius:50%;opacity:.42;
  background:radial-gradient(closest-side,#38ed7038,#38ed7000);
}
.outcome.won:is([data-tier="3"],[data-tier="4"],[data-tier="max"]) fx-glow{
  display:block;animation:win-glow 2.2s ease-out var(--stamp) both;
}
@keyframes win-rays{
  0%{opacity:0;transform:scale(.62) rotate(0deg)}
  14%{opacity:var(--rays-o)}
  60%{opacity:calc(var(--rays-o) * .7)}
  100%{opacity:0;transform:scale(1.08) rotate(var(--rays-turn,30deg))}
}
@keyframes win-glow{0%{opacity:0;transform:scale(.7)}16%{opacity:1;transform:scale(1.04)}100%{opacity:.42;transform:none}}

/* The sparks travel in container units, so their end points are fractions of
   the headline block whatever size it is set at: 50cqw is its edge. On a win
   they wait for the stamp. */
.outcome .burst{position:absolute;inset:0;pointer-events:none;container-type:size;--spark-k:1.3;--spark-ry:1}
.outcome .burst i{
  position:absolute;left:50%;top:50%;
  width:calc(var(--s,18px) * var(--spark-k));height:calc(var(--s,18px) * var(--spark-k));translate:-50% -50%;
  clip-path:polygon(50% 0,58% 42%,100% 50%,58% 58%,50% 100%,42% 58%,0 50%,42% 42%);
  background:var(--mint);opacity:0;
  animation:spark .9s ease-out both;animation-delay:var(--d,0s);
}
.outcome.won .burst i{animation-delay:calc(var(--stamp) + var(--d,0s))}
@keyframes spark{
  0%{opacity:0;transform:translate(0,0) scale(.2)}
  35%{opacity:1}
  100%{opacity:.85;transform:translate(var(--x),calc(var(--y) * var(--spark-ry))) scale(1) rotate(90deg)}
}
/* Win: just above the text, beside both lines, and below -- never over the
   numerals. The block sits high on the road now, so nothing flies far up
   into the lane labels, and below they stop at 72% of the block's height,
   short of the bar. They are in container units, so they grow with the type.
   They land upright (a quarter turn in flight), so none reads as a "×". The
   win uses the first ten of the fourteen; the crash throws none. */
.outcome.won .burst i:nth-child(n+11){display:none}
.outcome .burst i:nth-child(1){--x:-44cqw;--y:-62cqh;--s:22px;--d:0s}
.outcome .burst i:nth-child(2){--x:30cqw;--y:-66cqh;--s:14px;--d:.06s}
.outcome .burst i:nth-child(3){--x:-8cqw;--y:-60cqh;--s:12px;--d:.12s}
.outcome .burst i:nth-child(4){--x:58cqw;--y:-40cqh;--s:26px;--d:.02s}
.outcome .burst i:nth-child(5){--x:-60cqw;--y:-4cqh;--s:18px;--d:.1s}
.outcome .burst i:nth-child(6){--x:60cqw;--y:16cqh;--s:16px;--d:.16s}
.outcome .burst i:nth-child(7){--x:-40cqw;--y:64cqh;--s:20px;--d:.04s}
.outcome .burst i:nth-child(8){--x:36cqw;--y:70cqh;--s:12px;--d:.2s}
.outcome .burst i:nth-child(9){--x:8cqw;--y:72cqh;--s:10px;--d:.25s}
.outcome .burst i:nth-child(10){--x:-62cqw;--y:-36cqh;--s:14px;--d:.18s}

/* THE CRASH: YOU WIN's twin, in red. The owner found the slam too brutal,
   the cartoon too playful and the wipe too much like an appearance; for v5 he
   asked for the letters to jump in like the win's, then (2026-09-26) for the
   crash to be the cash-out's kind, "soft, not too crazy", then "just appear
   crashed ... you can say at what multiplier crashed like win", then "remove
   rebet", so no button stands under it: the next round starts from BET, as it
   always could. So the word is YOU WIN's eyebrow in every way but its colour
   and its text -- YOU WIN's size (`--word-size`; larger only on a short
   landscape screen, where YOU WIN is set small under the payout), its flat
   fill over a soft glow and a 2px lip, its soft pool of light behind the
   block. Under it, CRASHED AT 1.84x, the multiplier the round ended at
   (app.js), is the win's CASHED OUT AT line in the crash's pale red, and it
   rises in the way that line does.

   IN THE MIDDLE, WITH A LITTLE JUMP. The owner, 2026-09-26: "crashed text in
   middle and little animation for it to appear". It had stood just above the
   wreck, high on the road; now it is centred where YOU WIN is, on the road
   above the dock, over the two cars as the win is over the car that banked.
   And rather than fading in where it stands, the word jumps up into place,
   whole -- the "just jump up" the owner chose for v3's crash, and the win's
   letter jump done once for the word: up from under its place, a touch past
   it, and down with a slight squash, all in 420ms.

       0-420 ms  CRASHED jumps up into place
     200-540     CRASHED AT n.nnx rises in under it
      540 on     nothing moves

   Before it, the multiplier cowers and sinks away (section 8), and the cars
   do the crashing. No gradient, rim or breathing glow, no letters, and the
   road does not bump as it lands. */
.outcome:not(.won){background:radial-gradient(60% 55% at 50% 50%,#ff405226,#0000 70%)}
/* The lane tags stay over the road through a crash, as they do through a win.
   The owner, 2026-09-26: "when crashed on laptop show road things on top like
   win". They used to step aside for a crash on every layout, which left the
   laptop's crash the only result with the top of the road bare. A phone held
   upright still clears them for either result (section 10), which is what the
   owner asked of the phone. */
.lane-tags{transition:opacity .2s}
.outcome:not(.won) .burst{display:none}
.outcome:not(.won) strong{
  display:block;position:relative;margin:0;white-space:nowrap;
  font:900 var(--word-size)/1 var(--title);letter-spacing:.02em;
  color:var(--coral);text-shadow:0 0 18px #ff405280,0 2px 0 #3d0a10;
  transform-origin:50% 100%;
  animation:crash-word-in .42s both;
}
.outcome:not(.won)>span{
  display:block;margin-top:.9em;font:700 var(--line-size)/1.2 var(--body);letter-spacing:.22em;
  color:#ffc2c8;text-transform:uppercase;text-shadow:0 1px 2px #000c;
  animation:win-line-in .34s cubic-bezier(.2,.7,.3,1) .2s both;
}
@keyframes crash-word-in{
  0%{opacity:0;translate:0 .42em;scale:.92;animation-timing-function:cubic-bezier(.2,.7,.35,1)}
  30%{opacity:1}
  55%{translate:0 -.06em;scale:1.02;animation-timing-function:cubic-bezier(.5,0,.7,.5)}
  78%{translate:0 0;scale:1.03 .95;animation-timing-function:cubic-bezier(.2,.6,.3,1)}
  100%{opacity:1;translate:0 0;scale:1}
}

/* Reduced motion: every part of the result is simply there -- the crash
   fades in whole, the word and its line together; no letters, no count, no
   stamp, no rays (result-fx.js draws none of it). The global reduced-motion
   rule above kills every animation with !important; the fade is restated
   with !important and a more specific selector so that it survives it. */
@keyframes crash-fade{from{opacity:0}}
@media(prefers-reduced-motion:reduce){
  .outcome{animation:none!important}
  .outcome:not(.won){animation:crash-fade .3s ease-out!important}
  .outcome .burst i{animation:none;opacity:.85;transform:translate(var(--x),calc(var(--y) * var(--spark-ry)))}
  .outcome fx-rays{display:none!important}
}

/* Phones and every touch screen: the same composition, smaller. */
@media (max-width:860px), (pointer:coarse){
  .outcome,.outcome.won{max-width:92vw}
  .outcome.won strong{font-size:clamp(64px,19vw,100px)}
  .outcome.won.long strong{font-size:clamp(48px,13vw,72px)}
  .outcome.won>span{font-size:11px}
  .outcome,.outcome.won{--word-size:clamp(38px,11vw,54px);--line-size:11px}
  .outcome .burst{--spark-k:.9}
  .outcome fx-rays{width:150%}
}
/* A short portrait phone (320x568) centres the text only ~75px under the lane
   labels, so the sparks fly half as far up and down. */
@media (max-width:860px) and (max-height:700px) and (orientation:portrait){
  .outcome.won .burst{--spark-ry:.55}
}
/* A short landscape screen (the side panel, and the compact bar) sizes the
   type by height as well: at 320-414px tall the phone's width-based sizes
   would stand the headline over a third of the screen, and the sparks fly a
   shorter way. YOU WIN is set small here, an eyebrow over the payout, which
   is the headline; CRASHED has no payout under it and is its own headline, so
   it is the one layout where the crash's word is set larger than the win's:
   at 568x320, 35px against 21px. */
@media (max-width:960px) and (orientation:landscape) and (max-height:540px){
  .outcome.won strong{font-size:clamp(34px,min(15vw,14vh),84px)}
  .outcome.won.long strong{font-size:clamp(28px,min(10vw,10vh),60px)}
  .outcome,.outcome.won{--word-size:clamp(18px,min(8vw,6.5vh),40px)}
  .outcome:not(.won){--word-size:clamp(28px,min(11vw,11vh),56px)}
  .outcome .burst{--spark-k:.7}
  .outcome.won .burst{--spark-ry:.6}
}
/* The side panel: keep the text left of it, centred on the road. */
@media (min-width:600px) and (max-width:739px) and (max-height:540px) and (orientation:landscape),
       (max-width:599px) and (max-height:540px) and (min-aspect-ratio:3/2){
  .outcome,.outcome.won{max-width:calc(2 * min(var(--road-centre), 100vw - 296px - var(--road-centre)) - 12px)}
}

/* 8. The multiplier readout steps aside for the result. It stays through
   `crashing`, and fades out at `won` / `lost`, when the result text takes its
   place; it is back the moment the next round starts.

   v5: through `crashing` the number COWERS (result-fx.js), after the Temple's
   "the number cowers and is crushed", made gentle on the owner's word: any
   stamp still on it stops, it drains to a cold, dull red -- a pre-painted
   copy fading in over it, not a filter -- and eases down to .94; at contact
   (`redline:hit`) it sinks a little, squashes slightly and fades away in
   320ms. Then CRASHED comes in (section 7). Only transform and opacity move,
   and the copy goes when it is done. */
.readout{transition:opacity .2s}
body:is([data-phase=won],[data-phase=lost]) .readout{opacity:0;visibility:hidden;transition:opacity .2s,visibility 0s .2s}
body[data-phase=crashing] .readout,body[data-phase=crashing] .readout *{animation:none!important}

/* 9. THE MULTIPLIER ON A TALL PHONE: as big as the width allows, just above
   the lane tags. The owner, 2026-09-25, on a phone: "I want multiplier bigger,
   there is space". The tags carry `run-on` exactly when resize() starts the
   road part-way down a tall phone, so these rules follow the road's far end
   (`--road-top`) and apply nowhere else.

   24vw is the widest the widest reading can be: "1000.00×" measures 4.10em in
   the condensed face, 98.4% of the screen at 24vw. At 393x695 that is 94.32px
   against the 56.2px it was. The second term only binds on a short phone,
   where it keeps the number below the options button: the number's box is
   .82em tall and its foot sits 14px above the lane tags, so 74px puts its top
   60px down, clear of the 44px button 10-11px from the top.

   It is anchored by its foot, so the size is free to change without moving it
   into the tags. The safe-lane countdown pill leaves the flow for the same
   reason and floats above the number: under it, it would sit on the tags.

   The tags themselves sit `--tag-lift` above the road's far end rather than
   on it ("push up SAFE and that stuff a little"), over the road's run-on, and
   the number rises with them. At 393x695 that is WILD / RISKY / SAFE from
   188px to 170px down, and the number's top from 96.66px to 78.66px. */
.road{--tag-lift:18px}
.lane-tags.run-on{translate:0 calc(-1 * var(--tag-lift))}
.lane-tags.run-on~.readout{
  --mult-size:clamp(56px,min(24vw,(var(--road-top,0px) - var(--tag-lift) - 74px) / .82),124px);
  top:auto;bottom:calc(100% - var(--road-top,0px) + var(--tag-lift) + 14px);
}
.lane-tags.run-on~.readout>b{font-size:var(--mult-size)}
.lane-tags.run-on~.readout>#laneStatus{position:absolute;left:50%;bottom:100%;translate:-50% 0;margin:0 0 8px;white-space:nowrap}

/* 10. A WIN OR A CRASH TAKES A PHONE'S SCREEN. The owner, 2026-09-25: "when
   win animation on phone, and same for crash, other stuff should disappear
   and it should appear big". At won and lost the lane tags go, since they
   steer nothing between rounds, and the options button steps out while the
   result lands and comes back after it, so it is not out of reach for long.
   The credits badge steps out with it for a crash only (v5): on a win it stays
   where it is, so the new balance can be seen counting up in it. The betting
   panel stays: it is how the next round starts, and it holds the road still
   (section 3c).

   The win and the crash both sit in the middle of the screen above the
   panel (section 7). YOU WIN is 16vw where it was 11vw, CRASHED the same
   (`--word-size`, section 7; "CRASHED" measures 3.49em, 56% of the screen),
   and the payout is as big as its length allows. app.js writes the payout's
   length to `--result-len`, and .42em a character is more than any payout
   needs: the widest, "$1,000,000.00", the most a round can pay, measures
   4.88em against 5.46em. So 90vw over that holds one line at every width,
   capped at 30vw and 170px. At 393px: "$1.00" 117.9px where it was 74.7px,
   "$1,000.00" 93.6px, "$1,000,000.00" 64.8px. */
@media (max-width:599px) and (min-height:541px),
       (max-width:599px) and (orientation:portrait){
  .lane-tags{transition:opacity .2s}
  body:is([data-phase=won],[data-phase=lost]) .lane-tags{opacity:0;visibility:hidden;transition:opacity .2s,visibility 0s .2s}
  body:is([data-phase=won],[data-phase=lost]) .deck-extras,
  body[data-phase=lost] .credits{animation:result-clear 2.2s both}
  .outcome,.outcome.won{--result-centre:calc((100% - var(--dock-inset,0px)) / 2);--word-size:clamp(38px,16vw,90px);
    --line-size:13px}
  .outcome:not(.won)>span{letter-spacing:.2em}
  .outcome.won strong,.outcome.won.long strong{font-size:min(30vw,170px,90vw / (.42 * var(--result-len,13)))}
  .outcome.won>span{font-size:13px;letter-spacing:.2em}
}
/* Out for the first 1.8s of the result, back over the last .4s. */
@keyframes result-clear{0%,82%{opacity:0;visibility:hidden}to{opacity:1;visibility:visible}}
