/* ════════════════════════════════════════════════════════════════
   ELEVATOR — Climb & Cash Out
   Realistic skyscraper elevator. Muted, grounded palette.
   Zone theming via [data-zone] CSS variables on <body>.
════════════════════════════════════════════════════════════════ */

*,*::before,*::after{margin:0;padding:0;box-sizing:border-box;-webkit-tap-highlight-color:transparent}
html,body{width:100%;height:100%;overflow:hidden}
button{touch-action:manipulation}   /* rapid taps (CASH OUT!) must never trigger double-tap zoom or tap delay */
/* every interactive control clears the 44px touch minimum (item 10) */
@media (pointer:coarse){
  button,.adj,.pr,.sfx-btn,.bnum{min-height:44px}
  .btn-co,.btn-st,.btn-safe{min-height:56px}   /* primary actions get more than the minimum */
}
button:focus-visible,input:focus-visible{outline:2px solid rgba(230,192,116,.65);outline-offset:2px}   /* keyboard access (QA point 10) */

:root{
  /* ── CORNERS ──
     Nothing here is a pill any more. A fully rounded control reads as a tag — something to
     look at — and every one of these is something to press, so they are cut back to a corner
     that still softens the edge without rounding the shape away.

     Three sizes rather than one number, because a radius is only ever right relative to a
     height. A quarter of the control is the rule; hold one value across every size instead and
     the small chips come out as pills again while the tall buttons come out square. */
  --r-chip:3px;                 /* tags, badges, the switch track */
  --r-ctl:5px;                  /* keys and fields, roughly 30–40px */
  --r-key:7px;                  /* the big faces: BET, CASH OUT, BANK, PLAY */
  --ink:#e8eaef;
  /* These two carry most of the small text in the game — control labels, the round state,
     the lift risk/ceiling. At .45 and .22 they measured 1.7:1 against the panels, far under
     the 4.5:1 that small text needs, and unreadable on a phone in daylight. Lifted to clear
     the threshold while staying quiet: the hierarchy is unchanged, the text is just legible. */
  --ink-dim:rgba(232,234,239,.72);
  --ink-faint:rgba(232,234,239,.55);
  --panel:rgba(10,12,18,.66);
  --panel-line:rgba(255,255,255,.07);
  --steel-1:#c4c8cf; --steel-2:#9aa0a9; --steel-3:#6c727c; --steel-4:#3a3f47;
  --good:#42d06a; --bad:#f04141; --warn:#efa72b;   /* status colours carry a little more chroma than the original */
  --amber:#ff9d3a;            /* elevator segment display — already fully saturated, left alone */
}

/* make --accent animatable so a zone change re-lights the whole scene smoothly (graceful fallback: snaps) */
@property --accent{syntax:'<color>';inherits:true;initial-value:#d8a24a;}

/* Default zone (reception). Each zone overrides these. */
body{
  --accent:#d8a24a;          /* zone accent (warm brass) */
  --bg1:#15110d; --bg2:#241b12;  /* sky gradient */
  --glow:rgba(216,162,74,.16);
  
  font-family:'Inter',sans-serif;color:var(--ink);
  min-height:100vh;min-height:100dvh;position:relative;overflow:hidden;
  display:flex;align-items:center;justify-content:center;background:#06070a;
  transition:--accent 1.8s ease;   /* zone re-light */
}
/* ── ZONE PALETTES — each tier its own light: amber → teal → champagne → violet → cold metallic ──
   Saturation was lifted here (not lightness): the accents carry more chroma so the scene reads
   richer, while the shaft and page stay on the dark foundation. Raising --bg1/--bg2 or the panel
   values instead would wash the tower out — that is the mistake to avoid. */
/* Ten zones, ten lights. The walls stay dark everywhere; this is the colour of the light in the
   room, and it rises from warm and close (the foyer) to cold and far (the sky) to gold (the vault). */
body[data-zone="lobby"]     {--accent:#e8a54a;--glow:rgba(232,165,74,.19);}   /* Lobby — fireside amber */
body[data-zone="office"]    {--accent:#6fa8c9;--glow:rgba(111,168,201,.18);}  /* Office — steel blue */
body[data-zone="executive"] {--accent:#c9a15a;--glow:rgba(201,161,90,.20);}   /* Executive — brass */
body[data-zone="casino"]    {--accent:#c8643f;--glow:rgba(200,100,63,.20);}   /* Casino — bordeaux-gold */
body[data-zone="nightclub"] {--accent:#d24fd8;--glow:rgba(210,79,216,.20);}   /* Nightclub — dimmed magenta */
body[data-zone="luxury"]    {--accent:#eec36b;--glow:rgba(238,195,107,.23);}  /* Luxury — champagne */
body[data-zone="penthouse"] {--accent:#a77be0;--glow:rgba(167,123,224,.22);}  /* Penthouse — violet */
body[data-zone="rooftop"]   {--accent:#3fc4c0;--glow:rgba(63,196,192,.20);}   /* Rooftop — pool teal */
body[data-zone="skylounge"] {--accent:#9fd3f0;--glow:rgba(159,211,240,.24);}  /* Sky Lounge — ice blue */
body[data-zone="skyvault"]  {--accent:#f2c45a;--glow:rgba(242,196,90,.27);}   /* Sky Vault — gold on black */

/* ░░ ATMOSPHERE ░░ */
/* page background = LUXURY TOWER ATRIUM. Confident, symmetric architecture that actually READS:
   fluted onyx wall panelling, twin gold light stelae flanking the stage, a warm ceiling cone,
   and a grounded dark-marble base with a gold skirting line. Few elements, strong composition. */
.sky{position:fixed;inset:0;z-index:0;pointer-events:none;
  background:
    /* warm ceiling light cone onto the stage */
    radial-gradient(ellipse 46% 42% at 50% 0%,rgba(212,165,74,.13),transparent 72%),
    /* ambient glow pooling behind the shaft */
    radial-gradient(ellipse 46% 54% at 50% 46%,rgba(66,58,42,.38),transparent 74%),
    /* light fixtures at the stelae heads — the light has a visible source */
    radial-gradient(ellipse 120px 80px at calc(50% - 341px) 10%,rgba(244,208,138,.22),transparent 70%),
    radial-gradient(ellipse 120px 80px at calc(50% + 341px) 10%,rgba(244,208,138,.22),transparent 70%),
    /* twin gold light stelae — visible vertical light blades flanking the stage (off-screen on phones) */
    linear-gradient(90deg,transparent calc(50% - 350px),rgba(240,205,140,.06) calc(50% - 345px),
      rgba(246,214,150,.4) calc(50% - 342px) calc(50% - 340px),rgba(240,205,140,.06) calc(50% - 335px),transparent calc(50% - 330px)),
    linear-gradient(90deg,transparent calc(50% + 330px),rgba(240,205,140,.06) calc(50% + 335px),
      rgba(246,214,150,.4) calc(50% + 340px) calc(50% + 342px),rgba(240,205,140,.06) calc(50% + 345px),transparent calc(50% + 350px)),
    /* stelae answered by soft reflections on the polished base */
    radial-gradient(ellipse 14px 110px at calc(50% - 341px) 90%,rgba(246,214,150,.10),transparent 72%),
    radial-gradient(ellipse 14px 110px at calc(50% + 341px) 90%,rgba(246,214,150,.10),transparent 72%),
    /* fluted wall panelling — rib highlight + deep shadow reveal */
    repeating-linear-gradient(90deg,rgba(255,255,255,.022) 0 1.5px,transparent 1.5px 30px,rgba(0,0,0,.5) 30px 32px,transparent 32px 62px),
    /* gold skirting line where wall meets base */
    linear-gradient(180deg,transparent 79.6%,rgba(206,158,86,.16) 79.8% 80.1%,transparent 80.4%),
    /* grounded dark-marble base */
    linear-gradient(180deg,transparent 80%,rgba(8,7,5,.72) 90%,#0d0a07 100%),
    /* deep charcoal atrium walls */
    linear-gradient(180deg,#131318 0%,#0b0b0f 42%,#060609 100%);
  transition:background 2.2s ease}
/* whole-screen parallax: floor slabs + section dividers drifting by as you climb */
/* The travelling parallax, moved off background-position and onto transform.

   This layer is fixed, full width and 200% of the viewport tall — about 2.25 megapixels at a
   1500px window. Scrolling it by animating background-position repainted every one of those
   pixels on every frame, for the whole length of a ride, which is what you felt the moment the
   lift set off and for as long as it climbed. The mobile block already switched it off with the
   note "background-position animations repaint every frame"; desktop kept it running.

   The two gradients scrolled at different rates, so they are now two layers translating at
   their own rate instead. Each moves by exactly one period of its own pattern, so the loop is
   seamless, and a transform costs the compositor nothing. */
.bg-sections{position:fixed;left:0;right:0;top:-50%;height:200%;z-index:1;opacity:.08;
  pointer-events:none;transition:opacity 1.5s}
.bg-sections::before,.bg-sections::after{content:'';position:absolute;inset:0;pointer-events:none}
.bg-sections::before{background:repeating-linear-gradient(180deg,
  transparent 0 74px,rgba(255,255,255,.05) 74px 76px,transparent 76px 150px)}
.bg-sections::after{background:repeating-linear-gradient(180deg,transparent 0 150px,
  color-mix(in srgb,var(--accent) 22%,transparent) 150px 153px,transparent 153px 300px)}
/* The layers are built while the doors are still open, not at the moment the lift sets off.

   Starting an animation is when the compositor has to create and rasterise the layer it runs
   on, and these two are each twice the viewport tall — around 18 MB apiece on a 1502x749
   screen. Doing that at the instant START is pressed puts the whole allocation inside the
   first frame of the ride, which is exactly where the hitch was reported.

   `.warm` is applied during boarding and declares the animation already, paused. The layers
   exist and are rasterised in the five idle seconds before the ride. `.moving` then only
   flips play-state, which costs nothing. */
.bg-sections.warm::before{animation:bgScrollNear 2.4s linear infinite paused}
.bg-sections.warm::after{animation:bgScrollFar 2.4s linear infinite paused}
.bg-sections.warm.moving::before,.bg-sections.warm.moving::after{animation-play-state:running}
@keyframes bgScrollNear{from{transform:translateY(0)}to{transform:translateY(150px)}}
@keyframes bgScrollFar{from{transform:translateY(0)}to{transform:translateY(300px)}}
/* casino-room vignette */
.vignette{position:fixed;inset:0;z-index:2;pointer-events:none;
  background:radial-gradient(ellipse 82% 76% at 50% 42%,transparent 56%,rgba(0,0,0,.46) 100%)}

/* ░░ TIER ATMOSPHERE — grows with --tier (0 lobby → 1 summit): richer gold + more danger ░░ */
/* ZONE LIGHT — colours the room with the current zone accent; re-lights smoothly via animated --accent */
.zone-amb{position:fixed;inset:0;z-index:3;pointer-events:none;mix-blend-mode:screen;opacity:.55;
  background:
    radial-gradient(ellipse 72% 38% at 50% 12%,color-mix(in srgb,var(--accent) 32%,transparent),transparent 70%),
    radial-gradient(ellipse 96% 48% at 50% 100%,color-mix(in srgb,var(--accent) 18%,transparent),transparent 72%)}

.luxe{position:fixed;inset:0;z-index:150;pointer-events:none;mix-blend-mode:screen;
  opacity:calc(var(--tier,0) * .5);transition:opacity 2.2s ease;
  background:
    radial-gradient(ellipse 95% 46% at 50% 2%,rgba(255,206,112,.2),transparent 60%),
    radial-gradient(ellipse 75% 40% at 50% 100%,rgba(255,188,96,.14),transparent 66%)}
.peril{position:fixed;inset:0;z-index:151;pointer-events:none;
  opacity:calc(var(--tier,0) * .35);transition:opacity 2.2s ease;     /* only a hint of red (2026-10-15) */
  box-shadow:inset 0 0 150px rgba(214,42,42,.5),inset 0 0 46px rgba(214,42,42,.22)}
.peril::after{content:'';position:absolute;inset:0;box-shadow:inset 0 0 95px rgba(255,46,46,.55);
  opacity:0;animation:perilPulse 1.5s ease-in-out infinite}
@keyframes perilPulse{0%,100%{opacity:0}50%{opacity:calc(var(--tier,0) * .2)}}
/* ░░ SHAKE ░░ */
@keyframes shake{0%,100%{transform:translate(0,0)}
  20%{transform:translate(-4px,2px)}40%{transform:translate(5px,-3px)}
  60%{transform:translate(-5px,3px)}80%{transform:translate(3px,-2px)}}
.shaking{animation:shake .35s cubic-bezier(.36,.07,.19,.97) both}   /* fits the quicker ~620ms jolt beat */

/* ════════════════════════════════════════════════════════════════
   LAYOUT — narrow sides, elevator dominates the centre
════════════════════════════════════════════════════════════════ */
/* desktop = contained app stage; the elevator tower is the commanding centrepiece, side space kept tight */
.shell{position:relative;z-index:10;width:100%;max-width:1180px;height:100vh;height:100dvh;
  display:grid;grid-template-rows:56px 1fr 86px;grid-template-columns:200px 1fr 200px;
  gap:12px;padding:8px 16px 12px}   /* taller stage row, taller action bar */

/* minimal premium top bar — the name, the wallet, the menu. No logo weight; the elevator is
   the logo. A hairline closes the bar off from the shaft below it. */
/* A solid black bar edge to edge. The shell is centred and narrower than the viewport, so the
   bar breaks out of it with matched negative margin / positive padding — the band reaches the
   screen edges while its contents stay on the shell's own left and right lines. */
/* Two rows now: the bar, and the last rounds under it. Both sit inside the one black band the
   pseudo-element paints, so it still reads as a single header rather than two stacked things. */
.hdr{grid-column:1/-1;position:relative;
  display:grid;grid-template-rows:1fr auto;align-content:center;gap:3px}
.hdr-bar{display:flex;align-items:center;justify-content:space-between;gap:8px}
/* ══ A 44px THUMB, A 26px BUTTON ══

   The whole bar was 44px tall for one reason: the coarse-pointer rule gives every button a
   44px minimum, and the menu button is the tallest thing up here. Shrinking the button would
   shrink the touch target, which is a real accessibility rule and not one to lose to make a
   header look tidier.

   So the two are separated. The button PAINTS at 26px so the bar can be thin, and an invisible
   pseudo-element centred on it keeps 44 by 44 of tappable area — a thumb lands on exactly what
   it landed on before, and the bar is eighteen pixels shorter. */
.hdr .burger{min-height:0;height:26px;width:26px;position:relative;padding:0}
.hdr .burger::after{content:"";position:absolute;top:50%;left:50%;
  transform:translate(-50%,-50%);width:44px;height:44px}
/* The band is painted, not boxed. Growing the header itself made it overflow its grid row and
   put a scrollbar on the phone; a pseudo-element reaches the screen edges and the top edge
   while the header keeps exactly the geometry the layout expects. The 40px overhang above is
   clipped — it only has to clear the gap over the bar, which differs per breakpoint. */
.hdr::before{content:'';position:absolute;top:-40px;bottom:0;
  left:calc(50% - 50vw);right:calc(50% - 50vw);
  background:#000;border-bottom:1px solid rgba(255,255,255,.07);pointer-events:none}
.hdr > *{position:relative}   /* content paints over the band */

/* The balance belongs to the bar, not on top of it: no capsule, no border, no blur — the
   coin and the number sit directly on the black. */
.hdr .bal{background:none;border:0;box-shadow:none;backdrop-filter:none;padding:0 2px}

.hdr-l{display:flex;align-items:center;gap:8px;flex:0 0 auto}
/* the mark had no rule at all, so NUVEX and Elevator ran together as bare inline text */
/* Solid gold, not the dimmed ink it was. It is the name of the thing; on a black bar it can
   carry the house colour without competing with anything, and everything else up here — the
   balance, the burger — is deliberately quieter than it. */
.brand{font-family:'Bebas Neue',sans-serif;font-weight:400;font-size:1.1rem;
  letter-spacing:4px;color:var(--accent-gold,#e8c37e);text-transform:uppercase;line-height:1;
  white-space:nowrap;text-shadow:0 0 18px rgba(232,195,126,.22)}
/* the zone reads on the threshold sign inside the shaft; it does not need a second badge up here */
.hdr .status-cap{display:none}
/* quiet status capsule — carries the zone identity; pulses + re-lights on a zone change (no banner over gameplay) */
.status-cap{display:flex;align-items:center;gap:8px;min-width:0;max-width:48%;
  padding:6px 14px;border-radius:var(--r-ctl);
  background:linear-gradient(180deg,rgba(255,255,255,.04),transparent 60%),rgba(10,12,18,.6);
  border:1px solid var(--panel-line);backdrop-filter:blur(10px);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.04)}
.cap-dot{width:7px;height:7px;border-radius:50%;flex-shrink:0;background:var(--accent);
  box-shadow:0 0 9px var(--accent);transition:background 1.8s,box-shadow 1.8s}
.cap-zone{font-size:.62rem;font-weight:700;letter-spacing:2px;text-transform:uppercase;
  color:color-mix(in srgb,var(--accent) 22%,var(--ink-dim));  /* quiet — the accent dot carries the zone colour */
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:color 1.8s}
/* APPROACH — a new zone is two floors away: the capsule breathes so the threshold
   becomes a visible decision point (paired with the audio riser) */
.status-cap.approach{animation:capApproach .5s ease-in-out 3}
.status-cap.approach .cap-dot{animation:dotApproach .5s ease-in-out 3}
@keyframes capApproach{0%,100%{border-color:var(--panel-line)}
  50%{border-color:color-mix(in srgb,var(--accent) 75%,transparent);
      box-shadow:0 0 18px color-mix(in srgb,var(--accent) 38%,transparent)}}
@keyframes dotApproach{0%,100%{transform:scale(1);opacity:1}50%{transform:scale(1.5);opacity:.65}}

/* ── EXPRESS +10 — a rare, time-limited offer floating just above the action bar ── */
/* ── EXPRESS OFFER ──
   Reads as a service plate bolted to the shaft, not a casino prize: brushed dark metal,
   a machined gold edge, one small indicator lamp. It sits ABOVE the action bar so the
   hierarchy stays multiplier → cash out → bank → express, and it never overlaps them. */
.express-offer{position:absolute;left:50%;bottom:calc(100% + 10px);transform:translateX(-50%);
  z-index:40;display:flex;align-items:center;gap:11px;white-space:nowrap;
  padding:9px 20px 11px;border-radius:var(--r-key);cursor:pointer;overflow:hidden;
  border:1px solid rgba(214,176,110,.55);color:#f6e6bd;
  background:
    linear-gradient(180deg,rgba(255,238,200,.10),rgba(255,238,200,0) 42%),
    repeating-linear-gradient(90deg,rgba(255,255,255,.028) 0 2px,transparent 2px 4px),
    linear-gradient(178deg,#38312250,#1a1710 55%,#12100b);
  box-shadow:0 0 0 1px rgba(0,0,0,.6),0 12px 26px rgba(0,0,0,.6),
             0 0 26px rgba(203,160,88,.24),inset 0 1px 0 rgba(255,240,205,.28);
  animation:exIn .3s cubic-bezier(.2,1.25,.5,1)}
.express-offer[hidden]{display:none}
.express-offer:active{transform:translateX(-50%) translateY(1px)}
/* the indicator lamp — the only thing that pulses */
.ex-ico{width:9px;height:9px;border-radius:50%;flex:0 0 auto;
  background:radial-gradient(circle at 35% 32%,#ffe7ab,#d29b3c 62%,#6b4715);
  box-shadow:0 0 9px rgba(233,181,96,.85);animation:exLamp 1.05s ease-in-out infinite}
@keyframes exLamp{0%,100%{opacity:.55;box-shadow:0 0 6px rgba(233,181,96,.5)}
  50%{opacity:1;box-shadow:0 0 13px rgba(245,201,120,.95)}}
.ex-txt{display:flex;flex-direction:column;align-items:flex-start;gap:1px;line-height:1}
.ex-t{font-family:'Bebas Neue',sans-serif;font-size:1.16rem;letter-spacing:3px;color:#fff3d4}
.ex-s{font-size:.55rem;font-weight:700;letter-spacing:1.6px;color:rgba(233,205,150,.82)}
.ex-s b{color:#f0c479;font-size:.62rem}
/* countdown: a machined rail that drains over exactly decisionMs */
.ex-bar{position:absolute;left:0;bottom:0;height:2.5px;width:100%;transform-origin:left center;
  background:linear-gradient(90deg,#8a6224,#e7bd76 55%,#ffe4ac);opacity:.9;transform:scaleX(0)}
.express-offer.counting .ex-bar{animation:exDrain var(--ex-ms,2500ms) linear forwards}
@keyframes exDrain{from{transform:scaleX(1)}to{transform:scaleX(0)}}
@keyframes exIn{from{opacity:0;transform:translateX(-50%) translateY(10px) scale(.94)}
  to{opacity:1;transform:translateX(-50%) translateY(0) scale(1)}}
.bot{position:relative}                 /* anchor for the offer */

/* ── THE RACE ──
   Speed is carried by the world, not by the cabin teleporting: the shaft streaks,
   the whole stage vibrates faintly, and the cabin strains against its own weight.
   The multiplier is deliberately left untouched — it must stay readable throughout. */
body.express-run .shaft-world{filter:blur(1.6px)}
body.express-run .stage{animation:exShake .085s linear infinite}
@keyframes exShake{0%{transform:translate3d(0,0,0)}25%{transform:translate3d(.6px,-.5px,0)}
  50%{transform:translate3d(-.5px,.4px,0)}75%{transform:translate3d(.4px,.6px,0)}
  100%{transform:translate3d(0,0,0)}}
body.express-run .car-body{animation:exStrain .5s cubic-bezier(.3,.75,.25,1) infinite}
@keyframes exStrain{0%{transform:translateY(2.5px)}45%{transform:translateY(-2.5px)}100%{transform:translateY(2.5px)}}
body.express-run .rail{box-shadow:0 0 16px rgba(240,205,140,.5)}
body.express-run .ind-num{color:#ffdf9e;text-shadow:0 0 18px rgba(240,196,121,.75)}
/* vertical light streaks rushing down past the cabin = the shaft flying by */
body.express-run .shaft-vp::before{content:'';position:absolute;inset:0;z-index:12;pointer-events:none;
  background:repeating-linear-gradient(180deg,transparent 0 26px,rgba(255,228,172,.16) 26px 30px);
  animation:exStreak .18s linear infinite}
@keyframes exStreak{from{transform:translateY(-30px)}to{transform:translateY(0)}}

/* Motion sensitivity: keep the event legible, drop the vibration and strobing. */
@media (prefers-reduced-motion: reduce){
  body.express-run .stage{animation:none}
  body.express-run .shaft-vp::before{animation:none;opacity:.35}
  body.express-run .car-body{animation:none}
  .ex-ico{animation:none}
}

/* ── CROSSING A ZONE: the whole shaft re-lights in the new colour and a band of light
      sweeps up past the cabin. Noticeable, but it never covers the multiplier. ── */
.shaft-vp.zone-cross::after{content:'';position:absolute;left:0;right:0;height:46%;bottom:-46%;
  z-index:13;pointer-events:none;
  background:linear-gradient(0deg,transparent,color-mix(in srgb,var(--accent) 34%,transparent) 55%,transparent);
  animation:zoneSweep 1.05s cubic-bezier(.35,0,.2,1) forwards}
@keyframes zoneSweep{from{transform:translateY(0)}to{transform:translateY(-215%)}}
.shaft.zone-cross{animation:zoneEdge 1.1s ease-out}
@keyframes zoneEdge{0%,100%{border-color:color-mix(in srgb,var(--accent) 22%,var(--steel-4))}
  25%{border-color:color-mix(in srgb,var(--accent) 95%,transparent);
      box-shadow:0 0 26px color-mix(in srgb,var(--accent) 45%,transparent)}}
.indicator.zone-cross{animation:zoneBar .9s ease-out}
@keyframes zoneBar{0%,100%{background:rgba(9,11,15,.94)}
  22%{background:color-mix(in srgb,var(--accent) 18%,rgba(9,11,15,.94))}}

.status-cap.zone-in{animation:capPulse 1.2s cubic-bezier(.2,.8,.2,1)}
@keyframes capPulse{0%{transform:scale(1)}
  16%{transform:scale(1.045);box-shadow:0 0 22px color-mix(in srgb,var(--accent) 42%,transparent),inset 0 1px 0 rgba(255,255,255,.04)}
  100%{transform:scale(1)}}
.status-cap.zone-in .cap-dot{animation:dotPulse 1.2s ease-out}
@keyframes dotPulse{0%,100%{transform:scale(1)}22%{transform:scale(1.55)}}
/* refined wallet — smoked-glass pill, champagne coin, condensed numerals */
.bal{display:flex;align-items:center;gap:9px;
  background:linear-gradient(180deg,rgba(255,255,255,.05),transparent 60%),rgba(10,12,18,.72);
  border:1px solid rgba(255,232,170,.16);border-top-color:rgba(255,232,170,.32);
  border-radius:var(--r-ctl);padding:6px 16px 6px 7px;box-shadow:0 2px 10px rgba(0,0,0,.4),inset 0 1px 0 rgba(255,255,255,.05);
  backdrop-filter:blur(10px)}
.bal-num{font-family:'Share Tech Mono',monospace;font-size:1.04rem;font-weight:400;
  letter-spacing:1px;color:var(--ink);text-shadow:0 0 10px rgba(255,232,170,.18)}
.coin{width:18px;height:18px;border-radius:50%;flex-shrink:0;
  background:radial-gradient(circle at 36% 30%,#ffe9a8,#e0b14a 55%,#9c7320);
  box-shadow:0 0 0 1px rgba(0,0,0,.3),0 0 8px rgba(224,177,74,.4)}
.coin.sm{width:14px;height:14px}
/* In the bar the currency is the glyph alone (2026-10-16): no disc, no glow, the same gold as the
   name, set like a unit in front of the number. The glyph comes from the session's currency
   (paintCurrency in game.js). */
.hdr .bal .coin{width:auto;height:auto;border-radius:0;background:none;box-shadow:none;
  font-family:'Inter',system-ui,sans-serif;font-size:1.02rem;font-weight:600;line-height:1;color:#e8c37e}
.hdr .bal{gap:4px}

/* ░░ CARDS ░░ */
.card{background:
    linear-gradient(180deg,rgba(255,255,255,.04),transparent 40%),var(--panel);
  border:1px solid var(--panel-line);border-top:1px solid color-mix(in srgb,var(--accent) 22%,transparent);
  border-radius:12px;padding:10px 12px;backdrop-filter:blur(10px);transition:border-color 2s;
  box-shadow:0 6px 24px rgba(0,0,0,.45),inset 0 1px 0 rgba(255,255,255,.05)}
.clbl{font-size:.56rem;font-weight:800;letter-spacing:2.5px;color:var(--ink-faint);
  text-transform:uppercase;margin-bottom:8px}

/* LEFT COLUMN — compact */
.lcol{grid-column:1;grid-row:2;display:flex;flex-direction:column;gap:10px;overflow:hidden}
/* bet stepper — one premium control unit (inset track + embedded round buttons) */
.bet-ctrl{display:flex;align-items:center;gap:6px;margin-bottom:9px;
  background:rgba(0,0,0,.26);border:1px solid var(--panel-line);border-radius:12px;padding:5px}
.adj{width:36px;height:36px;border-radius:var(--r-ctl);flex-shrink:0;cursor:pointer;
  border:1px solid rgba(255,232,170,.16);color:var(--ink);font-size:1.2rem;font-weight:700;
  background:linear-gradient(180deg,rgba(255,255,255,.08),rgba(255,255,255,.02));
  display:flex;align-items:center;justify-content:center;transition:background .12s,border-color .15s,transform .1s}
.adj:hover{border-color:rgba(255,232,170,.4)}
.adj:active{background:color-mix(in srgb,var(--accent) 30%,transparent);transform:scale(.94)}
.bnum{flex:1;min-width:0;text-align:center;font-family:'Bebas Neue',sans-serif;font-size:1.8rem;color:var(--ink);
  letter-spacing:1px;text-shadow:0 0 12px color-mix(in srgb,var(--accent) 40%,transparent);
  background:none;border:none;outline:none;padding:0 2px;cursor:text;
  border-bottom:1px solid transparent;transition:border-color .15s}
/* it reads as a display until you touch it, then it reads as the field it has always been */
.bnum:hover{border-bottom-color:color-mix(in srgb,var(--accent) 28%,transparent)}
.bnum:focus{text-shadow:0 0 16px color-mix(in srgb,var(--accent) 70%,transparent);
  border-bottom-color:color-mix(in srgb,var(--accent) 65%,transparent)}
/* preset chips — premium, with a clear selected state */
/* Six chips rather than four, and two of them subtract. Wrapping instead of shrinking: at
   three per row each one keeps a thumb-sized target on a phone, which four across a narrow
   card would not. */
.prs{display:flex;gap:6px;flex-wrap:wrap}
/* Four across, one row. It was three across over two rows when there were six chips and
   they only added; four gears fit a single line and the block is a row shorter for it. */
.pr{flex:1 1 calc(25% - 5px);min-width:48px;padding:7px 0;background:rgba(255,255,255,.035);border:1px solid var(--panel-line);
  border-radius:var(--r-ctl);color:var(--ink-dim);font-size:.72rem;font-weight:800;letter-spacing:.5px;cursor:pointer;
  transition:background .14s,border-color .14s,color .14s,box-shadow .14s,transform .1s}
.pr:hover{color:var(--ink);border-color:color-mix(in srgb,var(--accent) 40%,var(--panel-line))}
.pr:active{transform:scale(.96)}
/* .pr.on is gone with the selected state: the chips add, so none of them is ever "the" stake */
.pr:disabled{opacity:.32;pointer-events:none}   /* topping up by this much would pass the balance */
/* The two that take money off are the quieter pair: same shape and same size, less pull, so
   the row still reads as one control rather than two competing ones. */
.pr-dn{background:rgba(255,255,255,.015);color:color-mix(in srgb,var(--ink-dim) 78%,transparent)}
.pr-dn:hover{color:var(--ink-dim);border-color:color-mix(in srgb,var(--panel-line) 100%,transparent)}

/* ══ THE GEAR IN USE ══
   The pills keep the shape they had. What is new is that one is always lit: it used to be true
   that none was ever "the" selected chip, because they only ever added. Now a chip IS the state
   of the control — the gear the − and + travel in — so it has to look like one. */
/* WHITE ON THE SELECTED CHIP, always. It was #0f0d08 — near-black on a gold gradient, which
   at this size and weight left the 1 barely there and the digits reading as smudges. The
   selected state is already carried by the gold itself; the number on top of it only has to be
   legible, and white with a dark rim is legible on every one of these gradients.

   The rim matters: white on gold alone is thin, so a soft dark shadow gives the strokes an
   edge to sit against rather than dissolving into the fill. */
.pr.on{color:#fff;font-weight:800;text-shadow:0 1px 2px rgba(24,16,4,.55);
  background:linear-gradient(180deg,color-mix(in srgb,var(--accent) 92%,white),var(--accent));
  border-color:color-mix(in srgb,var(--accent) 70%,transparent);
  box-shadow:0 0 14px color-mix(in srgb,var(--accent) 28%,transparent)}
.pr.on:hover{color:#fff;border-color:color-mix(in srgb,var(--accent) 70%,transparent)}

/* It says the step, because a chip that behaves differently on its second tap is not something
   anybody guesses from looking at it. */

/* ── THE FALL ──
   The crash read-out. Deliberately not a big red multiplier on black: that belongs to the
   game with the plane. Here the hero is the floor indicator dropping back to the ground,
   because in this building that is what losing actually looks like. */
.crash-box{padding:26px 34px 22px}
/* An inspection plate bolted to the shaft, not a dialog: brushed dark steel, a machined
   edge, one hairline of light along the top. The building's own material language — the
   previous card was a dashboard alert that happened to be red. */
.crash-box{padding:26px 30px 20px;border-radius:16px;
  background:
    linear-gradient(180deg,rgba(255,255,255,.055),rgba(255,255,255,0) 34%),
    repeating-linear-gradient(90deg,rgba(255,255,255,.016) 0 2px,transparent 2px 4px),
    linear-gradient(176deg,#191b21,#101216 58%,#0a0c10);
  border:1px solid rgba(255,255,255,.10);
  box-shadow:0 26px 60px rgba(0,0,0,.72),0 2px 0 rgba(255,255,255,.05) inset,
             0 0 0 1px rgba(0,0,0,.55)}
/* the state light: a thin machined rule, the only red that glows at all */
.crash-box::before{content:'';position:absolute;top:0;left:24%;right:24%;height:2px;border-radius:99px;
  background:linear-gradient(90deg,transparent,#ff4d5e,transparent);
  box-shadow:0 0 14px rgba(255,77,94,.6)}

/* engraved, not badged. Hairlines either side instead of a pill and a blinking lamp. */
.crash-tag{display:flex;align-items:center;justify-content:center;gap:12px;
  font-family:'Inter',sans-serif;font-size:.6rem;font-weight:800;letter-spacing:4.5px;
  color:#e08a94;background:none;border:0;padding:0}
.crash-tag::before,.crash-tag::after{content:'';height:1px;flex:1;max-width:52px;
  background:linear-gradient(90deg,transparent,rgba(224,138,148,.45))}
.crash-tag::after{background:linear-gradient(270deg,transparent,rgba(224,138,148,.45))}

/* One slot, two jobs: the floor while it falls, the multiplier once it lands. Red throughout —
   the whole read-out is the loss, so it never changes colour halfway through. */
.crash-cap{font-size:.5rem;font-weight:800;letter-spacing:4.5px;color:rgba(232,234,239,.42);margin-top:20px}
/* Sharp, not glowing. The bloom was doing the work colour and size should do — a tight
   shadow gives the figure weight without the arcade halo. */
.crash-big{line-height:1;color:#ff5464;
  text-shadow:0 1px 0 rgba(0,0,0,.6),0 0 18px rgba(255,60,80,.16);
  font-family:'Share Tech Mono',monospace;font-size:3.9rem;
  font-variant-numeric:tabular-nums;min-height:1.05em;margin:2px 0 4px}
.crash-big.dropping{animation:fallShake .12s linear infinite}
@keyframes fallShake{0%{transform:translate(0,0)}25%{transform:translate(-1.5px,1px)}
  50%{transform:translate(1px,-1px)}75%{transform:translate(-1px,-1.5px)}100%{transform:translate(0,0)}}
/* the swap to the multiplier: a bigger, heavier face, hit once */
.crash-big.mult{font-family:'Bebas Neue',sans-serif;font-size:4.4rem;letter-spacing:2px;
  animation:crashHit .34s cubic-bezier(.2,1.35,.4,1)}

/* The stake, as an engraved row under a hairline — a receipt line, not a caption. */
#crashOv .ovd{display:flex;align-items:center;justify-content:space-between;gap:16px;
  margin:16px 2px 0;padding-top:12px;border-top:1px solid rgba(255,255,255,.07);
  font-family:'Share Tech Mono',monospace;font-size:.72rem;letter-spacing:1px;
  color:rgba(232,234,239,.55)}
#crashOv .ovd b{color:rgba(232,234,239,.9);font-weight:400}

/* geometry only — the fill lives with the other overlay accents so there is one place
   that decides what a crash button looks like */
#crashOv .ovbtn{margin-top:16px;border-radius:var(--r-key);padding:12px;
  font-size:1.05rem;letter-spacing:3px;
  box-shadow:0 6px 16px rgba(0,0,0,.45),inset 0 1px 0 rgba(255,255,255,.16)}
@keyframes crashHit{0%{opacity:0;transform:scale(1.18)}60%{opacity:1;transform:scale(.97)}
  100%{opacity:1;transform:scale(1)}}
.crash-box.slam{animation:boxSlam .34s cubic-bezier(.25,1.3,.4,1)}
@keyframes boxSlam{0%{transform:translateY(-5px)}60%{transform:translateY(2px)}100%{transform:translateY(0)}}

@media (prefers-reduced-motion: reduce){
  .crash-big,.crash-big.dropping,.crash-big.mult,.crash-box.slam,.crash-tag::before{animation:none}
}

/* ── CONNECTION BANNER ──
   Sits over everything, because a suspended ride is the one thing the player must not have
   to guess about. It says "reconnecting", not "error": the round is still open server-side. */
.net-banner{position:fixed;left:50%;top:calc(12px + env(safe-area-inset-top,0px));transform:translateX(-50%);
  z-index:120;display:flex;align-items:center;gap:9px;white-space:nowrap;
  padding:9px 16px;border-radius:var(--r-ctl);
  background:rgba(8,10,15,.96);border:1px solid rgba(240,180,90,.45);
  box-shadow:0 10px 30px rgba(0,0,0,.6);
  font-size:.68rem;font-weight:700;letter-spacing:.6px;color:#f3ddab;
  animation:netIn .25s ease}
.net-banner[hidden]{display:none}
/* Settled: the same banner carrying a finished message rather than one in progress. No spinner,
   and a quieter edge — nothing here is being worked on. */
.net-banner.settled{border-color:rgba(160,170,190,.32);color:#cdd4e2}
.net-banner.settled .net-spin{display:none}
@keyframes netIn{from{opacity:0;transform:translateX(-50%) translateY(-8px)}
  to{opacity:1;transform:translateX(-50%) translateY(0)}}
.net-spin{width:11px;height:11px;border-radius:50%;flex:0 0 auto;
  border:2px solid rgba(243,221,171,.28);border-top-color:#f0c479;animation:netSpin .8s linear infinite}
@keyframes netSpin{to{transform:rotate(360deg)}}
/* while suspended the ride is visibly on hold, so nothing looks clickable-but-dead */
body.offline .shaft-vp{filter:saturate(.55) brightness(.8)}
body.offline .btn-co,body.offline .btn-safe{opacity:.5;pointer-events:none}
@media (prefers-reduced-motion: reduce){ .net-spin{animation:none} }

/* ── LIFT PICKER / CALL PANEL ──
   Mounted on the closed doors, not in the controls: it costs the bet card no height (which
   matters on short phones, where the tower must stay the largest thing on screen) and it is
   where you would call a lift anyway. Disappears the moment the doors open. */
/* Above the hall doors (z 30) — buried behind them it renders as nothing at all. */
.lift-panel{position:absolute;left:12px;right:12px;bottom:14px;z-index:34;
  padding:10px 10px 8px;border-radius:12px;
  background:rgba(4,6,10,.94);border:1px solid rgba(255,255,255,.10);
  box-shadow:0 10px 30px rgba(0,0,0,.6),inset 0 1px 0 rgba(255,255,255,.06);
  transition:opacity .28s ease,transform .28s ease}
.lift-panel::before{content:'CALL PANEL';display:block;text-align:center;
  font-size:.5rem;font-weight:800;letter-spacing:2.4px;color:var(--ink-faint);margin-bottom:7px}
body.playing .lift-panel,
body.no-callpanel .lift-panel{opacity:0;transform:translateY(8px);pointer-events:none}
.lbl-short{display:none}   /* the abbreviated label only appears where the row is halved */
.lift-row{display:flex;gap:6px;margin-bottom:6px}
.lift-opt{flex:1;min-width:0;display:flex;flex-direction:column;align-items:center;gap:1px;
  padding:6px 2px;border-radius:var(--r-ctl);cursor:pointer;
  background:rgba(255,255,255,.035);border:1px solid var(--panel-line);color:var(--ink-dim);
  transition:background .14s,border-color .14s,color .14s}
.lift-opt:hover:not(:disabled){color:var(--ink);border-color:color-mix(in srgb,var(--accent) 40%,var(--panel-line))}
.lift-opt.on{color:#fff;border-color:color-mix(in srgb,var(--accent) 65%,transparent);
  background:color-mix(in srgb,var(--accent) 16%,rgba(255,255,255,.035));
  box-shadow:0 0 0 1px color-mix(in srgb,var(--accent) 20%,transparent)}
.lift-opt:disabled{opacity:.4;cursor:default}
.lift-name{font-family:'Bebas Neue',sans-serif;font-size:.98rem;letter-spacing:1.6px;line-height:1}
.lift-meta{font-family:'Share Tech Mono',monospace;font-size:.55rem;letter-spacing:.4px;color:var(--ink-faint)}
.lift-opt.on .lift-meta{color:color-mix(in srgb,var(--accent) 72%,#fff)}
/* the risk word is the thing being chosen, so it carries the colour */
.lift-opt[data-risk="low"].on{border-color:rgba(96,190,150,.6);
  background:linear-gradient(180deg,rgba(96,190,150,.20),rgba(255,255,255,.035));
  box-shadow:0 0 0 1px rgba(96,190,150,.22)}
.lift-opt[data-risk="high"].on{border-color:rgba(232,120,150,.6);
  background:linear-gradient(180deg,rgba(232,120,150,.20),rgba(255,255,255,.035));
  box-shadow:0 0 0 1px rgba(232,120,150,.22)}
.lift-opt[data-risk="low"].on .lift-meta{color:#8fdcbb}
.lift-opt[data-risk="high"].on .lift-meta{color:#f2a4bb}
.lift-note{font-size:.56rem;line-height:1.35;color:var(--ink-faint);text-align:center;min-height:1.9em}

/* ── TOWER PRESENCE ──
   Other riders sit in the world layer, so they scroll with the building: someone ten floors
   up is drawn ten floors up. Deliberately faint — they are company, never competition for
   the multiplier's attention. */
.tower-layer{position:absolute;inset:0;pointer-events:none;z-index:6}
.rider{position:absolute;left:0;right:0;display:flex;align-items:center;gap:5px;
  padding-left:10px;opacity:.5;animation:riderIn .35s ease}
@keyframes riderIn{from{opacity:0}to{opacity:.5}}
.rider-dot{width:6px;height:6px;border-radius:50%;flex:0 0 auto;
  background:color-mix(in srgb,var(--accent) 80%,#fff);
  box-shadow:0 0 7px color-mix(in srgb,var(--accent) 60%,transparent)}
.rider-mx{font-family:'Share Tech Mono',monospace;font-size:.56rem;letter-spacing:.5px;
  color:color-mix(in srgb,var(--accent) 55%,#fff)}
.rider.r-service .rider-dot{background:#7fb3c8;box-shadow:0 0 7px rgba(127,179,200,.5)}
.rider.r-glass .rider-dot{background:#e08fe8;box-shadow:0 0 7px rgba(224,143,232,.5)}
.tower-count{margin-left:8px;font-size:.5rem;font-weight:800;letter-spacing:1.4px;
  text-transform:uppercase;color:var(--ink-faint)}

/* ── SETTINGS SWITCH ──
   A physical throw-switch for the compact settings controls. */
.swrow{margin-top:6px}
/* padding + matching negative margin: the finger target grows to ~45px without the switch
   taking any more room in the card than the 25px it appears to occupy */
.switch{flex-shrink:0;display:flex;align-items:center;gap:7px;cursor:pointer;
  background:none;border:0;padding:10px 0 10px 12px;margin:-10px 0 -10px -12px;
  -webkit-tap-highlight-color:transparent}
/* THE ONE EXCEPTION, AND IT IS DELIBERATE.

   Everything else that is pressed in this building has had its corners cut back, because a
   fully rounded control reads as a tag — something to look at — and those are all things to
   press. A switch is neither. It is a state you can see from across the room, and the shape
   IS the reading: a track with a knob at one end of it. Squared off it starts to look like a
   very small button that happens to be lit, which is the one thing a switch must never be
   mistaken for.

   So these three keep their ends. Not an oversight and not a leftover — asked for, after
   seeing both. */
.sw-track{position:relative;width:38px;height:21px;border-radius:99px;flex-shrink:0;
  background:rgba(0,0,0,.42);border:1px solid var(--panel-line);
  box-shadow:inset 0 1px 3px rgba(0,0,0,.5);transition:background .18s,border-color .18s}
.sw-knob{position:absolute;top:2px;left:2px;width:15px;height:15px;border-radius:50%;
  background:linear-gradient(180deg,#8d9099,#5e626b);
  box-shadow:0 1px 3px rgba(0,0,0,.6);transition:transform .18s cubic-bezier(.3,1.3,.5,1),background .18s}
.switch.on .sw-track{background:color-mix(in srgb,var(--accent) 30%,rgba(0,0,0,.42));
  border-color:color-mix(in srgb,var(--accent) 62%,transparent)}
.switch.on .sw-knob{transform:translateX(17px);
  background:linear-gradient(180deg,#ffeec2,#d9ab54);
  box-shadow:0 1px 4px rgba(0,0,0,.55),0 0 10px color-mix(in srgb,var(--accent) 55%,transparent)}
.sw-state{font-family:'Share Tech Mono',monospace;font-size:.62rem;letter-spacing:1px;
  color:var(--ink-faint);min-width:22px;text-align:left;transition:color .18s}
.switch.on .sw-state{color:color-mix(in srgb,var(--accent) 70%,#fff)}
.switch:focus-visible{outline:2px solid color-mix(in srgb,var(--accent) 70%,transparent);
  outline-offset:3px;border-radius:6px}
@media (prefers-reduced-motion: reduce){ .sw-knob{transition:none} }

/* floor arrival gets a short gold beat (item 12) */
.ind-num.tick{animation:floorTick .34s cubic-bezier(.2,.9,.3,1)}
/* The tick fires on every floor, so a white flash with a glow meant the readout was the
   brightest thing on screen for most of a ride. The movement stays; the flash does not. */
@keyframes floorTick{
  0%{transform:translateY(3px) scale(.96)}
  45%{transform:translateY(0) scale(1.03);color:var(--ink)}
  100%{transform:none}}

/* secondary information stays readable but never competes (items 4 + 14) */
.stat-card .sk{color:rgba(232,234,239,.34)}
.stat-card .sv{opacity:.72}
.stat-card{opacity:.86}

.mini-card{display:flex;flex-direction:column;gap:8px}
.row-lbl{display:flex;justify-content:space-between;align-items:center;font-size:.62rem;color:var(--ink-dim)}
.potamt{font-family:'Bebas Neue',sans-serif;font-size:1.4rem;color:var(--accent);transition:color 2s}
.rsk-hdr{display:flex;justify-content:space-between;align-items:center;margin-bottom:2px;
  flex-wrap:wrap;row-gap:2px}   /* longer risk labels may wrap instead of clipping (QA point 1) */
.rsk-lbl{font-size:.56rem;font-weight:800;letter-spacing:1.4px;text-transform:uppercase;color:var(--ink-dim)}
.rsk-flr{font-family:'Share Tech Mono',monospace;font-weight:400;letter-spacing:0;color:var(--ink-faint)}
/* status chip = confidence surface: a glowing dot (meaning isn't carried by colour alone) + a bold state word */
.rbadge{display:inline-flex;align-items:center;gap:5px;font-size:.56rem;font-weight:800;letter-spacing:1.4px;
  padding:3px 9px 3px 8px;border-radius:var(--r-chip);border:1px solid transparent}
.rbadge::before{content:'';width:6px;height:6px;border-radius:50%;background:currentColor;box-shadow:0 0 7px currentColor}
.rb-s{background:rgba(76,198,110,.13);border-color:rgba(76,198,110,.34);color:#63d488}
.rb-r{background:rgba(242,181,68,.15);border-color:rgba(242,181,68,.42);color:#f2b544}
.rb-d{background:rgba(244,91,105,.18);border-color:rgba(244,91,105,.5);color:#f4657a}
/* Seven pixels tall with rounded ends is a pill whatever it measures money in. It is not a
   button, but it is the last one you can see, so it goes square too. */
.rsk-track{height:7px;background:rgba(255,255,255,.06);border-radius:2px;overflow:hidden;
  box-shadow:inset 0 1px 2px rgba(0,0,0,.4)}
.rsk-bar{height:100%;width:0%;border-radius:2px;
  background:linear-gradient(90deg,var(--good),var(--warn),var(--bad));transition:width .5s cubic-bezier(.4,0,.2,1)}

.stat-card{margin-top:auto}
.srow{display:flex;justify-content:space-between;align-items:center;padding:4px 0;border-bottom:1px solid rgba(255,255,255,.04)}
.srow:last-child{border-bottom:none}
.sk{font-size:.54rem;font-weight:700;letter-spacing:1px;color:var(--ink-faint);text-transform:uppercase}
.sv{font-family:'Share Tech Mono',monospace;font-size:.84rem;font-weight:700}
.vg{color:var(--accent)}.vgr{color:var(--good)}.vc{color:#8fc0e0}.vt{color:var(--ink)}

/* RIGHT COLUMN — muted social panels (kept low-key so the elevator stays the focus) */
.rcol{grid-column:3;grid-row:2;display:flex;flex-direction:column;gap:10px;overflow:hidden}
.rcol .card{background:rgba(9,11,16,.6);border-color:rgba(255,255,255,.05);box-shadow:0 4px 16px rgba(0,0,0,.35)}
.rcol .clbl{color:var(--ink-faint)}
.live-card{flex:1;min-height:0;overflow:hidden;display:flex;flex-direction:column}  /* kept for Live Bets reintroduction */
.live-card #liveD{flex:1;min-height:0;overflow-y:auto}
.hist-card{flex:1;min-height:0;display:flex;flex-direction:column;overflow:hidden}
.hist-card #rndsD{flex:1;min-height:0;overflow-y:auto}
.empty{font-size:.6rem;color:var(--ink-faint);text-align:center;padding:14px 0}
.rndrow{display:flex;align-items:center;justify-content:space-between;background:rgba(255,255,255,.022);
  border-radius:7px;padding:5px 9px;margin-bottom:5px}
.rndrow:last-child{margin-bottom:0}
.rfl{font-family:'Bebas Neue',sans-serif;font-size:1rem;color:var(--ink-dim)}
.rmx{font-family:'Share Tech Mono',monospace;font-size:.66rem;color:var(--ink-dim)}
.rtag{font-size:.46rem;font-weight:800;letter-spacing:1px;padding:2px 6px;border-radius:var(--r-chip)}
.rt-w{background:rgba(76,198,110,.10);color:rgba(124,200,152,.85)}
.rt-l{background:rgba(224,81,81,.08);color:rgba(198,132,132,.8)}
.lrow{display:flex;align-items:center;justify-content:space-between;background:rgba(255,255,255,.022);
  border-radius:6px;padding:5px 9px;margin-bottom:4px;font-size:.62rem}
.lrow:last-child{margin-bottom:0}
.ln{color:var(--ink-dim)}.lbet{font-family:'Share Tech Mono',monospace;color:var(--ink-dim)}
.lst{color:var(--ink-faint)}

/* ════════════════════════════════════════════════════════════════
   CENTRE — THE ELEVATOR
════════════════════════════════════════════════════════════════ */
/* centre stage: panoramic windows fill the gap, elevator stays centred */
.stage{grid-column:2;grid-row:2;display:flex;align-items:stretch;justify-content:center;gap:14px;min-height:0}
/* box-shadow, not filter:drop-shadow. A filter on this column forces the browser to
   re-rasterise the whole 320k px² subtree on every frame the cabin inside it moves — which is
   every frame of a ride. The shaft is a rectangle, so the two look the same. */
.scol{flex:0 1 500px;min-width:0;display:flex;flex-direction:column;min-height:0;position:relative;
  box-shadow:0 16px 42px rgba(0,0,0,.55)}


/* Floor indicator (the lit panel above hall doors in a real building) */
/* clean, minimal floor/multiplier bar */
/* slim, centred floor readout — the only thing above the shaft, so the cabin stays the focus */
.indicator{flex-shrink:0;display:flex;align-items:center;justify-content:center;gap:10px;
  padding:7px 18px;border-radius:10px 10px 0 0;
  background:linear-gradient(180deg,rgba(255,255,255,.035),transparent 55%),rgba(9,11,15,.94);
  border:1px solid var(--steel-4);border-bottom:none;
  box-shadow:inset 0 -1px 0 color-mix(in srgb,var(--accent) 32%,transparent)}   /* gold lintel edge above the shaft */
.ind-arr{font-family:'Share Tech Mono',monospace;font-size:.9rem;color:var(--amber);opacity:.22;transition:opacity .2s}
.ind-arr.on{opacity:.9;animation:arrB .7s ease-in-out infinite alternate}
@keyframes arrB{from{opacity:.45}to{opacity:.95}}
.ind-cap{font-size:.54rem;font-weight:800;letter-spacing:3px;color:var(--ink-faint);text-transform:uppercase}
/* the floor is a readout, not a headline: smaller, cooler and without the glow it used to
   carry, so the cabin and its multiplier stay the brightest thing in the shaft */
.ind-num{font-family:'Share Tech Mono',monospace;font-size:clamp(1.05rem,2.2vw,1.3rem);
  color:var(--ink-dim);letter-spacing:2px;min-width:38px;text-align:center;text-shadow:none}

/* Shaft */
.shaft{flex:1;position:relative;min-height:0;
  background:linear-gradient(90deg,#171a1f 0 18px,transparent 18px),
            linear-gradient(270deg,#171a1f 0 18px,transparent 18px);
  background-repeat:no-repeat;background-position:left,right;
  border-left:2px solid var(--steel-4);border-right:2px solid var(--steel-4)}
/* polished guide rails — thin, with a fine specular centre line */
.rail{position:absolute;top:0;bottom:0;width:5px;z-index:4;opacity:.5;border-radius:2px;
  background:linear-gradient(90deg,#16181d,#464c56 46%,#2b2f36 54%,#141619);
  box-shadow:0 0 5px rgba(0,0,0,.6),inset 0 0 0 .5px rgba(255,255,255,.05)}
.rail-l{left:24px}.rail-r{right:24px}
/* slim tensioned hoist cables — run from the top of the shaft down onto the cabin roof */
.cable{position:absolute;top:0;width:2px;height:calc(62% - 76px);z-index:3;opacity:.85;
  background:repeating-linear-gradient(180deg,#8a919c 0 6px,#4a505a 6px 11px);
  box-shadow:0 0 4px rgba(0,0,0,.5);transform-origin:top center;
  animation:cableScroll .55s linear infinite}
/* small gold clamp where the cable meets the cabin roof */
.cable::after{content:'';position:absolute;bottom:-3px;left:50%;transform:translateX(-50%);
  width:7px;height:5px;border-radius:2px;background:linear-gradient(180deg,#e6c477,#9c7a2e)}
.cable.paused{animation:none}
.cable-l{left:calc(50% - 21px)}.cable-r{left:calc(50% + 18px)}
@keyframes cableScroll{from{background-position:0 0}to{background-position:0 -22px}}
/* on a crash the cables snap and recoil upward */
.cable.snapped{animation:cableSnap .3s ease-out forwards}
@keyframes cableSnap{0%{transform:translateY(0) scaleY(1);opacity:.9}
  25%{transform:translateY(-6px)}100%{transform:translateY(-42px) scaleY(.7);opacity:0}}

.shaft-vp{position:absolute;inset:0 18px;overflow:hidden;
  background:
    radial-gradient(ellipse 110% 34% at 50% 72%,color-mix(in srgb,var(--accent) 11%,transparent),transparent 62%), /* subtle zone light at the cabin — kept dim so the gold cabin pops on dark */
    radial-gradient(ellipse 110% 55% at 50% 4%,rgba(54,74,104,.20),transparent 70%),     /* cooler, higher = farther up */
    linear-gradient(90deg,rgba(2,3,5,.55),transparent 15% 85%,rgba(2,3,5,.55)),          /* side walls fall away into dark — pushes the centre forward */
    linear-gradient(90deg,rgba(255,255,255,.05) 0 2px,transparent 2px 5px,transparent 95%,rgba(255,255,255,.04) 98%), /* rail highlights catching the light */
    linear-gradient(90deg,transparent 0 24%,rgba(0,0,0,.32) 40% 60%,transparent 76%),    /* recessed centre channel — the cabin travels in it */
    repeating-linear-gradient(90deg,rgba(255,255,255,.016) 0 1px,transparent 1px 58px),  /* back-wall panel seams */
    #070809;
  box-shadow:inset 0 0 70px 8px rgba(4,5,8,.6)}   /* darken the edges so the cabin owns the centre */
.shaft-vp::before,.shaft-vp::after{content:'';position:absolute;left:0;right:0;height:18%;z-index:14;pointer-events:none}
.shaft-vp::before{top:0;background:linear-gradient(180deg,#070809,transparent)}
.shaft-vp::after{bottom:0;background:linear-gradient(0deg,#070809,transparent)}

/* scrolling world of floors */
/* the ride is compositor-only: anchored at bottom:0, moved via translateY (set in JS) */
/* No will-change here, deliberately.

   This container is as tall as the whole building — 332 x 15,480 px, eighteen screens — so
   will-change:transform asked the compositor to hold roughly 78 MB of texture for it at DPR 2
   and to keep that in step as the shaft moves. Measured, that dwarfs everything else in this
   file put together. Without the hint the browser composites the transform against the visible
   region instead of pre-allocating the entire tower.

   The proper fix is to stop putting a whole building in the DOM at all — a window of about ten
   rows recycled as the cabin climbs, which is what the brief asked for. That is written and it
   works geometrically to the pixel when floors are placed one at a time, but it misaligns by
   whole floor heights during a live ride, and it is not something to ship half-right into the
   thing players look at. It needs eyes on a screen. */
.shaft-world{position:absolute;left:0;right:0;bottom:0}
/* The travelling motion blur is gone, and so is the JS that applied the class. It put a blur()
   over the entire shaft world — a hundred floor scenes and the cabin — for 360ms after every
   floor step, which on a fast climb means permanently. */

/* ── floor rows — architectural level bands. The central axis stays CLEAR for cabin + cables;
      level numerals live on the shaft wall (left), zone signage appears once per zone. ── */
/* `contain` is the point here. Each row carries its own zone texture — five SVG patterns
   across the building — and the first time a row scrolls into view that texture has to be
   decoded and rasterised. Without containment the browser may widen the invalidated region
   beyond the row, and that shows up as an occasional long frame ON A FLOOR CHANGE while the
   main thread is completely idle. The owner's probe caught exactly one: 73ms at floor 28,
   with zero long tasks, in a session where 4570 of 4574 frames were clean.

   Telling the browser a row's paint cannot escape its own box lets it repaint just that row.
   The rows are already position:absolute with a fixed height and overflow:hidden, so nothing
   here changes what is drawn — only how far the damage from drawing it can spread. */
.floor-row{position:absolute;left:0;right:0;height:150px;overflow:hidden;
  /* content-visibility:auto was tried here and measured: it skips nothing. Inside an ancestor
     that carries a transform the browser treats the whole subtree as potentially visible, so
     all 102 rows stayed rendered. `contain` is what does work — it stops the repaint of one
     row from invalidating anything outside it. */
  contain:layout paint style}
/* soffit shadow — the slab above casts down the wall (the strongest depth cue in the shaft) */
.floor-row::before{content:'';position:absolute;left:0;right:0;top:0;height:26px;z-index:1;pointer-events:none;
  background:linear-gradient(180deg,rgba(0,0,0,.44),transparent)}
/* refined platform edge: light lip → steel body → deep underside, with a gold hairline */
.floor-row::after{content:'';position:absolute;left:0;right:0;bottom:0;height:7px;z-index:1;pointer-events:none;
  background:linear-gradient(180deg,rgba(255,255,255,.1) 0 1px,#3a3f48 1px 3px,#14151a 3px 100%);
  border-top:1px solid color-mix(in srgb,var(--accent) 24%,rgba(255,255,255,.07))}
/* No base filter. brightness(1.02) saturate(1.12) is a 2% lift nobody can see, but it put a
   filter node on every one of the hundred floor scenes inside the moving world. The .active
   and .passed variants below keep theirs — those carry real lighting. */
.fr-scene{position:absolute;inset:0;z-index:0} /* atmosphere, not a competitor to the cabin */
.fr-scene::before{content:'';position:absolute;inset:0}   /* zone interior look */
.fr-scene::after{content:'';position:absolute;left:0;right:0;bottom:0;height:54px;z-index:1;pointer-events:none;opacity:.34;
  background-repeat:repeat-x;background-position:center bottom;background-size:auto 54px} /* furniture silhouette — quiet */
/* level marker — centred in the floor band (passes behind the cabin as it scrolls) */
.fr-meta{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);z-index:2;
  display:flex;flex-direction:column;align-items:center;gap:2px}
.fr-num-sm{font-size:1.4rem}
.fr-num{font-family:'Bebas Neue',sans-serif;font-size:2.3rem;line-height:.9;letter-spacing:1px;opacity:.48;
  transition:opacity .3s;text-shadow:0 2px 8px rgba(0,0,0,.65)}
.fr-mult{font-family:'Share Tech Mono',monospace;font-size:.6rem;letter-spacing:.5px;color:var(--ink-faint)}
/* zone threshold sign — an elegant building sign where the zone begins, plus its real gameplay trait */
.fr-zone{position:absolute;top:9px;left:50%;transform:translateX(-50%);z-index:2;white-space:nowrap;
  font-family:'Bebas Neue',sans-serif;font-size:.92rem;letter-spacing:7px;padding-left:7px;
  text-transform:uppercase;opacity:.6;text-align:center}
.fr-zone-sub{display:block;margin-top:3px;font-family:'Inter',sans-serif;font-size:.46rem;font-weight:800;
  letter-spacing:2.2px;opacity:.85;padding-left:0}
/* ground/entrance foundation at the very bottom of the shaft */
.ground-base{position:absolute;left:0;right:0;bottom:0;height:70px;z-index:1;pointer-events:none;
  background:linear-gradient(180deg,transparent,#19120a 55%,#0a0705);
  box-shadow:inset 0 3px 0 rgba(216,162,74,.22)}

/* ZONE INTERIORS — lighter washes + recognizable furniture silhouettes (::after) */
/* Ground floor and reception: the same dark wood as the Lobby zone above them. They used to be
   petrol/blue-black, which was right when the first zone was too — with the foyer now warm, the
   start of every ride showed a cold blue band under the cabin meeting a warm one above it. One
   material from the street door to floor 10, darkest at the bottom so the cabin reads on it. */
.z-rec .fr-scene::before{background:
  radial-gradient(ellipse 74% 42% at 50% 100%,rgba(224,170,92,.08),transparent 68%),
  repeating-linear-gradient(90deg,rgba(255,220,170,.03) 0 1px,transparent 1px 36px),
  linear-gradient(180deg,#140f0a 0%,#0d0907 55%,#080604 100%)}
/* The reception desk passes directly behind the cabin while it waits at the ground — kept as a
   whisper so the cabin, not the furniture, is what the eye lands on. */
.z-rec .fr-scene::after{opacity:.16}
.z-rec .fr-scene::after{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='144' height='46'%3E%3Crect y='40' width='144' height='6' fill='%23dcae58' opacity='.42'/%3E%3Cg fill='%23dcae58' opacity='.55'%3E%3Crect x='30' y='24' width='84' height='16' rx='2'/%3E%3Crect x='26' y='20' width='92' height='5' rx='2'/%3E%3Crect x='8' y='30' width='8' height='10'/%3E%3Cellipse cx='12' cy='25' rx='7' ry='6' opacity='.6'/%3E%3Crect x='128' y='30' width='8' height='10'/%3E%3Cellipse cx='132' cy='25' rx='7' ry='6' opacity='.6'/%3E%3C/g%3E%3C/svg%3E")}
.z-rec .fr-num{color:#f3d8a2}.z-rec .fr-zone{color:#e0b25e}

/* ZONE INTERIORS — ten places, ten floors each. Dark walls everywhere; the colour is only light
   and the furniture silhouette. Generated as one block so every zone follows the same recipe. */
.z-lob .fr-scene::before{background:
  radial-gradient(ellipse 30% 40% at 22% 100%,rgba(240,150,60,.16),transparent 70%),
  radial-gradient(ellipse 74% 42% at 50% 100%,rgba(224,170,92,.10),transparent 68%),
  repeating-linear-gradient(90deg,rgba(255,220,170,.035) 0 1px,transparent 1px 36px),
  linear-gradient(180deg,#1a130d 0%,#110c08 55%,#0a0705 100%)}
.z-lob .fr-scene::after{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='144' height='46'%3E%3Crect y='42' width='144' height='4' fill='%23d9a35a' opacity='.42'/%3E %3Cg fill='%23d9a35a' opacity='.55'%3E%3Crect x='50' y='14' width='44' height='28' rx='1'/%3E%3C/g%3E %3Crect x='58' y='24' width='28' height='18' fill='%230c0805'/%3E %3Cpath d='M66 42 Q70 30 72 34 Q75 26 78 42Z' fill='%23ffb35c' opacity='.85'/%3E %3Cg fill='%23d9a35a' opacity='.5'%3E%3Cpath d='M12 42 v-14 q0-6 8-6 h6 q8 0 8 6 v14z'/%3E%3Cpath d='M110 42 v-14 q0-6 8-6 h6 q8 0 8 6 v14z'/%3E %3Crect x='136' y='22' width='2' height='20'/%3E%3Cpath d='M131 22 h12 l-3-7 h-6z'/%3E%3C/g%3E%3C/svg%3E")}
.z-lob .fr-num{color:#f3d8a2}.z-lob .fr-zone{color:#e0a85e}
.z-off .fr-scene::before{background:
  repeating-linear-gradient(90deg,rgba(140,190,225,.08) 0 2px,transparent 2px 40px),
  radial-gradient(ellipse 74% 42% at 50% 100%,rgba(111,168,201,.12),transparent 68%),
  linear-gradient(180deg,#0e151c 0%,#091017 55%,#060a0f 100%)}
.z-off .fr-scene::after{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='144' height='46'%3E%3Crect y='42' width='144' height='4' fill='%237fb4d4' opacity='.4'/%3E %3Cg opacity='.6'%3E%3Crect x='4' y='34' width='30' height='8' fill='%237fb4d4'/%3E%3Crect x='52' y='34' width='30' height='8' fill='%237fb4d4'/%3E%3Crect x='100' y='34' width='30' height='8' fill='%237fb4d4'/%3E %3Crect x='12' y='22' width='15' height='10' rx='1' fill='%23cfe6f5'/%3E%3Crect x='60' y='22' width='15' height='10' rx='1' fill='%23cfe6f5'/%3E%3Crect x='108' y='22' width='15' height='10' rx='1' fill='%23cfe6f5'/%3E %3Crect x='18' y='32' width='3' height='3' fill='%237fb4d4'/%3E%3Crect x='66' y='32' width='3' height='3' fill='%237fb4d4'/%3E%3Crect x='114' y='32' width='3' height='3' fill='%237fb4d4'/%3E%3C/g%3E%3C/svg%3E")}
.z-off .fr-num{color:#cfe3f0}.z-off .fr-zone{color:#86b8d6}
.z-exe .fr-scene::before{background:
  radial-gradient(ellipse 16% 30% at 25% 0%,rgba(230,190,110,.13),transparent 70%),
  radial-gradient(ellipse 16% 30% at 75% 0%,rgba(230,190,110,.13),transparent 70%),
  repeating-linear-gradient(115deg,rgba(255,255,255,.018) 0 2px,transparent 2px 23px),
  linear-gradient(180deg,#121012 0%,#0b0a0c 55%,#070608 100%)}
.z-exe .fr-scene::after{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='144' height='46'%3E%3Crect y='42' width='144' height='4' fill='%23c9a15a' opacity='.42'/%3E %3Cg fill='%23c9a15a' opacity='.55'%3E%3Crect x='14' y='28' width='116' height='4' rx='1'/%3E%3Crect x='20' y='32' width='3' height='10'/%3E%3Crect x='121' y='32' width='3' height='10'/%3E %3Cpath d='M30 28 v-8 q0-3 4-3 h2 q4 0 4 3 v8z'/%3E%3Cpath d='M52 28 v-8 q0-3 4-3 h2 q4 0 4 3 v8z'/%3E%3Cpath d='M82 28 v-8 q0-3 4-3 h2 q4 0 4 3 v8z'/%3E%3Cpath d='M104 28 v-8 q0-3 4-3 h2 q4 0 4 3 v8z'/%3E%3C/g%3E %3Cg fill='%23f2d38a' opacity='.8'%3E%3Crect x='71' y='18' width='2' height='10'/%3E%3Cpath d='M66 18 h12 l-2-5 h-8z'/%3E%3C/g%3E%3C/svg%3E")}
.z-exe .fr-num{color:#f1dcae}.z-exe .fr-zone{color:#d4ae68}
.z-cas .fr-scene::before{background:
  radial-gradient(ellipse 34% 30% at 50% 0%,rgba(255,214,140,.16),transparent 72%),
  radial-gradient(ellipse 74% 42% at 50% 100%,rgba(200,100,63,.12),transparent 68%),
  repeating-linear-gradient(90deg,rgba(255,200,150,.03) 0 1px,transparent 1px 28px),
  linear-gradient(180deg,#1c0f0d 0%,#120908 55%,#0a0505 100%)}
.z-cas .fr-scene::after{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='144' height='46'%3E%3Crect y='42' width='144' height='4' fill='%23c8643f' opacity='.42'/%3E %3Cg fill='%23d98a5c' opacity='.55'%3E%3Cellipse cx='72' cy='30' rx='34' ry='5'/%3E%3Crect x='68' y='30' width='8' height='12'/%3E %3Cpath d='M24 42 v-12 q0-5 7-5 h3 q7 0 7 5 v12z'/%3E%3Cpath d='M103 42 v-12 q0-5 7-5 h3 q7 0 7 5 v12z'/%3E%3C/g%3E %3Cellipse cx='72' cy='29' rx='28' ry='3.4' fill='%232f6b4c' opacity='.7'/%3E %3Cg fill='%23f2c45a' opacity='.8'%3E%3Crect x='60' y='25' width='4' height='3'/%3E%3Crect x='66' y='24' width='4' height='4'/%3E%3Crect x='80' y='25' width='4' height='3'/%3E%3C/g%3E %3Cg fill='%23ffe0a0' opacity='.6'%3E%3Crect x='71' y='0' width='2' height='6'/%3E%3Cpath d='M60 8 Q72 2 84 8 Q72 13 60 8Z'/%3E%3C/g%3E%3C/svg%3E")}
.z-cas .fr-num{color:#f4c9b0}.z-cas .fr-zone{color:#d8805a}
.z-clb .fr-scene::before{background:
  radial-gradient(ellipse 80% 40% at 50% 0%,rgba(210,79,216,.16),transparent 70%),
  repeating-linear-gradient(90deg,rgba(220,110,240,.06) 0 3px,transparent 3px 12px),
  linear-gradient(180deg,#0e0912 0%,#09060c 55%,#050407 100%)}
.z-clb .fr-scene::after{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='144' height='46'%3E%3Crect y='42' width='144' height='4' fill='%23d24fd8' opacity='.45'/%3E %3Cg fill='%23b84cc4' opacity='.6'%3E%3Crect x='52' y='26' width='40' height='12' rx='1'/%3E%3Crect x='8' y='14' width='12' height='28'/%3E%3Crect x='124' y='14' width='12' height='28'/%3E%3C/g%3E %3Cg fill='%23f0a8ff' opacity='.7'%3E%3Ccircle cx='14' cy='22' r='3'/%3E%3Ccircle cx='14' cy='33' r='4'/%3E%3Ccircle cx='130' cy='22' r='3'/%3E%3Ccircle cx='130' cy='33' r='4'/%3E%3Crect x='56' y='29' width='10' height='2'/%3E%3Crect x='78' y='29' width='10' height='2'/%3E%3C/g%3E %3Cg fill='%23140a18' opacity='.95'%3E%3Ccircle cx='34' cy='38' r='4'/%3E%3Ccircle cx='44' cy='37' r='4.5'/%3E%3Ccircle cx='100' cy='38' r='4'/%3E%3Ccircle cx='110' cy='37' r='4.5'/%3E%3C/g%3E%3C/svg%3E")}
.z-clb .fr-num{color:#f2c2f5}.z-clb .fr-zone{color:#d76ade}
.z-lux .fr-scene::before{background:
  radial-gradient(circle at 50% 16%,rgba(236,196,120,.16),transparent 50%),
  radial-gradient(ellipse 74% 42% at 50% 100%,rgba(230,192,116,.1),transparent 68%),
  linear-gradient(180deg,#181310 0%,#0f0b08 55%,#090705 100%)}
.z-lux .fr-scene::after{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='144' height='46'%3E%3Crect y='42' width='144' height='4' fill='%23e8c072' opacity='.42'/%3E%3Cg fill='%23ecc888' opacity='.6'%3E%3Crect x='35' width='2' height='6'/%3E%3Cpath d='M22 12 Q36 4 50 12 Q36 18 22 12Z' opacity='.55'/%3E%3Ccircle cx='26' cy='13' r='1.6'/%3E%3Ccircle cx='32' cy='15' r='1.6'/%3E%3Ccircle cx='36' cy='16' r='1.6'/%3E%3Ccircle cx='40' cy='15' r='1.6'/%3E%3Ccircle cx='46' cy='13' r='1.6'/%3E%3Crect x='107' width='2' height='6'/%3E%3Cpath d='M94 12 Q108 4 122 12 Q108 18 94 12Z' opacity='.55'/%3E%3Ccircle cx='98' cy='13' r='1.6'/%3E%3Ccircle cx='104' cy='15' r='1.6'/%3E%3Ccircle cx='108' cy='16' r='1.6'/%3E%3Ccircle cx='112' cy='15' r='1.6'/%3E%3Ccircle cx='118' cy='13' r='1.6'/%3E%3C/g%3E %3Cg fill='%23ecc888' opacity='.5'%3E%3Crect x='58' y='30' width='28' height='12' rx='2'/%3E%3Crect x='54' y='26' width='36' height='5' rx='2'/%3E%3C/g%3E%3C/svg%3E")}
.z-lux .fr-num{color:#f6daa0}.z-lux .fr-zone{color:#ecc47a}
.z-pen .fr-scene::before{background:
  radial-gradient(ellipse 100% 42% at 50% 8%,rgba(167,123,224,.14),transparent 68%),
  radial-gradient(ellipse 30% 20% at 80% 100%,rgba(140,170,255,.10),transparent 70%),
  repeating-linear-gradient(90deg,rgba(200,170,255,.05) 0 2px,transparent 2px 48px),
  linear-gradient(180deg,#150f20 0%,#0e0a15 55%,#08060c 100%)}
.z-pen .fr-scene::after{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='144' height='46'%3E%3Crect y='42' width='144' height='4' fill='%23a77be0' opacity='.4'/%3E%3Cg fill='%238f6bc4' opacity='.55'%3E%3Crect x='6' y='22' width='12' height='20'/%3E%3Crect x='22' y='14' width='10' height='28'/%3E%3Crect x='36' y='26' width='13' height='16'/%3E%3Crect x='52' y='10' width='10' height='32'/%3E%3Crect x='66' y='20' width='12' height='22'/%3E%3Crect x='82' y='28' width='12' height='14'/%3E%3Crect x='98' y='14' width='10' height='28'/%3E%3Crect x='112' y='24' width='13' height='18'/%3E%3Crect x='128' y='18' width='10' height='24'/%3E%3C/g%3E%3Cg fill='%23e3ccff' opacity='.75'%3E%3Crect x='9' y='26' width='2' height='2'/%3E%3Crect x='25' y='20' width='2' height='2'/%3E%3Crect x='55' y='16' width='2' height='2'/%3E%3Crect x='101' y='20' width='2' height='2'/%3E%3Crect x='131' y='24' width='2' height='2'/%3E%3C/g%3E%3C/svg%3E")}
.z-pen .fr-num{color:#e1cdf7}.z-pen .fr-zone{color:#b48ee6}
.z-roof .fr-scene::before{background:
  radial-gradient(ellipse 60% 30% at 50% 100%,rgba(63,196,192,.16),transparent 70%),
  radial-gradient(ellipse 120% 40% at 50% 0%,rgba(80,110,160,.12),transparent 70%),
  linear-gradient(180deg,#0b1422 0%,#08101a 55%,#050a10 100%)}
.z-roof .fr-scene::after{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='144' height='46'%3E%3Crect y='42' width='144' height='4' fill='%233fc4c0' opacity='.45'/%3E %3Crect x='40' y='34' width='64' height='8' rx='1' fill='%233fc4c0' opacity='.55'/%3E %3Crect x='44' y='35' width='56' height='2' fill='%23bff5f2' opacity='.6'/%3E %3Cg fill='%232f8f8c' opacity='.55'%3E%3Crect x='8' y='32' width='14' height='10'/%3E%3Ccircle cx='15' cy='28' r='6'/%3E%3Crect x='122' y='32' width='14' height='10'/%3E%3Ccircle cx='129' cy='28' r='6'/%3E%3C/g%3E %3Cg fill='%23d7f5ff' opacity='.35'%3E%3Ccircle cx='30' cy='12' r='1'/%3E%3Ccircle cx='66' cy='8' r='1'/%3E%3Ccircle cx='98' cy='14' r='1'/%3E%3Ccircle cx='118' cy='6' r='1'/%3E%3C/g%3E%3C/svg%3E")}
.z-roof .fr-num{color:#c6f2ef}.z-roof .fr-zone{color:#5fd0cc}
.z-sky .fr-scene::before{background:
  radial-gradient(ellipse 92% 60% at 50% 26%,rgba(190,224,238,.16),transparent 70%),
  radial-gradient(ellipse 42% 22% at 27% 66%,rgba(255,255,255,.09),transparent 70%),
  radial-gradient(ellipse 38% 20% at 74% 56%,rgba(255,255,255,.07),transparent 70%),
  linear-gradient(180deg,#101a23 0%,#0a1119 55%,#060a0e 100%)}
.z-sky .fr-scene::after{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='144' height='46'%3E%3Crect y='42' width='144' height='4' fill='%23bcdcec' opacity='.45'/%3E%3Ccircle cx='72' cy='14' r='9' fill='%23bcdcec' opacity='.5'/%3E%3Cg fill='%23ffffff' opacity='.42'%3E%3Cellipse cx='30' cy='30' rx='18' ry='6'/%3E%3Cellipse cx='104' cy='26' rx='16' ry='5'/%3E%3C/g%3E%3C/svg%3E")}
.z-sky .fr-num{color:#e2f3ff}.z-sky .fr-zone{color:#bcdcec}
.z-vlt .fr-scene::before{background:
  radial-gradient(circle at 50% 40%,rgba(242,196,90,.16),transparent 46%),
  repeating-radial-gradient(circle at 50% 40%,rgba(242,196,90,.05) 0 1px,transparent 1px 14px),
  linear-gradient(180deg,#0c0a06 0%,#080604 55%,#040302 100%)}
.z-vlt .fr-scene::after{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='144' height='46'%3E%3Crect y='42' width='144' height='4' fill='%23f2c45a' opacity='.5'/%3E %3Ccircle cx='72' cy='24' r='16' fill='none' stroke='%23f2c45a' stroke-width='2' opacity='.6'/%3E %3Ccircle cx='72' cy='24' r='9' fill='none' stroke='%23f2c45a' stroke-width='1.4' opacity='.55'/%3E %3Cg stroke='%23f2c45a' stroke-width='1.4' opacity='.55'%3E%3Cpath d='M72 15 v18 M63 24 h18'/%3E%3C/g%3E %3Cg fill='%23f2c45a' opacity='.7'%3E%3Cpath d='M10 42 l3-6 h12 l3 6z'/%3E%3Cpath d='M14 36 l3-6 h4 l3 6z'/%3E%3Cpath d='M116 42 l3-6 h12 l3 6z'/%3E%3Cpath d='M120 36 l3-6 h4 l3 6z'/%3E%3C/g%3E%3C/svg%3E")}
.z-vlt .fr-num{color:#ffe3a0}.z-vlt .fr-zone{color:#f2c45a}
.z-sky .fr-num{text-shadow:0 0 12px rgba(180,220,240,.5)}
.z-vlt .fr-num{text-shadow:0 0 12px rgba(242,196,90,.45)}

/* active / passed floor states */
.floor-row.active .fr-num{opacity:1;text-shadow:0 0 16px currentColor,0 2px 8px rgba(0,0,0,.65)}
.floor-row.active .fr-mult{color:var(--ink-dim)}
.floor-row.active .fr-scene{filter:brightness(1.35) saturate(1.2)}
.floor-row.active::after{border-top-color:color-mix(in srgb,var(--accent) 42%,transparent)}
.floor-row.passed .fr-scene{filter:brightness(.38) saturate(.55)}
.floor-row.passed .fr-num{opacity:.2}

/* ── ELEVATOR CABIN — slim, tall, big clear interior ── */
.car{position:absolute;left:50%;top:62%;transform:translate(-50%,-50%);z-index:20;
  width:166px;display:flex;flex-direction:column;align-items:center}
/* gold roof cap — brushed, with a bright specular top edge */
.car-roof{width:150px;height:9px;border-radius:5px 5px 0 0;
  background:linear-gradient(180deg,#fdefc0 0%,#e6c477 42%,#b58c3d 100%);
  box-shadow:inset 0 1px 0 rgba(255,248,224,.9),0 -2px 8px rgba(0,0,0,.5),0 0 15px rgba(214,170,96,.32)}
/* premium GOLD BEZEL — layered brushed metal with directional light, so the cabin reads as
   a milled object with weight rather than a floating card. Four material layers:
   vertical brushing · horizontal micro-grain · directional gradient · specular edges. */
.car-body{width:166px;height:150px;position:relative;border-radius:8px;border:1.5px solid #4e3a12;
  background:
    repeating-linear-gradient(92deg,rgba(255,255,255,.055) 0 1px,transparent 1px 3px),   /* brushing */
    repeating-linear-gradient(2deg,rgba(0,0,0,.05) 0 1px,transparent 1px 4px),           /* micro grain */
    linear-gradient(150deg,#fff2ce 0%,#f0d391 10%,#d9b061 30%,#b08838 58%,#8a6829 80%,#6d5220 100%),
    linear-gradient(90deg,rgba(255,255,255,.2),transparent 24%);
  box-shadow:
    inset 0 1.5px 0 rgba(255,250,228,.85),          /* top specular edge */
    inset 0 -2.5px 0 rgba(60,42,12,.75),            /* bottom shadow edge */
    inset 2px 0 3px rgba(255,240,200,.16),          /* left catch light */
    inset -2px 0 4px rgba(50,35,10,.5),             /* right fall-off */
    0 0 0 1px #0a0805,
    -7px 0 18px rgba(0,0,0,.6), 7px 0 18px rgba(0,0,0,.6),
    0 18px 34px rgba(0,0,0,.72),                    /* the cabin sits ON something */
    0 0 46px rgba(206,158,86,.28)}
/* soft environmental reflection sliding across the top of the metal */
.car-body::before{content:'';position:absolute;inset:0;border-radius:7px;pointer-events:none;z-index:1;
  background:linear-gradient(118deg,rgba(255,255,255,.28) 0 6%,rgba(255,255,255,.06) 12%,
    transparent 30%,transparent 74%,rgba(255,255,255,.10) 88%,transparent 100%)}
/* contact shadow pooled under the car — grounds it in the shaft.
   (hung off .car-base, because .car::after already carries the win burst) */
.car-base{position:relative}
.car-base::after{content:'';position:absolute;left:7%;right:7%;top:100%;height:15px;
  border-radius:50%;background:radial-gradient(ellipse at 50% 25%,rgba(0,0,0,.8),transparent 72%);
  filter:blur(3px);pointer-events:none}
/* dark recessed glass face — deeper housing, so the read-out sits INSIDE the machine */
.car-cabin{position:absolute;inset:8px 9px;border-radius:4px;overflow:hidden;border:1px solid #000;
  background:linear-gradient(180deg,#243043 0%,#141d2b 52%,#080d13 100%);
  box-shadow:
    inset 0 3px 14px rgba(0,0,0,.85),               /* the recess */
    inset 0 -2px 8px rgba(0,0,0,.6),
    inset 0 0 0 1px rgba(255,255,255,.035),
    inset 0 1px 0 rgba(255,240,200,.10);            /* light catching the top lip of the housing */
  display:flex;align-items:center;justify-content:center}
/* subtle glass reflection sweeping across the top of the face */
.car-cabin::before{content:'';position:absolute;inset:0;z-index:1;pointer-events:none;
  background:linear-gradient(157deg,rgba(255,255,255,.10) 0 10%,transparent 26%)}
/* luxurious gold inner lining that grows with tier */
.car-cabin::after{content:'';position:absolute;inset:0;z-index:2;pointer-events:none;border-radius:3px;
  background:radial-gradient(ellipse 100% 82% at 50% 46%,transparent 42%,rgba(255,200,104,.55) 122%);
  opacity:calc(var(--tier,0) * .34);transition:opacity 2.2s}
/* crisp warm ceiling light bar */
.cab-ceiling{position:absolute;top:0;left:0;right:0;height:30%;z-index:1;pointer-events:none;
  background:radial-gradient(ellipse 66% 130% at 50% -20%,rgba(255,241,214,.42),rgba(230,210,180,.08) 55%,transparent 80%)}
.cab-ceiling::before{content:'';position:absolute;top:3px;left:50%;transform:translateX(-50%);
  width:52px;height:3px;border-radius:3px;background:rgba(255,247,226,.92);box-shadow:0 0 12px 2px rgba(255,226,168,.6)}
/* multiplier is the big focal read-out (neon); floor is the small label */
.cab-screen{position:relative;z-index:3;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:5px}
/* floor row removed — only the multiplier is shown in the cabin */
/* bright white multiplier — purple glow intensifies via JS --mx-glow (0→1) as the multiplier rises */
.cab-mult{font-family:'Bebas Neue',sans-serif;font-size:3.6rem;line-height:.88;color:#fff;
  white-space:nowrap;letter-spacing:2px;font-weight:700;font-variant-numeric:tabular-nums;
  text-shadow:
    0 0 calc(var(--mx-glow,0) * 9px)  rgba(216,180,255,calc(var(--mx-glow,0) * .9)),   /* tight, crisp violet core */
    0 0 calc(var(--mx-glow,0) * 26px) rgba(176,96,240,calc(var(--mx-glow,0) * .5)),
    0 0 calc(var(--mx-glow,0) * 58px) rgba(140,60,220,calc(var(--mx-glow,0) * .26)),
    0 2px 4px rgba(0,0,0,.78)}
.car-base{width:166px;height:11px;border-radius:0 0 6px 6px;
  background:linear-gradient(180deg,#dcb669,#a57e33 52%,#6e5420);
  box-shadow:inset 0 1px 0 rgba(255,240,204,.35),0 5px 12px rgba(0,0,0,.6)}
/* CRASH — cabin jolts up as cables snap, then plunges down the shaft */
.car.falling{animation:carFall 1s cubic-bezier(.6,0,.85,.45) forwards;z-index:22}
@keyframes carFall{
  0%{transform:translate(-50%,-50%) rotate(0)}
  12%{transform:translate(-50%,-66%) rotate(-2deg)}
  100%{transform:translate(-50%,310%) rotate(6deg)}}   /* longer plunge — the cabin now starts higher (62%) */
/* impact burst at the bottom of the shaft */
.impact{position:absolute;left:0;right:0;bottom:0;height:64px;z-index:21;opacity:0;pointer-events:none;
  transform-origin:bottom;
  background:radial-gradient(ellipse 60% 100% at 50% 100%,rgba(255,140,60,.6),rgba(150,90,50,.25) 45%,transparent 72%)}
.impact.boom{animation:boom .55s ease-out}
@keyframes boom{0%{opacity:0;transform:scaleY(.15)}18%{opacity:1;transform:scaleY(1)}100%{opacity:0;transform:scaleY(1.4)}}

/* jolt warning */
.jolt-ov{position:absolute;inset:0;z-index:18;pointer-events:none;display:flex;align-items:center;justify-content:center;
  background:rgba(224,120,40,0);transition:background .12s}
.jolt-ov.show{background:rgba(224,120,40,.14)}
.jolt-txt{font-family:'Bebas Neue',sans-serif;font-size:1.4rem;letter-spacing:4px;color:#ffb46a;
  text-shadow:0 0 16px rgba(255,140,40,.6);opacity:0;transition:opacity .15s}
.jolt-ov.show .jolt-txt{opacity:1}

/* ── HALL DOORS — stainless steel ── */
.doors{position:absolute;inset:0;z-index:30;display:flex;pointer-events:none}
.door{flex:1;height:100%;position:relative;overflow:hidden;
  background:linear-gradient(90deg,#3a3f47,#5a616b 30%,#4a5059 50%,#5a616b 70%,#3a3f47);
  transition:transform .65s cubic-bezier(.77,0,.18,1)}
.door::before{content:'';position:absolute;inset:0;
  background:repeating-linear-gradient(90deg,transparent 0 13px,rgba(0,0,0,.14) 13px 14px)}
.door-l{transform-origin:left}.door-r{transform-origin:right}
.door-seam{position:absolute;top:0;bottom:0;left:50%;width:2px;transform:translateX(-50%);z-index:31;
  background:rgba(0,0,0,.5);transition:opacity .3s}
.doors.open .door-l{transform:translateX(-101%)}
.doors.open .door-r{transform:translateX(101%)}
.doors.open .door-seam{opacity:0}
.doors.jolt .door-l{transform:translateX(-22%)}
.doors.jolt .door-r{transform:translateX(22%)}
.dflash{position:absolute;inset:0;z-index:33;pointer-events:none;background:rgba(224,81,81,0);transition:background .08s}
.dflash.on{background:rgba(224,81,81,.5)}
.dflash.warn{background:rgba(224,120,40,.24)}
.dsign{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);z-index:34;text-align:center;
  opacity:0;pointer-events:none;transition:opacity .25s .2s;width:200px}
.dsign.show{opacity:1}
/* .ds-ct and .ds-cs were the OUT OF SERVICE sign on the doors. It is gone — it appeared at the
   same instant CABLE SNAPPED did, so the shaft carried two verdicts on one event. Kept as a
   note rather than as dead rules. */
.ds-wt{font-family:'Bebas Neue',sans-serif;font-size:1.2rem;color:var(--good);letter-spacing:2px;
  text-shadow:0 0 14px rgba(76,198,110,.5)}

.shaft-floor{flex-shrink:0;height:14px;border-radius:0 0 10px 10px;
  background:linear-gradient(180deg,#1c1c22,#0d0f13);
  border:2px solid var(--steel-4);border-top:none;
  box-shadow:inset 0 2px 0 color-mix(in srgb,var(--accent) 26%,transparent),0 6px 18px rgba(0,0,0,.5)}   /* gold base trim closing the stage frame */

/* ════════════════════════════════════════════════════════════════
   BOTTOM BAR
════════════════════════════════════════════════════════════════ */
/* One action row. The middle panel is gone, so this is a flex bar rather than a 3-column
   grid with a dead column — that hole was what made START look small and the bar empty. */
.bot{grid-column:1/-1;grid-row:3;display:flex;gap:10px;align-items:stretch;justify-content:center;
  width:100%;max-width:780px;margin:0 auto}
.btn-st{flex:1 1 auto}                     /* START owns the ready-state bar */
body.playing .co-wrap{flex:1 1 auto}       /* the live cluster owns it during a round */
/* BANK 50% + CASH OUT = one cluster. CASH OUT owns the money language (coin + big number);
   SAFE is the quieter secondary control, and once used it collapses into a slim receipt. */
/* the live cluster exists only while a round is running — before it, START owns the bar */
.co-wrap{display:none;gap:9px;min-width:0;align-items:stretch}
body.playing .co-wrap{display:flex}
.co-wrap .btn-co{flex:1 1 auto;min-width:0}
.co-wrap>button{height:100%}   /* both actions are one row, never two sizes */
.btn-safe{flex:0 0 28%;min-width:0;display:none;flex-direction:column;align-items:center;justify-content:center;
  gap:3px;padding:10px 8px;border-radius:var(--r-key);cursor:pointer;white-space:nowrap;overflow:hidden;
  border:1px solid rgba(230,192,116,.42);color:#f3ddab;
  background:linear-gradient(180deg,rgba(206,158,86,.2),rgba(28,23,14,.7));
  box-shadow:inset 0 1px 0 rgba(255,240,200,.18),0 4px 14px rgba(0,0,0,.35);
  transition:color .25s,border-color .25s,background .25s,transform .1s}   /* width snaps: an animated flex-basis stalls here */
.btn-safe.on{display:flex}
.btn-safe:hover{border-color:rgba(230,192,116,.5)}
.btn-safe:active{transform:translateY(2px)}
/* a real secondary action, not a utility box: same typographic system as CASH OUT,
   one step quieter in colour and weight */
.sf-t{font-family:'Bebas Neue',sans-serif;font-size:clamp(1.05rem,2vw,1.35rem);letter-spacing:1.8px;line-height:1}
.sf-a{font-family:'Bebas Neue',sans-serif;font-size:clamp(.85rem,1.6vw,1.05rem);
  color:rgba(255,242,214,.92);line-height:1.25;font-variant-numeric:tabular-nums}
/* used → shrinks to a quiet receipt so CASH OUT reclaims the thumb zone
   (px basis in BOTH states — a % → px transition cannot interpolate and would stall) */
.btn-safe.used{flex:0 0 22%;pointer-events:none;
  border-color:rgba(230,192,116,.16);background:rgba(206,158,86,.05);color:rgba(230,192,116,.55)}
.btn-safe.used .sf-t{font-size:.8rem;letter-spacing:1px}
.btn-safe.used .sf-a{font-size:.58rem;opacity:.75}

/* idle = polished green ghost (not dead); active (.on) = vivid, dominant green */
.btn-co{position:relative;border:1px solid rgba(76,198,110,.28);border-radius:var(--r-key);cursor:pointer;
  color:rgba(214,246,224,.5);
  background:linear-gradient(180deg,rgba(45,168,85,.1),rgba(18,26,21,.62));
  display:flex;flex-direction:column;align-items:center;justify-content:center;padding:8px;gap:2px;
  pointer-events:none;transition:color .18s,transform .1s,box-shadow .2s,border-color .2s,background .2s}
/* Live only enables it here; how it looks live is the machined face further down. The flat
   green fill that used to sit on this rule is gone rather than overridden — leaving a dead
   background and shadow behind an override is how a stylesheet stops being readable. */
.btn-co.on{pointer-events:all}
.co-t{font-family:'Bebas Neue',sans-serif;font-size:clamp(1.2rem,2.4vw,1.7rem);letter-spacing:2px}
.co-a{font-family:'Bebas Neue',sans-serif;font-size:clamp(.9rem,1.8vw,1.2rem);color:rgba(255,255,255,.9);
  display:flex;align-items:center;gap:5px}
.bot-mid{background:var(--panel);border:1px solid var(--panel-line);border-radius:12px;padding:7px 12px;
  display:flex;flex-direction:column;gap:3px;backdrop-filter:blur(10px)}
/* round state as a quiet line in the floor strip — never a dashboard panel */
.ind-state{margin-left:auto;font-size:.5rem;font-weight:800;letter-spacing:2px;
  text-transform:uppercase;color:var(--ink-faint);transition:color .25s}
.ind-state[data-s="ASCENDING"],.ind-state[data-s="CASHOUT_AVAILABLE"]{color:color-mix(in srgb,var(--accent) 70%,#fff)}
.ind-state[data-s="CASHED_OUT"],.ind-state[data-s="ROUND_COMPLETE"]{color:#63d488}
.ind-state[data-s="CRASHED"]{color:#f4657a}
.indicator{justify-content:flex-start;padding-left:16px;padding-right:14px}
.ind-cap{margin-left:2px}
.btn-st{position:relative;overflow:hidden;background:linear-gradient(175deg,#f0d27a,#cba049 42%,#a87c2c);
  border:1px solid rgba(255,232,170,.5);
  border-radius:var(--r-key);color:#1c1305;font-family:'Bebas Neue',sans-serif;font-size:clamp(1.2rem,2.4vw,1.7rem);
  letter-spacing:3px;cursor:pointer;padding:10px;text-shadow:0 1px 0 rgba(255,255,255,.25);
  box-shadow:0 5px 18px rgba(180,140,40,.32),inset 0 1px 0 rgba(255,255,255,.45);
  transition:transform .1s,filter .15s}
.btn-st::before{content:'';position:absolute;inset:0;border-radius:var(--r-key);
  background:linear-gradient(180deg,rgba(255,255,255,.35),transparent 45%)}
.btn-st:active{transform:translateY(2px)}
/* ── disabled must read as inactive, not merely faded (item 13) ── */
.btn-st:disabled,.btn-safe:disabled,.pr:disabled,.adj:disabled{
  pointer-events:none;cursor:not-allowed;filter:saturate(.15);opacity:.45;
  box-shadow:none;text-shadow:none}
.btn-st:disabled{background:linear-gradient(175deg,#3a3730,#2a2823);color:rgba(255,255,255,.4);
  border-color:rgba(255,255,255,.08)}
/* ── A live round shows only the two decisions that matter. START does not exist
      while the cabin is moving — it is removed, not greyed out. ── */
body.playing .btn-st{display:none}
body.playing .co-wrap{display:flex;width:100%}
.co-wrap{transition:opacity .18s ease}
.btn-st:not(:disabled):hover{filter:brightness(1.06)}

/* desktop: the bottom controls read as one machine console deck, not a floating form strip */
@media(min-width:701px){
  .bot{padding:9px;border-radius:16px;
    background:linear-gradient(180deg,rgba(255,255,255,.03),transparent 60%),rgba(9,11,16,.55);
    border:1px solid var(--panel-line);border-top-color:color-mix(in srgb,var(--accent) 16%,var(--panel-line));
    backdrop-filter:blur(10px);box-shadow:0 10px 34px rgba(0,0,0,.45),inset 0 1px 0 rgba(255,255,255,.04)}
  .bot-mid{background:rgba(0,0,0,.28);border-color:rgba(255,255,255,.05)}
  /* the desktop action cell is narrower — keep SAFE clearly secondary to CASH OUT */
  .btn-safe{flex:0 0 28%}
  .btn-safe.used{flex:0 0 22%}

  /* DESKTOP HERO — the elevator tower reads as the clear, commanding centrepiece */
  .scol{flex:0 1 680px}                                 /* the shaft fills the stage instead of floating in it */
  .bot{max-width:900px}                                 /* the action bar tracks the wider stage */
  .car{transform:translate(-50%,-50%) scale(1.12)}      /* cabin minimally larger, all proportions intact */
  .cable{height:calc(62% - 86px)}                       /* re-seat the cables onto the larger cabin roof */

  /* more substantial, higher-quality shaft side frames: brushed-metal pillars with a bronze reveal */
  .shaft{background:
      linear-gradient(90deg,#0d0f13 0 4px,#1a1d24 4px 20px,#262a33 20px 24px,transparent 24px),
      linear-gradient(270deg,#0d0f13 0 4px,#1a1d24 4px 20px,#262a33 20px 24px,transparent 24px);
    border-left:2px solid color-mix(in srgb,var(--accent) 22%,var(--steel-4));
    border-right:2px solid color-mix(in srgb,var(--accent) 22%,var(--steel-4))}
  .shaft-vp{inset:0 24px}                                /* clear the wider frames */
  .rail-l{left:30px}.rail-r{right:30px}

  /* left rail = ONE premium console (matches the mobile deck language), not three floating cards */
  .lcol{position:relative;gap:0;
    background:linear-gradient(180deg,rgba(255,255,255,.035),transparent 55%),rgba(9,11,16,.6);
    border:1px solid var(--panel-line);border-top-color:color-mix(in srgb,var(--accent) 16%,var(--panel-line));
    border-radius:16px;padding:4px 0;backdrop-filter:blur(10px);
    box-shadow:0 8px 26px rgba(0,0,0,.4),inset 0 1px 0 rgba(255,255,255,.04)}
  .lcol .card{background:none;border:none;box-shadow:none;backdrop-filter:none;border-radius:0;padding:14px}
  .lcol .bet-card,.lcol .mini-card{border-bottom:1px solid rgba(255,255,255,.06)}
  .lcol .stat-card{margin-top:0;border-bottom:1px solid rgba(255,255,255,.06)}  /* sections flow — no stranded void in the middle */
  /* section labels get a small gold tick — console sections read as engineered, not floating */
  .lcol .clbl{display:flex;align-items:center;gap:7px}
  .lcol .clbl::before{content:'';width:10px;height:1px;flex-shrink:0;
    background:color-mix(in srgb,var(--accent) 55%,transparent)}
  /* The embossed cabin emblem is gone. It existed to close the leftover space at the bottom
     of a TALL left panel; .lcol is a short horizontal stake bar now, so left:50% bottom:22px
     put a 26x34 gold-rimmed box straight on top of the preset chips — the small square in the
     bet row. Deleted rather than overridden: the panel it belonged to no longer exists. */
}

/* ════════════════════════════════════════════════════════════════
   OVERLAYS / TOASTS
════════════════════════════════════════════════════════════════ */
.ov{position:fixed;inset:0;z-index:200;display:none;align-items:center;justify-content:center;
  background:rgba(4,5,8,.5);backdrop-filter:blur(9px)}
.ov.show{display:flex}
/* premium result card — dark glass, thin state-light rule across the top (no loud coloured borders) */
.ovbox{position:relative;overflow:hidden;border-radius:20px;padding:30px 38px 26px;text-align:center;
  max-width:320px;width:90%;
  background:linear-gradient(180deg,rgba(255,255,255,.045),transparent 32%),linear-gradient(180deg,#14161c,#0a0b0f);
  border:1px solid rgba(255,255,255,.09);
  box-shadow:0 30px 90px rgba(0,0,0,.75),inset 0 1px 0 rgba(255,255,255,.06);
  animation:pop .3s cubic-bezier(.4,0,.2,1)}
.ovbox::before{content:'';position:absolute;top:0;left:18%;right:18%;height:2px;border-radius:99px;
  background:linear-gradient(90deg,transparent,var(--ov-accent,#d3a54a),transparent);
  box-shadow:0 0 20px var(--ov-accent,#d3a54a)}
@keyframes pop{from{transform:scale(.6) translateY(24px);opacity:0}to{transform:scale(1);opacity:1}}
.ovt{font-family:'Bebas Neue',sans-serif;font-size:2.6rem;line-height:1;letter-spacing:3px}
.ovs{font-size:.8rem;color:var(--ink-dim);margin:7px 0 12px}
.ovd{font-family:'Share Tech Mono',monospace;font-size:.8rem;color:var(--ink-dim);margin-top:8px}
.ov-big{font-family:'Bebas Neue',sans-serif;font-size:3.4rem;color:var(--accent);line-height:1;
  font-variant-numeric:tabular-nums;text-shadow:0 0 26px var(--glow)}
.ovbtn{margin-top:18px;width:100%;border:none;border-radius:var(--r-key);font-family:'Bebas Neue',sans-serif;
  font-size:1.15rem;letter-spacing:2.5px;padding:13px;cursor:pointer;color:#fff;
  box-shadow:0 6px 18px rgba(0,0,0,.4),inset 0 1px 0 rgba(255,255,255,.18);transition:filter .12s,transform .1s}
.ovbtn:hover{filter:brightness(1.07)}
.ovbtn:active{transform:translateY(1px)}

/* ══ THE END OF A ROUND ══
   Dimmed rather than covered: the shaft stays visible behind, because what just happened to it
   is the context for the number. Less blur than the other overlays for the same reason — this
   one is a verdict on the thing behind it, not a panel in front of it. */
/* .ov.end-ov, not .end-ov: a later mobile rule sets .ov to 86% and drops the blur —
   deliberately, because blurring a full screen stuttered at round end. Two classes outrank
   one whatever the order, so this lightens the dim without bringing the blur back to a
   phone. The shaft has to stay visible: the number is a verdict on what is behind it. */
.ov.end-ov{background:rgba(4,5,8,.62);cursor:pointer}
.endr{text-align:center;padding:0 24px;animation:endIn .22s cubic-bezier(.2,.9,.3,1) both}
.endr-t{
  font-family:'Bebas Neue',sans-serif;font-size:clamp(1.5rem,6vw,2.2rem);line-height:1;
  letter-spacing:.14em;color:rgba(232,234,239,.80);
}
/* The amount is the sentence. Colour carries the meaning, so no word repeats it: a loss does
   not need to be labelled LOST when it is red and carries a minus. */
.endr-amt{
  font-family:'Bebas Neue',sans-serif;font-size:clamp(3rem,14vw,5rem);line-height:1;
  letter-spacing:.02em;margin-top:10px;font-variant-numeric:tabular-nums;
}
.endr-amt.loss{color:#ff5464;text-shadow:0 0 34px rgba(255,84,100,.32)}
.endr-amt.gain{color:#e8c37e;text-shadow:0 0 34px rgba(232,195,126,.34)}
@keyframes endIn{from{opacity:0;transform:translateY(8px) scale(.98)}to{opacity:1;transform:none}}

/* ══ THE WIN, WITH A ROOM AROUND IT ══
   Darker than the crash's dim, because this one is asking to be looked at rather than read in
   passing. The panel is the same dark glass the rest of the game uses, with one thin brass rule
   across the top — the house style for "this is a result", and the only ornament it gets. */
.ov.win-ov{background:rgba(3,4,7,.80)}
.wincard{
  position:relative;overflow:hidden;text-align:center;
  min-width:min(300px,82vw);padding:30px 34px 26px;border-radius:20px;
  background:linear-gradient(180deg,rgba(255,255,255,.05),transparent 34%),
             linear-gradient(180deg,#15171d,#0a0b0f);
  /* The win is lit by the floor it was won on: the rim, the rule across the top, the figure
     and the multiplier all take the zone's light (--accent) — amber in the lobby, magenta in
     the club, ice at the sky lounge, gold in the vault. Brass is the fallback where no zone
     is set. The figure is the accent lifted toward white so the palest lights still read. */
  border:1px solid color-mix(in srgb,var(--accent,#e8c37e) 30%,transparent);
  box-shadow:0 28px 60px rgba(0,0,0,.62), 0 0 0 1px rgba(0,0,0,.4),
             inset 0 1px 0 rgba(255,255,255,.05),
             inset 0 40px 60px -40px color-mix(in srgb,var(--accent,#e8c37e) 14%,transparent);
  animation:winIn .28s cubic-bezier(.2,.95,.3,1) both;
}
.wincard::before{
  content:'';position:absolute;top:0;left:18%;right:18%;height:2px;border-radius:99px;
  background:linear-gradient(90deg,transparent,var(--accent,#e8c37e),transparent);
  box-shadow:0 0 18px color-mix(in srgb,var(--accent,#e8c37e) 55%,transparent);
}
.wincard-t{
  font-size:.58rem;font-weight:800;letter-spacing:.32em;text-transform:uppercase;
  color:rgba(232,234,239,.52);
}
/* The payout is the headline: it is the number a player tells somebody about. */
.wincard-amt{
  font-family:'Bebas Neue',sans-serif;font-size:clamp(2.8rem,12vw,3.9rem);line-height:1;
  letter-spacing:.02em;margin-top:14px;color:color-mix(in srgb,var(--accent,#e8c37e) 85%,#fff);
  font-variant-numeric:tabular-nums;text-shadow:0 0 38px color-mix(in srgb,var(--accent,#e8c37e) 34%,transparent);
}
/* And the multiplier under it, quieter — the same fact in the game's own units. */
.wincard-mult{
  font-family:'Share Tech Mono',monospace;font-size:.92rem;letter-spacing:.18em;
  margin-top:10px;color:color-mix(in srgb,var(--accent,#e8c37e) 72%,transparent);
}
@keyframes winIn{from{opacity:0;transform:translateY(14px) scale(.96)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){ .wincard{animation:none} }
@media (prefers-reduced-motion:reduce){ .endr{animation:none} }
/* prototype-stage disclaimer chip — the panel shows how a round can be re-checked,
   it does not assert an audited "provably fair" certification */
.fair-tag{display:block;margin-top:6px;font-family:'Inter',sans-serif;font-size:.5rem;font-weight:800;
  letter-spacing:1.4px;color:rgba(242,181,68,.9)}
#crashOv .ovbox{--ov-accent:#f45b69}
#crashOv .ovt{color:#f4657a;text-shadow:0 0 24px rgba(244,91,105,.45)}
/* Steel, not candy — see the crash plate rules above. A saturated red slab was the least
   premium element on the card, and it competed with the figure it sits under. */
#crashOv .ovbtn{background:linear-gradient(180deg,rgba(255,255,255,.10),rgba(255,255,255,.03));
  border:1px solid rgba(255,255,255,.14);color:#dfe2e8}
#crashOv .ovbtn:hover{background:linear-gradient(180deg,rgba(255,255,255,.15),rgba(255,255,255,.05));
  border-color:rgba(255,255,255,.22)}
/* ── THE PAYOUT PLATE ──────────────────────────────────────────────────────
   The crash already reads as part of the building: brushed steel, a machined edge, an
   engraved figure. The win did not — it was a dark card with a mint heading and a saturated
   green slab for a button, which is the same element the crash card called out as its least
   premium part and replaced.

   Same material, different light. Brass is what this building pays in, so the money is brass;
   green survives only as the small delta, where it means 'up' rather than 'success dialog'. */
#winOv .ovbox{--ov-accent:#d9b166;padding:26px 30px 20px;border-radius:16px;
  background:
    linear-gradient(180deg,rgba(255,255,255,.055),rgba(255,255,255,0) 34%),
    repeating-linear-gradient(90deg,rgba(255,255,255,.016) 0 2px,transparent 2px 4px),
    linear-gradient(176deg,#1a1b18,#111210 58%,#0a0b09);
  border:1px solid rgba(255,255,255,.10)}
#winOv .ovbox::before{background:linear-gradient(90deg,transparent,#e8c37e,transparent);
  box-shadow:0 0 14px rgba(232,195,126,.55)}

/* engraved, with hairlines either side — the same treatment as CABLE SNAPPED */
#winOv .ovt{font-family:'Inter',sans-serif;font-size:.6rem;font-weight:800;letter-spacing:4.5px;
  line-height:1;color:#dcb877;text-shadow:none;
  display:flex;align-items:center;justify-content:center;gap:12px}
#winOv .ovt::before,#winOv .ovt::after{content:'';height:1px;flex:1;max-width:52px;
  background:linear-gradient(90deg,transparent,rgba(220,184,119,.45))}
#winOv .ovt::after{background:linear-gradient(270deg,transparent,rgba(220,184,119,.45))}

/* Sharp, not glowing — weight from size and colour, not a halo. */
#winOv .ov-big{font-family:'Share Tech Mono',monospace;font-size:3.5rem;letter-spacing:1px;
  color:#f0d089;text-shadow:0 1px 0 rgba(0,0,0,.6),0 0 18px rgba(232,195,126,.14);
  font-variant-numeric:tabular-nums;margin:16px 0 2px}

/* A receipt, not a caption: label left, figure right, hairline above each row. */
#winOv .ovd{display:grid;grid-template-columns:1fr auto;gap:3px 16px;
  margin:16px 2px 0;font-family:'Inter',sans-serif;font-size:.58rem;font-weight:800;
  letter-spacing:2.2px;text-transform:uppercase;color:rgba(232,234,239,.5)}
#winOv .ovd span{padding-top:9px;border-top:1px solid rgba(255,255,255,.07);text-align:left}
#winOv .ovd b{padding-top:9px;border-top:1px solid rgba(255,255,255,.07);
  font-family:'Share Tech Mono',monospace;font-size:.82rem;font-weight:400;letter-spacing:.5px;
  color:var(--ink);font-variant-numeric:tabular-nums}
#winOv .ovd b.up{color:#5cc98a}          /* the only green left, and it means 'up' */

/* Steel, not candy — matching the crash plate's control exactly. */
#winOv .ovbtn{background:linear-gradient(180deg,rgba(255,255,255,.10),rgba(255,255,255,.03));
  border:1px solid rgba(255,255,255,.14);color:#e6dcc6}
#winOv .ovbtn:hover{background:linear-gradient(180deg,rgba(255,255,255,.15),rgba(255,255,255,.05));
  border-color:rgba(232,195,126,.34)}
/* NEAR MISS — cashed out one floor before the cable snapped: gold card, flashing light rule */
#winOv .ovbox.near{--ov-accent:#ffd27a;border-color:rgba(255,210,122,.35)}
#winOv .ovbox.near::before{animation:nearFlash .5s ease-out 3}
#winOv .ovbox.near .ovt{color:#ffd9a0;animation:nearPop .5s cubic-bezier(.34,1.56,.64,1)}
#winOv .ovbox.near .ovt::before{background:linear-gradient(90deg,transparent,rgba(255,217,160,.6))}
#winOv .ovbox.near .ovt::after{background:linear-gradient(270deg,transparent,rgba(255,217,160,.6))}
@keyframes nearFlash{0%,100%{opacity:1}50%{opacity:.25}}
@keyframes nearPop{0%{transform:scale(.86)}60%{transform:scale(1.06)}100%{transform:scale(1)}}

/* ════════════════════════════════════════════════════════════════
   ENTRY GATE — one-line hook, then PLAY. The single place the brand speaks.
════════════════════════════════════════════════════════════════ */
.entry{position:fixed;inset:0;z-index:400;display:flex;align-items:center;justify-content:center;
  padding:max(20px,env(safe-area-inset-top)) 24px max(20px,env(safe-area-inset-bottom));
  background:
    radial-gradient(ellipse 60% 50% at 50% 38%,rgba(66,58,42,.4),transparent 72%),
    linear-gradient(180deg,#101014 0%,#08080b 55%,#050507 100%);
  opacity:1;transition:opacity .45s ease}
.entry.hide{opacity:0;pointer-events:none}
.entry-box{display:flex;flex-direction:column;align-items:center;text-align:center;max-width:340px}
/* ══ THE SIGN IS THE NAME ══

   There used to be an empty gold rectangle here with the word ELEVATOR set underneath it: an
   emblem that was a placeholder and a wordmark doing the emblem's job. One hanging sign does
   both, and it is the object the game is actually about.

   It is an <h1>, which is also the first heading this page has ever had — the accessibility
   pass found the document had none at all, and the loudest thing on the screen is the right
   one to make it. The image carries the alt text, so the heading is announced as ELEVATOR
   rather than as an unlabelled graphic.

   Width and height are on the element, so nothing below it moves while it loads. */
/* Visually gone, still announced. The heading needs a text node for assistive technology;
   the drawing beside it is aria-hidden, so this is the only thing read out. */
.vh{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap;border:0}
.entry-sign{margin:0 0 6px;line-height:0}
.entry-sign svg{
  /* Sized by the viewport, capped by the artwork: on a phone it takes the width it can get,
     on a desktop it stops before it becomes a poster. */
  /* Three limits, and the third is the one that matters. A width-only cap fits the sign to
     the screen it is on sideways and says nothing about how much room is left underneath —
     on a 360x560 phone that put the studio mark twelve pixels past the fold, with no
     scrollbar to reach it. The vh term ties the sign to the vertical room instead, which is
     the axis it actually competes for, and it works in both orientations without another
     breakpoint to forget. */
  width:min(292px,70vw,36vh);height:auto;
  /* The sign carries its own glow inside the SVG; this is the light it throws on the room. */
  filter:drop-shadow(0 10px 26px rgba(206,158,86,.20))}
/* ══ THE HOOK ══

   It was one paragraph of three sentences, wrapping wherever the width happened to put it — so
   on one screen "snaps the" ended a line and "cable" started the next, which is a break in the
   middle of the only frightening word on the page.

   Three lines now, one per beat, each an element so the break is decided here and not by the
   viewport. The first two are the terms; the third is what to do, and it is the only one lit.
   A gap rather than a rule between them: at this size a divider would be another object
   competing with the sign, and there is one hero on this screen. */
.entry-hook{display:flex;flex-direction:column;gap:5px;
  margin:22px 0 28px;font-size:.95rem;line-height:1.35;color:var(--ink-dim);
  /* Belt and braces: if a line does wrap on a very narrow phone, it wraps evenly rather than
     leaving one word stranded. */
  text-wrap:balance}
.entry-hook em{font-style:normal;color:var(--ink);
  /* Letter-spacing rather than a heavier weight — the face is already light here, and bolding
     it would make it shout where it only needs to be the last thing read. */
  letter-spacing:.3px}
.entry-play{width:100%;max-width:280px;padding:16px;border-radius:var(--r-key);cursor:pointer;
  /* Fourteen characters where there were four. The tracking comes down rather than the size:
     a smaller label on the only button on the screen reads as timidity, and Bebas at four
     pixels of tracking would have run PLAY PROTOTYPE into both edges. */
  font-family:'Bebas Neue',sans-serif;font-size:1.5rem;letter-spacing:2.4px;color:#1c1305;
  background:linear-gradient(175deg,#f0d27a,#cba049 42%,#a87c2c);
  border:1px solid rgba(255,232,170,.5);text-shadow:0 1px 0 rgba(255,255,255,.25);
  box-shadow:0 6px 22px rgba(180,140,40,.35),inset 0 1px 0 rgba(255,255,255,.45);
  transition:transform .1s,filter .15s}
.entry-play:hover{filter:brightness(1.06)}
.entry-play:active{transform:translateY(2px)}
.entry-foot{margin-top:16px;font-size:.64rem;letter-spacing:1.2px;color:var(--ink-faint)}

/* ── THE SIGNATURE ──
   Last, smallest, and deliberately dimmer than everything above it. A studio mark that
   competes with the game's own name is an advertisement; one that sits under it is a
   signature. It brightens on hover because a partner reading this will want to click it one
   day, and the mark should look like it knows that. */
.entry-by{display:flex;flex-direction:column;align-items:center;gap:7px;
  margin:22px 0 0;opacity:.82;transition:opacity .25s}
.entry-by:hover{opacity:.9}
.entry-by span{font-size:.6rem;font-weight:800;letter-spacing:2.8px;text-transform:uppercase;
  color:var(--ink-faint)}
.entry-by img{width:min(168px,44vw,20vh);height:auto;display:block}

/* provably-fair modal */
.fair-ov{z-index:230}
.fairbox{background:#0c0e12;border:1px solid rgba(255,255,255,.12);border-radius:16px;padding:22px 22px 18px;
  width:92%;max-width:440px;animation:pop .3s cubic-bezier(.4,0,.2,1)}
.fair-h{font-family:'Bebas Neue',sans-serif;font-size:1.5rem;letter-spacing:2px;color:var(--ink)}
.fair-p{font-size:.72rem;line-height:1.5;color:var(--ink-dim);margin:8px 0 14px}
.fair-l{font-size:.56rem;font-weight:800;letter-spacing:1.5px;text-transform:uppercase;color:var(--ink-faint)}
.fair-row{display:flex;gap:6px;margin:5px 0 14px}
.fair-in{flex:1;min-width:0;background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.12);border-radius:8px;
  color:var(--ink);font-family:'Share Tech Mono',monospace;font-size:.78rem;padding:8px 10px}
.fair-rnd{width:38px;border:1px solid rgba(255,255,255,.12);background:rgba(255,255,255,.05);color:var(--ink);
  border-radius:8px;cursor:pointer;font-size:1rem}
.fair-rnd:active{background:rgba(255,255,255,.14)}
.fair-grid{display:grid;grid-template-columns:auto 1fr;gap:7px 12px;align-items:center;
  background:rgba(255,255,255,.03);border-radius:10px;padding:11px 13px}
.fair-grid>span:nth-child(odd){font-size:.58rem;font-weight:700;letter-spacing:.5px;color:var(--ink-faint);text-transform:uppercase}
.fair-grid code{font-family:'Share Tech Mono',monospace;font-size:.64rem;color:var(--ink-dim);word-break:break-all;line-height:1.3}
.fair-v{font-family:'Share Tech Mono',monospace;font-size:.72rem;font-weight:700;color:var(--ink-dim)}
.fair-v.ok{color:var(--good)}.fair-v.bad{color:var(--bad)}
.fair-close{background:linear-gradient(135deg,#2a2e35,#3c424b);margin-top:14px}

.jolt-t{position:fixed;top:124px;left:50%;transform:translateX(-50%) translateY(-12px);z-index:300;
  opacity:0;pointer-events:none;border-radius:var(--r-chip);padding:4px 18px;white-space:nowrap;
  transition:opacity .18s,transform .18s;
  background:rgba(224,120,40,.14);border:1px solid rgba(224,120,40,.55);color:#e0a33a;
  font-family:'Bebas Neue',sans-serif;font-size:.9rem;letter-spacing:3px}
.jolt-t.show{opacity:1;transform:translateX(-50%) translateY(0)}
/* BANK 50% confirmation — gold pill */
.secured-t{background:rgba(230,192,116,.14);border-color:rgba(230,192,116,.55);color:#f0d492}

/* ════════════════════════════════════════════════════════════════
   HYPE EFFECTS — escalating juice, kept tasteful
════════════════════════════════════════════════════════════════ */
/* header utility buttons */
.sfx-btn{width:36px;height:36px;border-radius:var(--r-ctl);border:1px solid var(--panel-line);
  background:linear-gradient(180deg,rgba(255,255,255,.04),transparent 60%),rgba(10,12,18,.66);
  color:var(--ink);font-size:.95rem;cursor:pointer;backdrop-filter:blur(10px);
  display:flex;align-items:center;justify-content:center;transition:transform .1s,border-color .15s,opacity .15s}
.sfx-btn:active{transform:scale(.92)}
/* muted state must be unmistakable, not just dimmer (QA point 7) */
.sfx-btn.muted{position:relative;opacity:.62;color:var(--ink-dim);
  border-color:rgba(244,91,105,.4);background:rgba(244,91,105,.07)}
.sfx-btn.muted::after{content:'';position:absolute;left:16%;right:16%;top:50%;height:2px;border-radius:2px;
  background:#f4657a;transform:rotate(-45deg);box-shadow:0 0 6px rgba(244,91,105,.6)}
.trust-btn{opacity:.66}                 /* fairness sits quietly; still a clear touch target */
.trust-btn:hover{opacity:1;border-color:rgba(255,232,170,.3)}

/* multiplier "pop" when it ticks up + bigger pop at milestones */
@keyframes mxPop{0%{transform:scale(1)}45%{transform:scale(1.22)}100%{transform:scale(1)}}
.cab-mult.pop{animation:mxPop .3s ease-out}

/* floating milestone banner near the cabin */
.milestone{position:fixed;left:50%;top:46%;z-index:190;pointer-events:none;opacity:0;
  transform:translate(-50%,-50%);font-family:'Bebas Neue',sans-serif;font-size:clamp(2rem,5vw,3.2rem);
  letter-spacing:2px;color:var(--accent);text-shadow:0 0 26px var(--accent),0 0 60px var(--glow);white-space:nowrap}
.milestone.show{animation:mileShow 1.05s cubic-bezier(.22,1,.36,1)}
@keyframes mileShow{0%{opacity:0;transform:translate(-50%,-40%) scale(.5)}
  22%{opacity:1;transform:translate(-50%,-52%) scale(1.12)}
  60%{opacity:1;transform:translate(-50%,-60%) scale(1)}
  100%{opacity:0;transform:translate(-50%,-86%) scale(1)}}

/* cabin glow tiers — intensify with the multiplier */
.car-body{transition:box-shadow .6s ease}
.car.hype1 .car-body{box-shadow:0 0 0 1px #0d0b06,-5px 0 12px rgba(0,0,0,.55),5px 0 12px rgba(0,0,0,.55),0 0 24px var(--glow)}
.car.hype2 .car-body{box-shadow:0 0 0 1px #0d0b06,-5px 0 12px rgba(0,0,0,.55),5px 0 12px rgba(0,0,0,.55),0 0 36px var(--glow),0 0 64px var(--glow)}
/* The hot-cabin glow used to animate box-shadow, which repaints a 104px blur on every frame —
   on the one element that is also translating up the shaft. The blur is now painted once into
   a pseudo-element and only its opacity animates, which the compositor handles on its own. */
.car.hype3 .car-body{box-shadow:0 0 0 1px #0d0b06,-5px 0 12px rgba(0,0,0,.55),5px 0 12px rgba(0,0,0,.55),0 0 30px var(--accent),0 0 52px var(--glow)}
.car.hype3 .car-body::after{content:'';position:absolute;inset:0;border-radius:inherit;
  pointer-events:none;box-shadow:0 0 56px var(--accent),0 0 104px var(--accent);
  animation:carGlow 1s ease-in-out infinite}
@keyframes carGlow{0%,100%{opacity:0}50%{opacity:1}}

/* CASH OUT button — gentle breathing while live, draws the eye */
/* same treatment: the breathing glow is a pseudo-element fading in and out, not an animated
   box-shadow repainting the button every frame for the whole length of a round */
.btn-co.on{position:relative;
  box-shadow:0 5px 18px rgba(45,168,85,.32),inset 0 1px 0 rgba(255,255,255,.18)}
.btn-co.on::after{content:'';position:absolute;inset:0;border-radius:inherit;
  pointer-events:none;box-shadow:0 6px 26px rgba(45,168,85,.6);
  animation:coGlow 1.6s ease-in-out infinite}
@keyframes coGlow{0%,100%{opacity:0}50%{opacity:1}}
.btn-co.bump{animation:coBump .28s ease-out}
@keyframes coBump{0%{transform:scale(1)}45%{transform:scale(1.035)}100%{transform:scale(1)}}

/* danger heartbeat — subtle red edge pulse when crash risk is high */
.danger-vig{position:fixed;inset:0;z-index:188;pointer-events:none;opacity:0;
  box-shadow:inset 0 0 120px rgba(224,60,60,.55);transition:opacity .4s}
.danger-vig.on{animation:heartbeat 1.15s ease-in-out infinite}
@keyframes heartbeat{0%,100%{opacity:.05}50%{opacity:.18}}

/* ════════════════════════════════════════════════════════════════
   STATE CINEMATICS — danger, crash and cash-out as unmistakable beats
   (transform/opacity only; the cabin itself responds to the game state)
════════════════════════════════════════════════════════════════ */
/* DANGER — a red glow gathers under the cabin and breathes with the heartbeat */
.car::before{content:'';position:absolute;inset:-24px -22px;z-index:-1;border-radius:20px;opacity:0;
  background:radial-gradient(ellipse at 50% 55%,rgba(224,60,60,.18),transparent 70%);
  transition:opacity .6s;pointer-events:none}
body.danger .car::before{opacity:1;animation:dangerBreath 1.15s ease-in-out infinite}
@keyframes dangerBreath{0%,100%{opacity:.35}50%{opacity:.7}}

/* ── SUSPENSION: a loaded car is never perfectly still. Tiny vertical float while riding,
      applied to the body only so the cabin's own transform (position/scale) is untouched. ── */
body.playing .car-body{animation:suspend 2.7s ease-in-out infinite}
@keyframes suspend{0%,100%{transform:translateY(0)}35%{transform:translateY(.9px)}70%{transform:translateY(-.7px)}}
/* the cabin dips and recovers as each floor passes — weight, not a jump */
.car.floorpass .car-body{animation:floorDip .34s cubic-bezier(.3,.9,.4,1)}
@keyframes floorDip{0%{transform:translateY(0)}30%{transform:translateY(2.2px)}
  62%{transform:translateY(-1.1px)}100%{transform:translateY(0)}}

/* CRASH — the cabin light fails and the interior dims while everything goes wrong */
.car.failing .cab-ceiling::before{animation:lightFail .4s steps(3,end) 2}
.car.failing .car-cabin{filter:brightness(.72)}
@keyframes lightFail{0%,100%{opacity:1}30%{opacity:.15}60%{opacity:.8}80%{opacity:.1}}

/* CRASH — the read-out dies: drains to red and flickers out like a failing sign */
.cab-mult.mx-dead{color:#ff5460;
  text-shadow:0 0 16px rgba(255,60,70,.55),0 2px 4px rgba(0,0,0,.8);
  animation:mxDie .85s steps(1) forwards}
@keyframes mxDie{0%{opacity:1}14%{opacity:.25}22%{opacity:1}34%{opacity:.15}
  46%{opacity:.8}60%{opacity:.1}74%{opacity:.45}100%{opacity:.08}}

/* CASH OUT — the read-out turns gold and the cabin releases one golden burst */
.cab-mult.mx-cashed{color:#ffe9ad;
  text-shadow:0 0 14px rgba(255,214,120,.85),0 0 42px rgba(230,180,90,.5),0 2px 4px rgba(0,0,0,.7)}
.car.car-win::after{content:'';position:absolute;inset:-34px -30px;z-index:-1;border-radius:24px;
  background:radial-gradient(ellipse at 50% 50%,rgba(255,216,130,.55),transparent 70%);
  animation:winBurst .95s ease-out forwards;pointer-events:none}
@keyframes winBurst{0%{opacity:0;transform:scale(.7)}25%{opacity:1;transform:scale(1.05)}100%{opacity:0;transform:scale(1.3)}}

/* win confetti */
.confetti{position:fixed;inset:0;z-index:210;pointer-events:none;overflow:hidden}
.confetti i{position:absolute;top:42%;left:50%;width:9px;height:14px;border-radius:2px;opacity:0;
  will-change:transform,opacity}
.confetti i.go{animation:conFall var(--d,1.4s) cubic-bezier(.2,.7,.4,1) forwards}
/* sparks off the snapping cables — small, hot, short-lived */
.confetti i.spark{top:56%;width:3px;height:3px;border-radius:50%;box-shadow:0 0 6px currentColor}
.confetti i.spark.go{animation:sparkFly var(--d,.7s) cubic-bezier(.15,.7,.4,1) forwards}
@keyframes sparkFly{0%{opacity:1;transform:translate(0,0) scale(1.2)}
  100%{opacity:0;transform:translate(var(--x,0),var(--y,90px)) scale(.2)}}
@keyframes conFall{0%{opacity:1;transform:translate(0,0) rotate(0)}
  100%{opacity:0;transform:translate(var(--x,0),var(--y,400px)) rotate(var(--r,540deg))}}

/* ════════════════════════════════════════════════════════════════
   RESPONSIVE — phone = vertical stack, elevator stays the hero
════════════════════════════════════════════════════════════════ */
/* The phone composition is the product. Desktop now gets the same stacked column rather than
   a second, thinner-feeling layout with side rails — one thing to design, one thing to test,
   and the tower reads the same everywhere. Phone landscape keeps its own composition below. */
@media(max-width:700px) and (orientation:portrait){
  /* app-shell: fill the screen, respect the notch + home indicator (no browser feel) */
  .shell{display:flex;flex-direction:column;max-width:none;width:100%;height:100dvh;gap:7px;
    padding:max(7px,env(safe-area-inset-top)) max(9px,env(safe-area-inset-right))
            calc(10px + env(safe-area-inset-bottom,0px)) max(9px,env(safe-area-inset-left))}   /* CTA clear of the gesture bar (QA point 1) */
  .hdr{order:0;flex:0 0 auto}
  .sfx-btn{width:40px;height:40px}     /* comfortable thumb targets */
  .bal{padding:6px 14px 6px 7px}
  .bal-num{font-size:1.04rem}
  .status-cap{max-width:46%;padding:5px 11px;gap:6px}
  .cap-zone{font-size:.56rem;letter-spacing:1.2px}

  /* secondary side content is desktop-only → on mobile the elevator gets the full screen */
  .rcol{display:none}

  /* elevator fills the rest */
  .stage{order:2;flex:1 1 auto;min-height:0;gap:0}
  .scol{flex:1 1 auto;max-width:none}
  .floor-row{height:128px}

  /* THE multiplier is the hero — bigger cabin, bigger read-out, nothing competes */
  .car{width:204px}
  .car-roof{width:186px}
  .car-body{width:204px;height:164px}
  .car-base{width:204px}
  .cab-mult{font-size:clamp(60px,16vw,88px);letter-spacing:1px}   /* hero scales with device width, stays largest live text */

  /* lower deck = ONE control system: a single panel holding the bet stepper + risk, split by a divider */
  /* column, not row: it only ever held the bet card, so the direction never showed — the
     moment a second child arrived they sat side by side at half width each */
  .lcol{order:3;flex:0 0 auto;flex-direction:row;align-items:stretch;gap:0;
    background:linear-gradient(180deg,rgba(255,255,255,.035),transparent 55%),rgba(9,11,16,.6);
    border:1px solid var(--panel-line);border-top-color:color-mix(in srgb,var(--accent) 16%,var(--panel-line));
    border-radius:14px;padding:10px;backdrop-filter:blur(10px);
    box-shadow:0 8px 26px rgba(0,0,0,.4),inset 0 1px 0 rgba(255,255,255,.04)}
  .lcol .card{background:none;border:none;box-shadow:none;backdrop-filter:none;border-radius:0;padding:0 12px;min-width:0}
  .lcol .bet-card{flex:1.2 1 0;padding-left:2px}    /* basis 0 → split stays proportional, content can never push the risk card off-screen */
  .lcol .mini-card{flex:1 1 0;justify-content:center;border-left:1px solid var(--panel-line);padding-right:2px}
  .lcol .stat-card{display:none}
  .adj{width:34px;height:34px}
  .bnum{font-size:1.45rem}
  .pr{padding:7px 0;font-size:.66rem}
  .rsk-lbl{font-size:.6rem}
  .rbadge{font-size:.58rem;padding:3px 9px}

  /* more air between the three zones so nothing feels compressed (item 9) */
  .shell{gap:11px}
  .lcol{margin-bottom:2px}

  /* the status panel is worth its space on mobile too — it sits above the action bar */
  .bot-mid{order:3;flex:0 0 auto;display:flex;flex-direction:row;align-items:baseline;
    justify-content:center;gap:10px;padding:7px 12px;text-align:left}
  .bot-mid .bc-lbl{font-size:.5rem}
  .bot-mid .bc-val{font-size:1.3rem}
  .bot-mid .bc-state{margin-right:auto}

  /* stats collapse to a compact, tappable summary on small screens (item 4) */
  .lcol .stat-card{display:block;padding:10px 12px;cursor:pointer;flex:0 0 auto;
    border-left:1px solid var(--panel-line);min-width:74px}
  .lcol .stat-card .clbl{margin-bottom:0;text-align:center}
  .lcol .stat-card .clbl::after{content:' ▾';opacity:.6}
  .lcol .stat-card.open .clbl::after{content:' ▴'}
  .lcol .stat-card .srow{display:none}
  .lcol .stat-card.open{position:absolute;left:9px;right:9px;bottom:100%;margin-bottom:8px;
    z-index:30;background:#12141b;border:1px solid var(--panel-line);border-radius:12px;
    padding:12px 14px;box-shadow:0 12px 30px rgba(0,0,0,.6)}
  .lcol .stat-card.open .srow{display:flex}
  .lcol{position:relative}

  /* ONE dominant, state-driven action cluster filling the thumb zone */
  .bot{order:4;flex:0 0 auto;display:flex;gap:9px}
  .btn-st{flex:1 1 auto;padding:16px 8px;font-size:1.5rem}
  .co-wrap{display:none}                             /* idle → only START shows */
  body.playing .btn-st{display:none}                 /* ascending → START steps aside */
  body.playing .co-wrap{display:flex;flex:1 1 auto}
  body.playing .btn-co{display:flex;padding:14px 8px}
  body.playing .co-t{font-size:1.5rem}
  body.playing .btn-safe.on{padding:10px 6px}

  /* calmer ambience — the full-screen tier glows dominate a small display, so soften them */
  .peril{opacity:calc(var(--tier,0) * .22);
    box-shadow:inset 0 0 90px rgba(214,42,42,.32),inset 0 0 30px rgba(214,42,42,.14)}
  .peril::after{box-shadow:inset 0 0 60px rgba(255,46,46,.38)}
  .luxe{opacity:calc(var(--tier,0) * .34)}
  .danger-vig{box-shadow:inset 0 0 80px rgba(224,60,60,.38)}
  .danger-vig.on{animation-duration:1.5s}

}

/* ── SHORT PHONES — reclaim height for the shaft ──
   On a 640px-tall handset the controls panel was ending up taller than the elevator, which
   inverts the whole point: the tower is the hero, the controls are support. Everything here
   trims chrome and spacing only — not one touch target shrinks. */
@media (orientation:portrait) and (max-height:700px){
  .bet-card > .clbl{display:none}            /* the −/number/+ stepper with presets under it needs no caption */
  .bet-ctrl{margin-bottom:6px;padding:3px}
  .adj{width:34px;height:34px}
  .pr{padding:6px 0}
  .lcol{gap:7px}
  /* The hint goes on a short screen, and the tower keeps the height.

     It was briefly kept here on the grounds that the stake block had become one row. It is
     three rows again, and with the hint the left column grew to 301px in a 419px viewport —
     which pushed the shaft to zero height. The tower is the hero; a caption is not worth it.
     The second tap is still discoverable by tapping, which is how anyone finds it anyway. */
  .prs{margin-top:7px}
  .stake-row{gap:12px}
  /* both switches on one line — worth 28px, which is the difference between the tower
     being the biggest thing on screen and the controls taking that place */
  .sw-grid{display:flex;gap:10px;align-items:center}
  .lbl-long{display:none}
  .lbl-short{display:inline}
  .sw-grid .sw-state{display:none}      /* the knob position already says on or off */
}


/* LOBBY sits dead centre because the two side groups carry equal weight, not because it is
   pinned there: the balance is far wider than the icons opposite it, so left-to-right
   distribution alone would push it off. Flow-based, so the capsule's own zone-change
   animation still owns its transform. */
.hdr-r{display:flex;align-items:center;gap:8px;justify-content:flex-end}
.hdr-l,.hdr-r{flex:0 0 auto;min-width:0}
.hdr .status-cap{flex:0 0 auto}

/* ══════════════ STAKE ══════════════
   A wager selector, not a currency field. The number is the component: no unit symbol, no
   framed input, no wallet chrome. The steppers are quiet discs either side so the figure
   keeps the attention. */
/* Fills its card. The old row was flanked by six chips that took up the rest; with those
   gone the panel was left sitting at its content width in a card twice as wide. */
.stake{display:flex;flex-direction:column;align-items:center;gap:1px}
/* The number between the two calls, on one line. Deleted while the panel was a different shape;
   without it the buttons stack above and below the read-out, which is a column of three
   controls where there should be one row. */
.stake-row{display:flex;align-items:center;justify-content:center;gap:14px;width:100%}
.stake-lbl{font-size:.52rem;font-weight:800;letter-spacing:3.4px;text-transform:uppercase;
  color:var(--ink-faint)}

/* A circle is a pill with nowhere left to go. These are the two most-pressed controls in
   the game and they now match the field between them rather than floating beside it. */
.stake-adj{width:42px;height:42px;border-radius:var(--r-ctl);flex:0 0 auto;cursor:pointer;
  display:flex;align-items:center;justify-content:center;
  font-size:1.4rem;line-height:1;font-weight:400;color:var(--ink);
  background:linear-gradient(180deg,rgba(255,255,255,.09),rgba(255,255,255,.02));
  border:1px solid rgba(255,232,170,.18);
  box-shadow:0 3px 10px rgba(0,0,0,.4),inset 0 1px 0 rgba(255,255,255,.14);
  transition:border-color .14s,background .14s,transform .1s}
.stake-adj:hover{border-color:rgba(255,232,170,.45)}
.stake-adj:active{transform:scale(.93)}
/* the hero: big, centred, gold-lit, and it never looks like a text box */
.stake .bnum{flex:0 1 auto;width:auto;min-width:2.5ch;max-width:100%;text-align:center;
  font-family:'Bebas Neue',sans-serif;font-size:2.9rem;line-height:1;letter-spacing:1.5px;
  color:#fff;background:none;border:0;outline:none;padding:0;
  text-shadow:0 0 22px color-mix(in srgb,var(--accent) 42%,transparent)}
.stake .bnum:focus{text-shadow:0 0 28px color-mix(in srgb,var(--accent) 72%,transparent)}
.bet-card .prs{margin-top:10px}

/* ══════════════ RIDERS PANEL ══════════════
   MOBILE FIRST: on a phone this is a sheet that slides up over the game, because vertical
   space there belongs to the shaft and a permanent panel would take it. The rider count in
   the floor strip is its handle. On desktop the same markup sits in the column the grid
   already reserves, so nothing else has to move. */
.riders{display:flex;flex-direction:column;min-height:0;
  background:linear-gradient(180deg,rgba(255,255,255,.04),rgba(255,255,255,0) 30%),rgba(9,11,16,.92);
  border:1px solid var(--panel-line);border-radius:14px;overflow:hidden}
.rd-grab,.rd-close{display:none}

.ppl-tabs{display:flex;border-bottom:1px solid var(--panel-line)}
.ppl-tab{flex:1;padding:9px 4px;cursor:pointer;background:none;border:0;
  font-size:.55rem;font-weight:800;letter-spacing:1.1px;text-transform:uppercase;color:var(--ink-faint);
  border-bottom:2px solid transparent;transition:color .14s,border-color .14s}
.ppl-tab.on{color:#fff;border-bottom-color:color-mix(in srgb,var(--accent) 70%,transparent)}
.ppl-head{display:flex;justify-content:space-between;padding:7px 11px;
  font-size:.52rem;font-weight:800;letter-spacing:1.2px;text-transform:uppercase;color:var(--ink-faint)}
.ppl-list{flex:1 1 auto;min-height:0;overflow-y:auto;padding:0 8px 8px}
.prow{display:flex;align-items:center;gap:8px;padding:6px 4px;
  font-size:.64rem;border-bottom:1px solid rgba(255,255,255,.04)}
.prow:last-child{border-bottom:none}
.prow.me{background:color-mix(in srgb,var(--accent) 12%,transparent);border-radius:6px}
.p-who{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--ink-dim)}
.prow.me .p-who{color:#fff;font-weight:700}
.p-out{font-family:'Share Tech Mono',monospace;color:#8fdcbb}
.p-in{font-family:'Share Tech Mono',monospace;color:var(--ink-faint)}
.ppl-empty{padding:16px 4px;text-align:center;font-size:.6rem;color:var(--ink-faint)}

/* the last cabins, as floors — the number a building is remembered by */
.rd-hist{display:flex;flex-wrap:wrap;gap:4px;padding:8px 9px;border-top:1px solid var(--panel-line)}
/* ══ THE LAST ROUNDS ══

   Aviator's idea, in this building's colours. Theirs is a rainbow — blue, purple, pink — which
   reads as a legend you have to learn. Here the scale is the one the game already speaks in:
   dim for a cabin that barely left, brass through the middle, bright gold when it went high.
   Nothing to learn, because it is the same gold the multiplier climbs into during a ride.

   Newest on the left, and the row is masked at its right edge rather than cut, so the oldest
   fades out instead of being sliced in half by the balance. */
.hist-strip{
  min-width:0;display:flex;align-items:center;gap:5px;
  overflow-x:auto;overflow-y:hidden;scrollbar-width:none;
  -webkit-mask-image:linear-gradient(90deg,#000 82%,transparent);
  mask-image:linear-gradient(90deg,#000 82%,transparent);
}
.hist-strip::-webkit-scrollbar{display:none}
.hchip{
  flex:0 0 auto;padding:2px 7px;border-radius:var(--r-chip);
  font-family:'Share Tech Mono',monospace;font-size:.6rem;letter-spacing:.5px;
  border:1px solid rgba(255,255,255,.08);background:rgba(255,255,255,.03);
  color:rgba(232,234,239,.5);
}
/* barely left the ground */
.hchip.h-low{color:rgba(232,234,239,.46)}
/* the working middle of the building */
.hchip.h-mid{color:#e0b878;border-color:rgba(232,195,126,.26);background:rgba(232,195,126,.06)}
/* the ones worth remembering */
.hchip.h-high{color:#ffd489;border-color:rgba(255,212,137,.45);background:rgba(255,212,137,.10);
  box-shadow:0 0 12px rgba(255,212,137,.14)}

/* The count in the floor strip is a real control on a phone. Padding plus matching negative
   margin gives it a 44px finger target without making the strip any taller — the global
   min-height for touch buttons would otherwise push the strip down and cost the shaft 21px. */
.tower-count{margin:-18px 0 -18px 8px;padding:18px 9px;border-radius:var(--r-chip);cursor:pointer;
  min-height:0;display:inline-flex;align-items:center;line-height:1;
  background:none;border:0;
  font-size:.5rem;font-weight:800;letter-spacing:1.3px;text-transform:uppercase;color:var(--ink-dim)}
.tower-count::after{content:'';display:inline-block;width:0}
.tower-count[hidden]{display:none}
.tower-count:hover{color:#fff;border-color:color-mix(in srgb,var(--accent) 42%,var(--panel-line))}

/* ── PHONE: the panel sits BELOW the game and you scroll to it ──
   The game still occupies exactly one screen — the shaft keeps every pixel it had — and the
   panel lives underneath in normal flow. Scrolling reaches it; nothing overlays, nothing
   resizes, so the layout cannot shift under the player mid-ride. */
@media (max-width:999px){
  /* The panel is a SIBLING of the shell, not a child: inside it, it competed with the game
     for the same 100dvh and crushed the shaft to 36px. Outside, the shell keeps exactly one
     screenful — the shaft is untouched — and the panel simply lives below the fold. */
  html,body{overflow-y:auto;overflow-x:hidden;height:auto;min-height:100%}
  body{display:block}
  .shell{height:100dvh;min-height:100dvh}
  .rcol{display:block;position:static;transform:none;pointer-events:auto;
    padding:0 max(9px,env(safe-area-inset-left)) calc(16px + env(safe-area-inset-bottom,0px));
    margin-top:10px}
  .riders,.ppl-list{max-height:none}
  .rd-grab,.rd-close,.rd-scrim{display:none}
  .tower-count{pointer-events:none}   /* nothing to open — the panel is just further down */
}
/* ── DESKTOP ─────────────────────────────────────────────────────────────
   A spacer column mirrors the riders panel, so the lift, the zone pill and the
   action bar sit on the viewport's centre line instead of 126px left of it.
   The bet panel leaves the left column and becomes a compact bar directly above
   START — horizontal, because stacking it would cost the shaft about 100px. */
@media (min-width:1000px){
  body{display:grid;grid-template-columns:240px minmax(0,1fr) 240px;
    align-items:stretch;gap:12px;padding:10px 14px}
  .shell{grid-column:2;width:100%;max-width:980px;margin:0 auto;
    grid-template-rows:52px minmax(0,1fr) auto auto}
  .rcol{grid-column:3;display:flex;align-self:center;max-height:82vh;
    min-height:min(460px,74vh);grid-row:auto}
  .riders{flex:1 1 auto}
  .rd-scrim{display:none}

  .stage{grid-column:1/-1;grid-row:2}          /* the lift owns the shell's full width */

  .lcol{grid-column:1/-1;grid-row:3;flex-direction:row;align-items:center;gap:0;
    width:100%;max-width:900px;margin:0 auto;overflow:visible}
  .lcol .bet-card{flex:1 1 auto;display:flex;flex-direction:row;align-items:center;
    gap:18px;padding:8px 16px}
  .lcol .bet-card .stake{flex:0 0 auto;display:flex;align-items:center;gap:14px}
  .lcol .bet-card .stake-lbl{margin-bottom:0}
  /* the number is the tallest thing in the bar; unclamped it stretches to 565px and
     costs the shaft 50px of height, so it is sized to its content here */
  .lcol .bet-card .stake-row{flex:0 0 auto;gap:10px}
  .lcol .bet-card .bnum{flex:0 0 140px;width:140px;font-size:1.9rem}
  .lcol .bet-card .stake-adj{width:34px;height:34px;font-size:1.05rem}
  .lcol .bet-card .prs{flex:1 1 auto;margin:0;justify-content:flex-end}
  .bot{grid-row:4}
}

/* ══════════════ MENU ══════════════
   A drawer off the right edge in the building's own material: brushed dark steel, a machined
   gold hairline, no casino gloss. The cabin stays visible behind it — you never lose sight of
   the round you are in. */
.burger{width:38px;height:38px;flex:0 0 auto;margin-left:8px;border-radius:var(--r-ctl);cursor:pointer;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;
  background:rgba(10,12,18,.66);border:1px solid var(--panel-line);
  transition:border-color .15s,background .15s}
.burger:hover{border-color:color-mix(in srgb,var(--accent) 45%,var(--panel-line))}
.burger span{display:block;width:16px;height:1.5px;border-radius:2px;background:var(--ink-dim);
  transition:background .15s}
.burger:hover span{background:var(--ink)}

.menu-scrim{position:fixed;inset:0;z-index:210;background:rgba(3,4,7,.55);
  animation:scrimIn .22s ease}
.menu-scrim[hidden]{display:none}
@keyframes scrimIn{from{opacity:0}to{opacity:1}}

.menu{position:fixed;top:0;right:0;bottom:0;z-index:220;width:min(360px,88vw);
  display:flex;flex-direction:column;
  background:
    linear-gradient(180deg,rgba(255,255,255,.045),rgba(255,255,255,0) 26%),
    repeating-linear-gradient(90deg,rgba(255,255,255,.014) 0 2px,transparent 2px 4px),
    linear-gradient(176deg,#15171c,#0e1014 60%,#090b0e);
  border-left:1px solid rgba(255,255,255,.10);
  box-shadow:-24px 0 60px rgba(0,0,0,.6);
  padding-top:env(safe-area-inset-top,0px);padding-bottom:env(safe-area-inset-bottom,0px);
  animation:menuIn .26s cubic-bezier(.22,.9,.3,1)}
.menu[hidden]{display:none}
@keyframes menuIn{from{transform:translateX(100%)}to{transform:translateX(0)}}
/* the one gold detail — a machined edge, not a glow */
.menu::before{content:'';position:absolute;left:0;top:0;bottom:0;width:1px;
  background:linear-gradient(180deg,transparent,rgba(234,161,64,.5) 18%,rgba(234,161,64,.5) 82%,transparent)}

.menu-top{display:flex;align-items:center;gap:10px;padding:15px 16px 13px;
  border-bottom:1px solid rgba(255,255,255,.07)}
.menu-title{flex:1;font-family:'Bebas Neue',sans-serif;font-size:1.2rem;letter-spacing:3px;color:#fff}
.menu-back,.menu-x{width:32px;height:32px;border-radius:var(--r-ctl);cursor:pointer;flex:0 0 auto;
  background:rgba(255,255,255,.05);border:1px solid var(--panel-line);color:var(--ink-dim);font-size:1rem}
.menu-back{order:-1;font-size:1.35rem;line-height:1}
.menu-back[hidden]{display:none}
.menu-back:hover,.menu-x:hover{color:#fff;border-color:color-mix(in srgb,var(--accent) 45%,var(--panel-line))}

.menu-body{flex:1 1 auto;overflow-y:auto;padding:12px 12px 20px}
.menu-body[hidden]{display:none}
.menu-group{border:1px solid var(--panel-line);border-radius:12px;overflow:hidden;margin-bottom:12px;
  background:rgba(255,255,255,.022)}
.menu-row,.menu-item{display:flex;align-items:center;gap:11px;width:100%;
  padding:12px 13px;border:0;background:none;cursor:default;color:var(--ink);
  font-size:.78rem;font-family:'Inter',sans-serif;text-align:left;
  border-bottom:1px solid rgba(255,255,255,.05)}
.menu-row:last-child,.menu-item:last-child{border-bottom:none}
.menu-item{cursor:pointer;transition:background .13s}
.menu-item:hover{background:rgba(255,255,255,.045)}
.mr-l{flex:1;display:flex;align-items:center;gap:11px}
/* Line icons, not emoji: emoji render in each platform's own colour and weight, so the column
   never sat still. These are strokes in the row's own colour. */
.mi{font-style:normal;width:22px;height:22px;flex:0 0 auto;display:grid;place-items:center;
  color:var(--ink-dim)}
.mi svg{width:20px;height:20px;display:block;fill:none;stroke:currentColor;stroke-width:1.5;
  stroke-linecap:round;stroke-linejoin:round}
.menu-item:hover .mi{color:var(--ink)}
.mi-go{margin-left:auto;color:var(--ink-faint);font-size:1.1rem;line-height:1}
.menu-foot{text-align:center;font-size:.54rem;letter-spacing:1.6px;text-transform:uppercase;
  color:var(--ink-faint);line-height:1.8;margin-top:6px}

/* sub-pages */
.ms-h{font-family:'Bebas Neue',sans-serif;font-size:1rem;letter-spacing:2.4px;color:#fff;
  margin:14px 2px 8px}
.ms-h:first-child{margin-top:2px}
.ms-p{font-size:.74rem;line-height:1.65;color:var(--ink-dim);margin:0 2px 10px}
.ms-step{display:flex;gap:11px;padding:9px 2px;border-bottom:1px solid rgba(255,255,255,.05);
  font-size:.74rem;line-height:1.55;color:var(--ink-dim)}
.ms-step b{display:block;color:#fff;font-weight:700;margin-bottom:2px}
.ms-n{flex:0 0 22px;height:22px;border-radius:50%;display:flex;align-items:center;justify-content:center;
  font-family:'Share Tech Mono',monospace;font-size:.66rem;color:#0d0f13;
  background:linear-gradient(180deg,#f0d27a,#cba049)}
.ms-kv{display:flex;justify-content:space-between;gap:12px;padding:9px 2px;
  border-bottom:1px solid rgba(255,255,255,.05);font-size:.74rem;color:var(--ink-dim)}
.ms-kv b{color:#fff;font-weight:700;font-family:'Share Tech Mono',monospace;
  word-break:break-all;text-align:right}
.ms-note{font-size:.66rem;line-height:1.6;color:var(--ink-faint);
  border-left:2px solid rgba(234,161,64,.5);padding:2px 0 2px 10px;margin:10px 2px}
.ms-empty{text-align:center;color:var(--ink-faint);font-size:.72rem;padding:26px 0}
.hrow{display:grid;grid-template-columns:1fr auto auto;gap:8px;align-items:center;
  padding:9px 2px;border-bottom:1px solid rgba(255,255,255,.05);font-size:.7rem}
.hrow .h-when{color:var(--ink-faint);font-size:.6rem}
.hrow .h-mx{font-family:'Share Tech Mono',monospace;color:var(--ink-dim)}
.hrow .h-amt{font-family:'Share Tech Mono',monospace;text-align:right;min-width:74px}
.hrow.win .h-amt{color:#42d06a}.hrow.loss .h-amt{color:#f04141}
.h-tags{display:flex;gap:4px;margin-top:3px}
.h-tag{font-size:.5rem;letter-spacing:.8px;padding:1px 5px;border-radius:4px;
  border:1px solid rgba(234,161,64,.35);color:#f0c479}

/* the player asked for no animation — honour it everywhere, not just here */
body.no-anim *{animation:none !important;transition:none !important}

/* ── RECENT RIDES ── the strip Aviator fills with multipliers. A building remembers how high
   it got, so these are floors; the colour says how far, which is the only thing worth
   encoding at this size. */
/* The strip's desktop rules used to live here, from when it sat in the left column. It is in
   the header bar now, at every width, and one set of rules describes it. */

/* ── PEOPLE ── who is aboard, how the last cabin ended, who got highest today */
.people{order:2;flex:0 0 auto;display:flex;flex-direction:column;gap:0;
  background:rgba(9,11,16,.6);border:1px solid var(--panel-line);border-radius:12px;overflow:hidden}
.ppl-tabs{display:flex;gap:0;border-bottom:1px solid var(--panel-line)}
.ppl-tab{flex:1;padding:8px 4px;cursor:pointer;background:none;border:0;
  font-size:.56rem;font-weight:800;letter-spacing:1.1px;text-transform:uppercase;color:var(--ink-faint);
  border-bottom:2px solid transparent;transition:color .14s,border-color .14s}
.ppl-tab.on{color:#fff;border-bottom-color:color-mix(in srgb,var(--accent) 70%,transparent)}
.ppl-head{display:flex;justify-content:space-between;padding:6px 11px;
  font-size:.54rem;font-weight:800;letter-spacing:1.2px;text-transform:uppercase;color:var(--ink-faint)}
.ppl-list{max-height:118px;overflow-y:auto;padding:0 7px 7px}
.prow{display:flex;align-items:center;gap:8px;padding:5px 4px;border-radius:7px;
  font-size:.62rem;border-bottom:1px solid rgba(255,255,255,.04)}
.prow:last-child{border-bottom:none}
.prow.me{background:color-mix(in srgb,var(--accent) 12%,transparent)}
.p-who{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--ink-dim)}
.prow.me .p-who{color:#fff;font-weight:700}
.p-fl{font-family:'Share Tech Mono',monospace;color:var(--ink-dim)}
.p-out{font-family:'Share Tech Mono',monospace;color:#8fdcbb}
.p-in{font-family:'Share Tech Mono',monospace;color:var(--ink-faint)}
.ppl-empty{padding:12px 4px;text-align:center;font-size:.58rem;color:var(--ink-faint)}

/* ── UTILITY ROW ── sound + round verification, in the controls rather than the top strip,
   where the browser chrome and the notch were clipping them on a phone. */
.util-row{display:flex;gap:8px;margin-top:9px}
.util-btn{flex:1;min-width:0;display:flex;align-items:center;justify-content:center;gap:7px;
  padding:9px 6px;border-radius:10px;cursor:pointer;
  background:rgba(255,255,255,.035);border:1px solid var(--panel-line);color:var(--ink-dim);
  font-size:.6rem;font-weight:800;letter-spacing:1.1px;text-transform:uppercase;
  transition:background .14s,border-color .14s,color .14s}
.util-btn:hover{color:var(--ink);border-color:color-mix(in srgb,var(--accent) 38%,var(--panel-line))}
.util-ico{font-size:.95rem;line-height:1}
.util-btn.muted{color:var(--ink-faint)}
.util-btn.muted .util-ico{opacity:.45}

/* ── PHONE PERFORMANCE — expensive effects off on touch devices in BOTH orientations ── */
@media (max-width:700px), (max-width:1000px) and (max-height:620px) and (orientation:landscape){
  .cable{animation:none}                    /* background-position animations repaint every frame */
  /* the parallax runs on the two pseudo-layers now, so the switch has to name them or the
     phone would quietly get an effect this block exists to keep off it */
  .bg-sections.warm::before,.bg-sections.warm::after{animation:none}
  .card,.status-cap,.bal,.sfx-btn,.lcol,.bot,.bot-mid{backdrop-filter:none}  /* stacked backdrop blurs are very costly on phones */
  .ov{backdrop-filter:none;background:rgba(4,5,8,.86)}   /* the win/crash overlay blur caused the stutter at round end */
  body,.card{transition:none}               /* SNAP the zone re-light — interpolating full-screen gradients janked every zone change */
  .btn-co.on{animation:none;               /* breathing box-shadow repainted the button every frame for the whole ride */
    box-shadow:0 6px 24px rgba(45,168,85,.5),inset 0 1px 0 rgba(255,255,255,.2)}
  .car.hype3 .car-body{animation:none}      /* same story for the cabin pulse at high multipliers */
  .scol{filter:none}                        /* drop-shadow on the WHOLE animated game column re-filtered every frame */
  .luxe,.zone-amb{mix-blend-mode:normal}    /* full-screen blend layers force expensive re-compositing over the moving world */
  .luxe{opacity:calc(var(--tier,0) * .18)}
  .zone-amb{opacity:.3}
  .fr-scene::after{display:none}            /* furniture silhouettes: cheaper floor tiles to rasterise mid-ride */
  /* The zone walls keep their glow and their colour and lose the fine wall patterns: four
     gradient layers per floor tile, a hundred tiles in the world, rasterised again whenever a
     tile scrolls into view. Two layers read the same at phone size. */
  .z-rec .fr-scene::before{background:radial-gradient(ellipse 74% 42% at 50% 100%,rgba(224,170,92,.08),transparent 68%),linear-gradient(180deg,#140f0a 0%,#0d0907 55%,#080604 100%)}
  .z-lob .fr-scene::before{background:radial-gradient(ellipse 30% 40% at 22% 100%,rgba(240,150,60,.16),transparent 70%),linear-gradient(180deg,#1a130d 0%,#110c08 55%,#0a0705 100%)}
  .z-off .fr-scene::before{background:repeating-linear-gradient(90deg,rgba(140,190,225,.08) 0 2px,transparent 2px 40px),linear-gradient(180deg,#0e151c 0%,#091017 55%,#060a0f 100%)}
  .z-exe .fr-scene::before{background:radial-gradient(ellipse 16% 30% at 25% 0%,rgba(230,190,110,.13),transparent 70%),linear-gradient(180deg,#121012 0%,#0b0a0c 55%,#070608 100%)}
  .z-cas .fr-scene::before{background:radial-gradient(ellipse 34% 30% at 50% 0%,rgba(255,214,140,.16),transparent 72%),linear-gradient(180deg,#1c0f0d 0%,#120908 55%,#0a0505 100%)}
  .z-clb .fr-scene::before{background:radial-gradient(ellipse 80% 40% at 50% 0%,rgba(210,79,216,.16),transparent 70%),linear-gradient(180deg,#0e0912 0%,#09060c 55%,#050407 100%)}
  .z-lux .fr-scene::before{background:radial-gradient(circle at 50% 16%,rgba(236,196,120,.16),transparent 50%),linear-gradient(180deg,#181310 0%,#0f0b08 55%,#090705 100%)}
  .z-pen .fr-scene::before{background:radial-gradient(ellipse 100% 42% at 50% 8%,rgba(167,123,224,.14),transparent 68%),linear-gradient(180deg,#150f20 0%,#0e0a15 55%,#08060c 100%)}
  .z-roof .fr-scene::before{background:radial-gradient(ellipse 60% 30% at 50% 100%,rgba(63,196,192,.16),transparent 70%),linear-gradient(180deg,#0b1422 0%,#08101a 55%,#050a10 100%)}
  .z-sky .fr-scene::before{background:radial-gradient(ellipse 92% 60% at 50% 26%,rgba(190,224,238,.16),transparent 70%),linear-gradient(180deg,#101a23 0%,#0a1119 55%,#060a0e 100%)}
  .z-vlt .fr-scene::before{background:radial-gradient(circle at 50% 40%,rgba(242,196,90,.16),transparent 46%),linear-gradient(180deg,#0c0a06 0%,#080604 55%,#040302 100%)}
}

/* ── PHONE LANDSCAPE — dedicated composition: controls left, full-height stage right (QA point 1) ── */
@media (max-width:1000px) and (max-height:620px) and (orientation:landscape){
  /* the shaft is only ~210px tall here — the offer goes to one line so it sits below
     the cabin instead of eating a fifth of the shaft. Both labels stay: "+10 FLOORS"
     is the offer, dropping it would leave an unexplained button. */
  .express-offer{padding:6px 16px 8px;gap:8px}
  .express-offer .ex-txt{flex-direction:row;align-items:baseline;gap:7px}
  .ex-t{font-size:1rem;letter-spacing:2px}
  .ex-s{font-size:.52rem}

  .shell{max-width:none;grid-template-rows:46px 1fr 54px;grid-template-columns:200px 1fr;gap:7px;
    padding:6px max(10px,env(safe-area-inset-right)) calc(6px + env(safe-area-inset-bottom,0px)) max(10px,env(safe-area-inset-left))}
  .sfx-btn{width:32px;height:32px}
  .bal{padding:4px 12px 4px 6px}.bal-num{font-size:.92rem}
  .status-cap{padding:4px 10px}.cap-zone{font-size:.54rem}
  .lcol{grid-column:1;grid-row:2;gap:0;padding:2px 0;overflow:hidden}
  .lcol .card{padding:8px 12px}
  .lcol .stat-card{display:none}
  .stage{grid-column:2;grid-row:2}
  .scol{flex:1 1 auto;max-width:none}
  .car{transform:translate(-50%,-50%) scale(.78)}
  .cable{height:calc(62% - 60px)}
  .floor-row::before{height:18px}
  .fr-num{font-size:1.7rem}
  .indicator{padding:4px 14px}
  /* compact console bar with the single state-driven CTA */
  .bot{grid-column:1/-1;grid-row:3;display:flex;max-width:none;padding:5px;gap:7px}
  .bot-mid{display:none}
  .btn-st{flex:1;font-size:1.05rem;padding:7px;letter-spacing:2px}
  .co-wrap{display:none}
  body.playing .btn-st{display:none}
  body.playing .co-wrap{display:flex;flex:1}
  body.playing .btn-co{display:flex;padding:5px}
  body.playing .co-t{font-size:1.05rem}
  .sf-t{font-size:.95rem}
  .co-a{font-size:.85rem}
  /* entry gate fits a ~370px-tall screen: the sign shrinks rather than being hidden,
     because on the shortest screen it is the only thing that says what this is. */
  .entry-sign svg{width:min(196px,52vw)}
  .entry-by{margin-top:12px;gap:4px}
  .entry-by img{width:126px}
  .entry-hook{margin:10px 0 12px;font-size:.85rem}
  .entry-play{padding:10px;font-size:1.2rem;max-width:240px}
  .entry-foot{margin-top:8px}
}

/* ── VERY NARROW PORTRAIT (≤379px) — nothing may clip (QA point 1) ── */
@media (max-width:379px){
  .lcol .card{padding:0 9px}
  .adj{width:30px;height:30px}
  .bnum{font-size:1.3rem}
  .pr{font-size:.6rem;padding:6px 0}
  .rsk-lbl{font-size:.54rem}
  .rbadge{font-size:.54rem;padding:3px 7px}
}
/* short phones — shrink the cabin a touch so everything fits */
@media(max-width:700px) and (max-height:700px) and (orientation:portrait){
  .car{transform:translate(-50%,-50%) scale(.86)}
  .floor-row{height:118px}
}
/* short desktop / landscape */
@media(min-width:701px) and (max-height:640px){.shell{grid-template-rows:44px 1fr 70px}.floor-row{height:126px}}

/* ── Accessibility: honour the OS "reduce motion" setting — kill the ambient loops ── */
@media(prefers-reduced-motion:reduce){
  .car.hype3 .car-body,.btn-co.on,.danger-vig.on,.peril::after,.cable,.confetti i.go,
  body.danger .car::before,.cab-mult.mx-dead,.car.car-win::after,
  .confetti i.spark.go,#winOv .ovbox.near::before,#winOv .ovbox.near .ovt,
  .car.failing .cab-ceiling::before,
  .status-cap.approach,.status-cap.approach .cap-dot{
    animation:none!important}
  .confetti i.spark{display:none}          /* sparks are pure motion — drop them entirely */
  .danger-vig{display:none}
  /* meaning survives as static colour: red under-glow stays lit, dead read-out stays red-dim */
  .cab-mult.mx-dead{opacity:.35}
}

/* Stacked backdrop blurs were already known to cause stutter here — the rule that switches
   them off only ever applied under 700px, so every desktop kept all seven of them, each one
   re-sampling the moving shaft behind it every frame. It applies everywhere now. */
.card,.status-cap,.bal,.sfx-btn,.lcol,.bot,.bot-mid,.ov,.riders{backdrop-filter:none}

/* ══════════════════════════════════════════════════════════════════
   RIDE RENDERING — reduced motion, and the cabin's own small life
   ══════════════════════════════════════════════════════════════════ */

/* The shaft is the one thing that moves during a ride, on its own composite layer, driven by
   translate3d from the rAF engine. No transition here: a transition commits to a duration
   before the next server tick is known. */
.shaft-world{transition:none}

/* A cabin under power is never perfectly still. One pixel, and only while riding — enough to
   read as a motor, far too little to be mistaken for the ride itself. */
@keyframes cabHum{0%,100%{transform:translate3d(0,0,0)}50%{transform:translate3d(0,.6px,0)}}
body[data-riding="1"] .car-body{animation:cabHum .22s ease-in-out infinite}

/* Someone who has asked their system for less motion gets the game without the decoration:
   the cabin is placed rather than animated, and nothing loops. The ride still reads, because
   the floor number and the multiplier are text, and they are the server's numbers either way. */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{animation-duration:.01ms !important;animation-iteration-count:1 !important;
    transition-duration:.01ms !important;scroll-behavior:auto !important}
  body[data-riding="1"] .car-body{animation:none}
  .bg-sections.warm::before,.bg-sections.warm::after{animation:none}
  .cable{animation:none}
  .confetti i,.spark{display:none}          /* particles are decoration, and there are dozens */
}

/* ══════════════════════════════════════════════════════════════════
   The top bar's CONTENTS follow its band to the edges.

   The black band already runs the full width of the screen, but everything in it — the name,
   the balance, the menu — sat inside the shell's centred column: 471px of empty black on the
   left and 470px on the right at a 1889px window. The bar looked like a full-width bar with
   its contents huddled in the middle.

   The header breaks out horizontally the same way its band does, so `50% - 50vw` resolves to
   zero for the band and the two stay in step by construction. Nothing grows vertically here —
   an earlier attempt at this added top padding as well and pushed the phone into a scrollbar. */
@media (min-width:1000px){
  .hdr{margin-left:calc(50% - 50vw);margin-right:calc(50% - 50vw);
    padding-left:26px;padding-right:26px}
}

/* Nothing inside the shaft may paint outside it.

   The ground row is 360px tall and hangs 256px below the shaft's viewport, and its label —
   the faint 'G / Street Entrance' — lands at 935,814, which is inside the stake bar, between
   the +10 and +50 chips. That is the small square in the corner of the bet row.

   overflow:hidden on .shaft-vp ought to be enough, but the row carries `contain: paint` and
   the label is absolutely positioned with a z-index, and that combination is exactly where
   escapes happen. clip-path is not advisory: it clips the painted result of the whole subtree
   whatever stacking contexts are inside it, so the shaft can no longer leak into the UI. */
.shaft-vp{clip-path:inset(0)}

/* And the label itself has no business below the lobby: the floor readout above the shaft
   already says which floor you are on, and the ground row's copy only ever showed 'G'. */
.ground-row .fr-meta{display:none}

/* The cables belong behind the hall doors.

   .doors carries z-index:30, which looks like it should settle this — but the doors live
   INSIDE .shaft-vp, and z-index only orders siblings within their own stacking context. The
   cables are siblings OF .shaft-vp at z-index:3, so the entire viewport subtree, doors and
   all, paints below them. Raising the doors higher cannot fix that; they are in a different
   part of the tree.

   So the cables simply are not drawn while the shaft is shut, which is also what a real lift
   looks like: closed doors, no machinery. They fade back in with the doors opening. */
   Driven by a class on .shaft rather than by :has(.doors:not(.open)). The selector matched
   correctly on load but did not re-evaluate when .open was added during a round, and a visual
   detail is a poor thing to hang on selector invalidation. openDoors and closeDoors already
   own this state, so they set it. */
.cable{transition:opacity .28s ease}
.shaft.sealed .cable{opacity:0}

/* ══════════════════════════════════════════════════════════════════
   THE ACTION DECK — the same building, one floor lower

   The payout is a machined plate now; the deck under it was still stock UI: a flat saturated
   gold slab for START and four identical grey rectangles for the chips. Nothing here changes
   size or position — every box stays exactly where the layout puts it. What changes is
   material and type, so the controls read as machined rather than drawn.
   ══════════════════════════════════════════════════════════════════ */

/* START: brass with depth instead of a bright flat fill. The face is darker and the light
   sits on the top edge where a milled surface would catch it, so the letters read as struck
   into the metal rather than printed on a colour. */
.btn-st{background:
    linear-gradient(180deg,rgba(255,255,255,.16),rgba(255,255,255,0) 42%),
    repeating-linear-gradient(90deg,rgba(0,0,0,.05) 0 2px,transparent 2px 4px),
    linear-gradient(176deg,#e2be6f,#bf9540 46%,#8f6a26);
  border:1px solid rgba(255,236,186,.42);
  color:#241906;text-shadow:0 1px 0 rgba(255,240,205,.45);
  box-shadow:0 6px 20px rgba(0,0,0,.42),
             inset 0 1px 0 rgba(255,245,215,.55),
             inset 0 -2px 0 rgba(80,54,12,.45)}
.btn-st::before{background:linear-gradient(180deg,rgba(255,255,255,.22),transparent 38%)}
.btn-st:not(:disabled):hover{filter:brightness(1.04)}
/* a struck control travels a little and comes back — no bounce */
.btn-st:active{transform:translateY(1px);
  box-shadow:0 2px 10px rgba(0,0,0,.5),inset 0 2px 5px rgba(80,54,12,.4)}

/* The chips: engraved keys, not filled rectangles. A hairline of light on the top edge, the
   figure in the instrument face, and brass arriving only on the one you are touching. */
.pr{background:linear-gradient(180deg,rgba(255,255,255,.055),rgba(255,255,255,.012));
  border:1px solid rgba(255,255,255,.09);border-radius:var(--r-ctl);
  font-family:'Share Tech Mono',monospace;font-size:.78rem;font-weight:400;letter-spacing:1px;
  color:var(--ink-dim);box-shadow:inset 0 1px 0 rgba(255,255,255,.06)}
.pr:hover{color:#f0d089;border-color:rgba(232,195,126,.34);
  background:linear-gradient(180deg,rgba(232,195,126,.10),rgba(232,195,126,.02))}
.pr:active{transform:none;
  background:linear-gradient(180deg,rgba(0,0,0,.25),rgba(255,255,255,.02));
  box-shadow:inset 0 2px 4px rgba(0,0,0,.4)}

/* The stake reads as an instrument: monospaced, tabular, sitting in a milled recess so the
   figure has somewhere to be rather than floating between two circles. */
.stake-row{gap:10px}
.stake .bnum,.lcol .bet-card .bnum{
  font-family:'Share Tech Mono',monospace;font-size:1.45rem;letter-spacing:1px;line-height:1;
  font-variant-numeric:tabular-nums;text-shadow:none;color:#f2e6cc;
  background:linear-gradient(180deg,rgba(0,0,0,.34),rgba(0,0,0,.16));
  border:1px solid rgba(255,255,255,.07);
  border-radius:var(--r-ctl);padding:3px 12px;
  box-shadow:inset 0 2px 5px rgba(0,0,0,.45)}
.stake .bnum:hover,.lcol .bet-card .bnum:hover{border-color:rgba(232,195,126,.28)}
.stake .bnum:focus,.lcol .bet-card .bnum:focus{border-color:rgba(232,195,126,.55);
  color:#fff;
  text-shadow:none;box-shadow:inset 0 2px 5px rgba(0,0,0,.5),0 0 0 2px rgba(232,195,126,.12)}

/* ══ THE AMOUNT STAYS READABLE WHILE YOU ARE EDITING IT ══

   Tapping the field selects the whole amount, so typing replaces it instead of appending to
   it. That is the behaviour anybody wants — but nothing in this file ever said what SELECTED
   text should look like, so the browser painted its own default over cream text on a dark
   inset panel, and the number became a smudge the moment you touched it.

   Which browser and which default does not matter, and chasing them would be the wrong fix.
   The rule is simply stated here instead of left to somebody else.

   Fixed colours rather than var(--accent): the accent changes with the zone — amber in the
   lobby, teal in the offices, champagne, violet in the penthouse, ice at the summit — and a
   pairing that reads against one of those disappears against another. This pair is the same
   in every shaft and on every floor.

   ONE VENDOR PSEUDO PER RULE, and that is not tidiness. A selector list is invalid as a WHOLE
   if any single selector in it is invalid, so ::selection and ::-moz-selection written in one
   list means every browser throws the entire rule away — including the half it understands.
   Written that way first, and the browser dropped the lot: the parsed stylesheet held no
   ::selection at all while the file on disk held three. */
.stake .bnum::selection,.lcol .bet-card .bnum::selection{
  background:#f0d9a4;color:#140e07;text-shadow:none}
.stake .bnum::-moz-selection,.lcol .bet-card .bnum::-moz-selection{
  background:#f0d9a4;color:#140e07;text-shadow:none}

/* And every other field in the game, for the same reason. The stake is the one you notice
   because it is the one you edit, but an unreadable selection is unreadable anywhere. */
input::selection{background:#f0d9a4;color:#140e07}
input::-moz-selection{background:#f0d9a4;color:#140e07}

/* The steppers become machined keys — square-ish and seated, matching the chips. */
.stake-adj{width:38px;height:38px;border-radius:var(--r-ctl);
  background:linear-gradient(180deg,rgba(255,255,255,.075),rgba(255,255,255,.015));
  border:1px solid rgba(255,255,255,.10);color:var(--ink-dim);font-size:1.15rem;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.07)}
.stake-adj:hover{color:#f0d089;border-color:rgba(232,195,126,.34)}
.stake-adj:active{transform:none;background:linear-gradient(180deg,rgba(0,0,0,.25),rgba(255,255,255,.02));
  box-shadow:inset 0 2px 4px rgba(0,0,0,.4)}

/* the label engraved, like every other label on this building */
.stake-lbl{letter-spacing:4px;color:rgba(232,234,239,.42)}

/* ══════════════════════════════════════════════════════════════════
   THE LIVE CONTROLS — the last flat slab in the building

   CASH OUT was the same saturated green fill that the crash card and the payout plate both
   had removed from them: a colour standing in for a control. It is a lit key now — the same
   machined face as START, carrying green light instead of brass, so the two read as the same
   kind of object doing different jobs rather than as two unrelated buttons.

   Sizes and positions are untouched: the deck's geometry was measured and is left alone.
   ══════════════════════════════════════════════════════════════════ */

/* Live: a deep green face with the light on its top edge and a green rim, not a flat fill.
   The figure moves into the instrument face so the money reads like every other number here. */
.btn-co.on{color:#eafff1;border:1px solid rgba(120,226,160,.45);
  background:
    linear-gradient(180deg,rgba(255,255,255,.14),rgba(255,255,255,0) 44%),
    repeating-linear-gradient(90deg,rgba(0,0,0,.05) 0 2px,transparent 2px 4px),
    linear-gradient(176deg,#1e6b3b,#15512c 48%,#0d3a1f);
  box-shadow:0 6px 20px rgba(0,0,0,.42),
             inset 0 1px 0 rgba(190,255,214,.34),
             inset 0 -2px 0 rgba(6,32,16,.5)}
.btn-co.on:hover{filter:brightness(1.05)}
/* struck, not squashed — travels a pixel and seats, like START and the chips */
.btn-co:active{transform:translateY(1px)}
.btn-co.on:active{box-shadow:0 2px 10px rgba(0,0,0,.5),inset 0 2px 5px rgba(6,32,16,.45)}

.co-t{font-family:'Bebas Neue',sans-serif;letter-spacing:3px;
  text-shadow:0 1px 0 rgba(0,0,0,.35)}
.co-a{font-family:'Share Tech Mono',monospace;font-variant-numeric:tabular-nums;
  font-size:clamp(.8rem,1.6vw,1rem);letter-spacing:.5px;color:#d8f6e4}

/* the breathing rim keeps its own layer — it fades opacity, it does not repaint a shadow */
.btn-co.on::after{box-shadow:0 0 0 1px rgba(150,240,190,.5),0 6px 26px rgba(45,168,85,.45)}

/* BANK 50%: the same machining, one step quieter, lit brass instead of green. */
.btn-safe{border:1px solid rgba(230,192,116,.34);
  background:
    linear-gradient(180deg,rgba(255,255,255,.07),rgba(255,255,255,0) 44%),
    repeating-linear-gradient(90deg,rgba(0,0,0,.05) 0 2px,transparent 2px 4px),
    linear-gradient(176deg,#2a2318,#1d1811 52%,#141009);
  box-shadow:0 5px 16px rgba(0,0,0,.38),
             inset 0 1px 0 rgba(255,240,200,.16),
             inset 0 -2px 0 rgba(0,0,0,.35)}
.btn-safe:hover{border-color:rgba(240,208,137,.55)}
.btn-safe:active{transform:translateY(1px);
  box-shadow:0 2px 8px rgba(0,0,0,.45),inset 0 2px 5px rgba(0,0,0,.4)}
.sf-a{font-family:'Share Tech Mono',monospace;font-variant-numeric:tabular-nums;
  letter-spacing:.5px;color:rgba(245,228,190,.92)}

@media (prefers-reduced-motion: reduce){ .btn-co.on::after{animation:none;opacity:0} }

/* ══════════════════════════════════════════════════════════════════
   THE WINS PANEL, THE LAST ROUNDS, AND THE MENU AS A FLAG

   Desktop gains a panel on the left edge, from the black band's lower edge to the bottom of
   the window: who cashed out, today's best, the top. Every ride is still the player's own —
   the panel is after the fact, never a shared cabin.

   The last rounds leave the black band on desktop and sit on their own line beneath it,
   starting where the panel ends, coloured by the zone each round ended in.

   The menu stops being a drawer and becomes a flag under the button: the account on top,
   then the switches, then the pages. --band-b is measured by syncBand() in game.js.
   ══════════════════════════════════════════════════════════════════ */

/* The pause after a round (COOLDOWN_MS, 1.5 s): the dark BET key fills with brass from the left while
   it counts down, so the wait reads as the game getting ready, not as a dead button. */
.btn-st.cooling:disabled::after{content:'';position:absolute;inset:0;border-radius:inherit;pointer-events:none;
  transform-origin:left center;transform:scaleX(0);
  background:linear-gradient(90deg,rgba(232,195,126,.20),rgba(232,195,126,.08));
  animation:coolFill 1.5s linear forwards}
@keyframes coolFill{to{transform:scaleX(1)}}

/* The brand mark: the call-button plate (▲ lit, ▼ dimmed) left of the name, in the same gold.
   Sized to the cap height of the wordmark so the two read as one sign. */
.brand-mark{width:19px;height:19px;flex:0 0 auto;display:block;margin-right:-1px}
@media (min-width:1000px){ .brand-mark{width:22px;height:22px} }

/* the ten zone lights, turned up to read at chip size; zc0 is a cable that went on the ground */
.zc0{--c:#ff5a5a}.zc1{--c:#ffb13b}.zc2{--c:#7fc4ff}.zc3{--c:#e3c27a}.zc4{--c:#ff7a5c}.zc5{--c:#ff6bf0}
.zc6{--c:#ffe08a}.zc7{--c:#c58bff}.zc8{--c:#3fe6dc}.zc9{--c:#b8e6ff}.zc10{--c:#ffd36b}

/* ══ EACH ZONE MOVES A LITTLE ══
   One layer for the whole room, not a hundred floors: the zone light (.zone-amb) carries a
   second light whose motion belongs to the zone — a fire in the foyer, a chandelier in the
   salon, lasers in the club, clouds on the roof, a pulse in the vault. Only opacity and
   transform are animated, so the compositor does it on a phone too, and nothing moves when
   motion is turned off (the menu switch, or prefers-reduced-motion). */
.zone-amb::after{content:'';position:absolute;inset:-10%;opacity:0;pointer-events:none;transition:opacity 1.2s ease}
body[data-zone="lobby"] .zone-amb::after{opacity:1;
  background:radial-gradient(ellipse 30% 22% at 30% 92%,rgba(255,150,60,.22),transparent 70%);
  animation:zFire 2.8s ease-in-out infinite}
@keyframes zFire{0%,100%{opacity:.75}30%{opacity:1}55%{opacity:.6}80%{opacity:.9}}
body[data-zone="casino"] .zone-amb::after{opacity:1;
  background:radial-gradient(circle at 46% 9%,rgba(255,236,190,.35) 0 1.5px,transparent 3px),
             radial-gradient(circle at 54% 11%,rgba(255,236,190,.3) 0 1.5px,transparent 3px),
             radial-gradient(ellipse 26% 14% at 50% 8%,rgba(255,214,140,.14),transparent 70%);
  animation:zTwinkle 3.4s ease-in-out infinite}
@keyframes zTwinkle{0%,100%{opacity:.65}50%{opacity:1}}
body[data-zone="nightclub"] .zone-amb::after{opacity:1;transform-origin:50% 0;
  background:linear-gradient(100deg,transparent 47%,rgba(225,90,235,.22) 49.5%,transparent 52%),
             linear-gradient(80deg,transparent 47%,rgba(120,150,255,.16) 49.5%,transparent 52%);
  animation:zLaser 7s ease-in-out infinite alternate}
@keyframes zLaser{from{transform:rotate(-9deg)}to{transform:rotate(9deg)}}
body[data-zone="penthouse"] .zone-amb::after{opacity:1;
  background:radial-gradient(ellipse 34% 14% at 72% 96%,rgba(150,170,255,.18),transparent 70%);
  animation:zFire 4.6s ease-in-out infinite}
body[data-zone="rooftop"] .zone-amb::after{opacity:1;
  background:radial-gradient(ellipse 22% 7% at 20% 30%,rgba(220,235,255,.10),transparent 70%),
             radial-gradient(ellipse 26% 8% at 70% 22%,rgba(220,235,255,.08),transparent 70%);
  animation:zDrift 26s linear infinite alternate}
@keyframes zDrift{from{transform:translateX(-6%)}to{transform:translateX(6%)}}
body[data-zone="skylounge"] .zone-amb::after{opacity:1;
  background:linear-gradient(180deg,transparent 40%,rgba(200,230,255,.10) 50%,transparent 60%);
  animation:zSweep 9s ease-in-out infinite}
@keyframes zSweep{0%,100%{transform:translateY(-30%)}50%{transform:translateY(30%)}}
body[data-zone="skyvault"] .zone-amb::after{opacity:1;
  background:radial-gradient(circle at 50% 42%,rgba(242,196,90,.20),transparent 40%);
  animation:zPulse 2.6s ease-in-out infinite}
@keyframes zPulse{0%,100%{opacity:.45;transform:scale(.96)}50%{opacity:1;transform:scale(1.04)}}
@media (prefers-reduced-motion: reduce){ .zone-amb::after{animation:none !important} }
/* the avatars' colours — classes, because the page's policy refuses style attributes */
.av0{--av:#b8832f}.av1{--av:#2a9c90}.av2{--av:#8a5cc9}.av3{--av:#b99b57}
.av4{--av:#6f8faa}.av5{--av:#b0463c}.av6{--av:#3f7a4a}.av7{--av:#5a5f6b}

/* the last rounds, in the zone's own light: plain numbers, no boxes, like the strip players
   know from Aviator — bright colour, solid weight, tabular figures, on their own dark band. */
.hchip.z{color:color-mix(in srgb,var(--c) 85%,#fff);border:0;background:none;box-shadow:none;
  font-family:'Inter',sans-serif;font-weight:600;font-size:.7rem;letter-spacing:.1px;
  font-variant-numeric:tabular-nums;padding:0 5px;line-height:1.2}

/* The strip over the shaft is kept as a plain lintel — the floor, the arrow and the state
   line are hidden at the owner's call. The elements stay in the page (the game still writes
   to them, and restoring this is deleting one rule). */
.indicator > *{visibility:hidden}

/* ── players and chat: two plain marks on the bar, no ring, no fill ── */
.hdr-ico{position:relative;width:30px;height:30px;min-height:0;padding:0;margin-left:6px;
  display:grid;place-items:center;flex:0 0 auto;cursor:pointer;
  background:none;border:0;color:var(--ink-dim);transition:color .14s}
.hdr-ico:first-of-type{margin-left:14px}
.hdr-ico svg{width:20px;height:20px;fill:none;stroke:currentColor;stroke-width:1.6;
  stroke-linecap:round;stroke-linejoin:round}
.hdr-ico:hover,.hdr-ico.on{color:#f0d089}
.hdr-ico::after{content:"";position:absolute;inset:-7px}      /* a 44px target around a 30px mark */
.ico-dot{position:absolute;top:4px;right:3px;width:6px;height:6px;border-radius:50%;background:#e8c37e}
.ico-dot[hidden]{display:none}

.social{position:fixed;z-index:215;top:calc(var(--band-b,56px) + 6px);right:max(10px,env(safe-area-inset-right,0px));
  width:min(320px,calc(100vw - 20px));height:min(520px,calc(100dvh - var(--band-b,56px) - 18px));
  display:flex;flex-direction:column;background:#000;border:1px solid rgba(255,255,255,.08);
  border-radius:12px;overflow:hidden;box-shadow:0 18px 50px rgba(0,0,0,.62);animation:flagIn .18s ease-out}
.social[hidden]{display:none}
.so-tabs{display:flex;gap:4px;margin:10px;padding:3px;border-radius:18px;
  background:rgba(255,255,255,.035);border:1px solid rgba(255,255,255,.06)}
.so-tab{flex:1;display:flex;align-items:center;justify-content:center;gap:6px;min-height:0;padding:7px 0;
  border:0;border-radius:15px;background:none;cursor:pointer;white-space:nowrap;
  font:500 .64rem 'Inter',sans-serif;color:var(--ink-dim);transition:background .14s,color .14s}
.so-tab svg{width:15px;height:15px;fill:none;stroke:currentColor;stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round}
.so-tab:hover{color:var(--ink)}
.so-tab.on{background:rgba(255,255,255,.09);color:#fff}
.so-body{flex:1 1 auto;min-height:0;display:flex;flex-direction:column}
.so-body[hidden]{display:none}
.so-list{flex:1 1 auto;min-height:0;overflow-y:auto;padding:0 10px 10px;scrollbar-width:thin;
  scrollbar-color:rgba(255,255,255,.12) transparent}

.pl-row{display:flex;align-items:center;gap:9px;height:34px;padding:0 8px;margin-bottom:2px;border-radius:7px;
  font-size:.68rem;background:rgba(255,255,255,.035)}
.pl-row.me{background:rgba(232,195,126,.06);box-shadow:inset 0 0 0 1px rgba(232,195,126,.42)}
.pl-n{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--ink-dim)}
.pl-row.me .pl-n{color:#fff}
.pl-row em{font-style:normal;font-family:'Share Tech Mono',monospace;font-size:.64rem;padding:2px 6px;border-radius:10px;
  color:var(--c);background:color-mix(in srgb,var(--c) 12%,transparent);border:1px solid color-mix(in srgb,var(--c) 34%,transparent)}
.pl-idle{font-size:.58rem;color:var(--ink-faint)}

.ch-row{display:flex;gap:9px;padding:7px 4px;border-bottom:1px solid rgba(255,255,255,.04)}
.ch-row .ws-av{margin-top:2px}
.ch-body{flex:1;min-width:0}
.ch-head{display:flex;justify-content:space-between;gap:8px;margin-bottom:2px}
.ch-n{font-size:.62rem;font-weight:500;color:var(--ink-dim)}
.ch-row.me .ch-n{color:#f0d089}
.ch-t{font-family:'Share Tech Mono',monospace;font-size:.56rem;color:var(--ink-faint)}
.ch-txt{font-size:.72rem;line-height:1.45;color:var(--ink);overflow-wrap:anywhere}
.chat-hint{min-height:0;padding:0 14px;font-size:.6rem;color:#f0b36b;transition:padding .15s}
.chat-hint.on{padding:6px 14px}
.chat-row{display:flex;gap:6px;padding:10px;border-top:1px solid rgba(255,255,255,.07)}
.chat-in{flex:1;min-width:0;height:36px;padding:0 12px;border-radius:18px;outline:none;
  background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.09);color:var(--ink);
  font:400 .72rem 'Inter',sans-serif}
.chat-in:focus{border-color:rgba(232,195,126,.45)}
.chat-in::placeholder{color:var(--ink-faint)}
.chat-send{width:36px;height:36px;min-height:0;padding:0;border-radius:50%;flex:0 0 auto;cursor:pointer;
  display:grid;place-items:center;background:rgba(232,195,126,.12);border:1px solid rgba(232,195,126,.35);color:#f0d089}
.chat-send:hover{background:rgba(232,195,126,.2)}
.chat-send svg{width:17px;height:17px;fill:none;stroke:currentColor;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}

/* ── the flag ── */
.menu-scrim{background:transparent;animation:none}
.menu{top:calc(var(--band-b,56px) + 6px);right:max(10px,env(safe-area-inset-right,0px));bottom:auto;
  width:min(310px,calc(100vw - 20px));max-height:calc(100dvh - var(--band-b,56px) - 18px);
  border:1px solid rgba(255,255,255,.10);border-radius:12px;overflow:hidden;padding:0;
  box-shadow:0 18px 50px rgba(0,0,0,.62);animation:flagIn .18s ease-out}
@keyframes flagIn{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:none}}
.menu::before{left:16px;right:16px;top:0;bottom:auto;width:auto;height:1px;
  background:linear-gradient(90deg,transparent,rgba(234,161,64,.55),transparent)}
.menu.home .menu-top{display:none}
.menu-body{min-height:0;padding:10px}
.menu-group{margin-bottom:10px}
.menu-row,.menu-item{padding:10px 12px}
.menu-foot{margin-top:2px}

/* ── the demo account ── */
.acct{display:flex;align-items:center;gap:10px;padding:4px 4px 12px}
.acct-av,.ws-av,.av-opt{display:grid;place-items:center;border-radius:50%;
  background:radial-gradient(circle at 32% 28%,color-mix(in srgb,var(--av,#8a6a32) 55%,#fff),var(--av,#8a6a32) 55%,color-mix(in srgb,var(--av,#8a6a32) 60%,#000));
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.18)}
.acct-av{width:40px;height:40px;flex:0 0 auto}
.acct-av svg,.av-opt svg,.ws-av svg{width:58%;height:58%;fill:none;stroke:#fff;stroke-width:1.7;
  stroke-linecap:round;stroke-linejoin:round}
.acct-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  font-family:'Share Tech Mono',monospace;font-size:.95rem;color:#fff}
.acct-chg{flex:0 0 auto;min-height:0;padding:6px 10px;border-radius:16px;cursor:pointer;
  background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.12);color:var(--ink-dim);
  font:500 .62rem 'Inter',sans-serif;transition:border-color .14s,color .14s}
.acct-chg:hover,.acct-chg[aria-expanded="true"]{color:#f0d089;border-color:rgba(232,195,126,.45)}
.acct-pick{display:grid;grid-template-columns:repeat(4,1fr);gap:8px;padding:2px 4px 12px}
.acct-pick[hidden]{display:none}
.av-opt{width:42px;height:42px;min-height:0;margin:auto;padding:0;border:0;cursor:pointer;
  transition:transform .12s}
.av-opt:hover{transform:scale(1.06)}
.av-opt.on{box-shadow:inset 0 0 0 1px rgba(255,255,255,.18),0 0 0 2px #e8c37e}

/* ── the wins panel ──
   PHONE AND TABLET: below the game. The game keeps exactly one screen — the shell is 100dvh
   and the page scrolls (see the max-width:999px block above) — and the panel lives under the
   fold, so scrolling down past the lift reaches All bets, My bets and Top. Nothing overlays
   the shaft and nothing resizes it mid-ride. */
.wins-side{display:flex;flex-direction:column;background:#000;position:relative;z-index:12;
  margin:10px max(9px,env(safe-area-inset-left,0px)) calc(16px + env(safe-area-inset-bottom,0px));
  border:1px solid rgba(255,255,255,.07);border-radius:12px;overflow:hidden}
.wins-side .ws-list{overflow:visible;max-height:none}
@media (min-width:1000px){
  :root{--side-w:clamp(240px,19vw,300px);--strip-h:30px}
  body{grid-template-columns:var(--side-w) minmax(0,1fr) var(--side-w)}
  /* The bar itself is 36px: the marks on it are 30px at most, and the black band reads as a
     thin strip rather than a slab above the lift. */
  .shell{grid-template-rows:calc(36px + var(--strip-h)) minmax(0,1fr) auto auto}
  .hdr{grid-template-rows:minmax(0,1fr) var(--strip-h);gap:0}
  .hdr::before{bottom:var(--strip-h)}
  /* The last rounds on a band of their own under the bar: a shade lighter than the bar so the
     two read as separate things, with a hairline under it. */
  .hdr::after{content:'';position:absolute;left:calc(50% - 50vw);right:calc(50% - 50vw);bottom:0;
    height:var(--strip-h);background:#0b0d12;border-bottom:1px solid rgba(255,255,255,.06);pointer-events:none}
  .hdr > *{z-index:1}                      /* the bar and the numbers paint over both bands */
  .hdr .hist-strip{align-self:center;margin-left:calc(var(--side-w) - 26px + 6px)}
  .hdr .hchip{font-size:.76rem;padding:0 6px}

  .wins-side{display:flex;flex-direction:column;position:fixed;left:0;bottom:0;z-index:30;
    top:var(--band-b,62px);width:var(--side-w);margin:0;border:0;border-radius:0;
    background:#000;border-right:1px solid rgba(255,255,255,.05)}
  .wins-side .ws-list{overflow-y:auto}
}
/* ── The panel as a table, not a stack of cards ──
   One gutter (--ws-x) for the tabs, the column heads, every row and the footer, so the four
   columns line up from top to bottom. Rows are full width and separated by a hairline rather
   than boxed; the only accent is your own row's gold edge. Numbers are tabular, so a column of
   amounts reads down its right edge instead of jittering. */
.wins-side{--ws-x:16px;--ws-line:rgba(255,255,255,.055)}

.ws-tabs{display:flex;gap:2px;margin:0;padding:0 calc(var(--ws-x) - 8px);
  border-bottom:1px solid var(--ws-line)}
.ws-tab{position:relative;flex:0 0 auto;min-height:0;height:44px;padding:0 8px;border:0;background:none;
  cursor:pointer;white-space:nowrap;font:500 .7rem 'Inter',sans-serif;letter-spacing:.01em;
  color:var(--ink-faint);transition:color .15s}
.ws-tab::after{content:"";position:absolute;left:8px;right:8px;bottom:-1px;height:2px;border-radius:2px 2px 0 0;
  background:#d8a24a;transform:scaleX(0);transition:transform .2s ease}
.ws-tab:hover{color:var(--ink-dim)}
.ws-tab.on{color:#fff}
.ws-tab.on::after{transform:scaleX(1)}
.ws-tab:focus-visible{outline:none;color:#fff;box-shadow:inset 0 0 0 1px rgba(232,195,126,.45);border-radius:6px}

.ws-cols,.ws-row{display:grid;grid-template-columns:minmax(0,1.45fr) minmax(0,.7fr) minmax(0,.8fr) minmax(0,1.15fr);
  align-items:center;column-gap:10px}
.ws-cols{padding:13px var(--ws-x) 9px;font:600 .55rem 'Inter',sans-serif;letter-spacing:.1em;
  text-transform:uppercase;color:rgba(232,234,239,.46)}
.ws-cols span:nth-child(n+2),.ws-row > span:nth-child(n+2){text-align:right}
.ws-cols span{white-space:nowrap;overflow:hidden;text-overflow:clip}
.ws-list{flex:1 1 auto;min-height:0;overflow-y:auto;padding:0 0 8px;scrollbar-width:thin;
  scrollbar-color:rgba(255,255,255,.1) transparent}

.ws-row{height:46px;padding:0 var(--ws-x);border-bottom:1px solid rgba(255,255,255,.035);
  font-size:.76rem;transition:background .15s}
.ws-row:hover{background:rgba(255,255,255,.022)}
/* ══ ONE SIGNAL PER ROW ══
   The row used to carry three at once: gold because it was YOURS, green on the amount because
   it PAID, grey because it LOST. Three codes competing in forty pixels, and with a list of your
   own bets everything came out gold — the state you actually want to read was the one thing you
   could not see.

   So they are split by job. COLOUR belongs to the outcome: green when it paid, nothing at all
   when it did not. TYPE belongs to identity: your own row says "You" in white. Nothing is gold
   here any more — gold is the cabin's and the BET button's, and it stops meaning anything if
   every list borrows it. */
.ws-row.me .ws-n{color:#fff;font-weight:600}
.ws-p{display:flex;align-items:center;gap:9px;min-width:0}
.ws-av{width:20px;height:20px;flex:0 0 auto}
.ws-n{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  font-weight:500;color:var(--ink-dim)}
.ws-b,.ws-w,.ws-x em{font-family:'Share Tech Mono',monospace;font-variant-numeric:tabular-nums;letter-spacing:.02em}
/* The stake was set so dim it stopped being information and became texture. Readable now,
    and still clearly subordinate to the payout beside it. */
.ws-b{color:rgba(232,234,239,.62);font-size:.76rem}
.ws-x{color:rgba(232,234,239,.3)}
.ws-x em{font-style:normal;font-size:.8rem;color:#d6dae1;padding:0;background:none;border-radius:0}

/* A round that PAID. Desaturated on purpose: a dark premium list cannot take a saturated green
   without it reading as a system alert, and a win is good news, not an alarm. The wash falls
   away to the right so the row still ends in black and the column rhythm survives. */
.ws-row.won{background:linear-gradient(90deg,rgba(78,170,124,.15),rgba(78,170,124,.05) 52%,transparent 86%);
  box-shadow:inset 2px 0 0 #4ea97c}
.ws-row.won .ws-n{color:#dff0e6}
.ws-row.won.me .ws-n{color:#fff}
/* The payout is the one number the row exists for, so it is the biggest and the brightest. */
.ws-w{color:#7cc9a2;font-size:.84rem}
.ws-row.won .ws-w{color:#93dfb7}

/* A round that did not pay is plain black — no tint, no bar, nothing to look at. That is the
   whole point: the eye should be able to find the green ones without reading a single number.
   Settled, not an error, so it is never red. */
.ws-row.lost{background:none}
.ws-row.lost .ws-n{color:rgba(232,234,239,.5)}
.ws-row.lost .ws-b{color:rgba(232,234,239,.5)}
.ws-row.lost.me .ws-n{color:rgba(255,255,255,.76)}
.ws-row.lost .ws-x{color:rgba(232,234,239,.26);font-size:.8rem}

.ws-empty{padding:40px 24px;text-align:center;font-size:.66rem;line-height:1.7;color:rgba(232,234,239,.4)}
.ws-empty::before{content:"";display:block;width:28px;height:28px;margin:0 auto 12px;border-radius:50%;
  border:1px solid rgba(255,255,255,.12);
  background:radial-gradient(circle,rgba(232,195,126,.5) 0 2px,transparent 3px)}

.ws-foot{display:flex;align-items:center;gap:8px;min-height:0;padding:14px var(--ws-x);cursor:pointer;
  border:0;border-top:1px solid var(--ws-line);background:none;text-align:left;
  font:500 .64rem 'Inter',sans-serif;color:rgba(232,234,239,.45);transition:color .15s}
.ws-foot:hover{color:var(--ink)}
.ws-foot:focus-visible{outline:none;color:#fff;box-shadow:inset 0 0 0 1px rgba(232,195,126,.45)}
.ws-foot svg{width:15px;height:15px;fill:none;stroke:currentColor;stroke-width:1.6;
  stroke-linecap:round;stroke-linejoin:round}

/* ══════════════════════════════════════════════════════════════════
   THE CABIN CARRIES THE ZONE'S LIGHT

   On a phone the floors are plain on purpose (their furniture is switched off for the frame
   rate), so the zone has to be read somewhere that costs nothing. The cabin is the one thing
   the eye never leaves — so the cabin takes the room's light: the lamp in its ceiling, the
   glow behind the multiplier, a breath of colour in the glass, the halo it throws on the
   shaft, and the cables above it. The gold bezel stays gold; it is the cabin's own metal.
   One element, recoloured only when the zone changes — no per-floor painting at all.
   ══════════════════════════════════════════════════════════════════ */
.car-body{box-shadow:
    inset 0 1.5px 0 rgba(255,250,228,.85), inset 0 -2.5px 0 rgba(60,42,12,.75),
    inset 2px 0 3px rgba(255,240,200,.16), inset -2px 0 4px rgba(50,35,10,.5),
    0 0 0 1px #0a0805,
    -7px 0 18px rgba(0,0,0,.6), 7px 0 18px rgba(0,0,0,.6),
    0 18px 34px rgba(0,0,0,.72),
    0 0 46px color-mix(in srgb,var(--accent) 34%,transparent)}
.car-cabin{background:
    radial-gradient(ellipse 90% 60% at 50% 0%,color-mix(in srgb,var(--accent) 22%,transparent),transparent 70%),
    linear-gradient(180deg,#1f2735 0%,#131a26 52%,#080d13 100%)}
.cab-ceiling{background:radial-gradient(ellipse 66% 130% at 50% -20%,
    color-mix(in srgb,var(--accent) 45%,rgba(255,241,214,.42)),
    color-mix(in srgb,var(--accent) 12%,transparent) 55%,transparent 80%)}
.cab-ceiling::before{background:color-mix(in srgb,var(--accent) 40%,#fff7e2);
  box-shadow:0 0 12px 2px color-mix(in srgb,var(--accent) 70%,transparent)}
/* The read-out always carries a little of the zone; the climb (--mx-glow, 0 → 1) turns it up. */
.cab-mult{text-shadow:
    0 0 10px color-mix(in srgb,var(--accent) 40%,transparent),
    0 0 calc(var(--mx-glow,0) * 9px)  color-mix(in srgb,var(--accent) calc(var(--mx-glow,0) * 90%),transparent),
    0 0 calc(var(--mx-glow,0) * 26px) color-mix(in srgb,var(--accent) calc(var(--mx-glow,0) * 50%),transparent),
    0 0 calc(var(--mx-glow,0) * 58px) color-mix(in srgb,var(--accent) calc(var(--mx-glow,0) * 26%),transparent),
    0 2px 4px rgba(0,0,0,.78)}
.cable{box-shadow:0 0 4px rgba(0,0,0,.5),0 0 6px color-mix(in srgb,var(--accent) 45%,transparent)}

/* ══ THE AGE GATE ══
   A dialog, asked when PLAY is pressed. Dark and gold rather than the white card the rest of
   the industry uses, because this one belongs to the building it opens — but the shape is the
   familiar one on purpose: a visitor has seen this exact dialog before and should not have to
   read it twice to know what it wants. */

/* [hidden] is an attribute, and any rule that sets display beats it. The age panel did exactly
   that and showed itself next to the button it was supposed to replace. Stated once, here,
   so no later layout rule can undo it again. */
[hidden]{display:none!important}

/* Above the entry screen, which sits at 400 and was painting over this dialog: the gate has
   to be the topmost thing on the page or it is not a gate. */
.age-ov{position:fixed;inset:0;z-index:500;display:flex;align-items:center;justify-content:center;
  padding:24px;background:rgba(4,6,10,.78);backdrop-filter:blur(3px)}
.age-card{width:100%;max-width:400px;padding:30px 26px 26px;text-align:center;
  border-radius:12px;background:linear-gradient(180deg,#141a24,#0b0e15);
  border:1px solid rgba(216,162,74,.3);
  box-shadow:0 30px 80px rgba(0,0,0,.6),inset 0 1px 0 rgba(255,232,170,.14)}
.age-title{margin:0 0 14px;font-family:'Bebas Neue',sans-serif;font-weight:400;
  font-size:1.6rem;letter-spacing:2px;text-transform:uppercase;color:var(--accent-gold,#e8c37e)}
.age-p{margin:0 0 16px;font-size:.86rem;line-height:1.55;color:var(--ink-dim)}
.age-p b{color:var(--ink)}
.age-actions{display:flex;flex-direction:column;gap:10px;margin-top:20px}

/* The yes carries the gold because it is the ordinary answer; the no is a real button with a
   real target size, not a link pretending to be one — refusing has to be as easy as agreeing
   or the dialog is theatre. */
.age-yes{padding:14px 18px;border-radius:var(--r-key);cursor:pointer;
  font-family:'Bebas Neue',sans-serif;font-size:1.15rem;letter-spacing:1.6px;color:#1c1305;
  background:linear-gradient(175deg,#f0d27a,#cba049 42%,#a87c2c);
  border:1px solid rgba(255,232,170,.5);text-shadow:0 1px 0 rgba(255,255,255,.25);
  box-shadow:0 6px 18px rgba(180,140,40,.3),inset 0 1px 0 rgba(255,255,255,.4);
  transition:transform .1s,filter .15s}
.age-yes:hover{filter:brightness(1.06)}
.age-yes:active{transform:translateY(2px)}
.age-no{padding:13px 18px;border-radius:var(--r-key);cursor:pointer;
  font-family:'Bebas Neue',sans-serif;font-size:1.05rem;letter-spacing:1.4px;
  color:var(--ink-dim);background:transparent;border:1px solid var(--panel-line);
  transition:color .15s,border-color .15s}
.age-no:hover{color:var(--ink);border-color:rgba(255,255,255,.18)}
.age-yes:focus-visible,.age-no:focus-visible{outline:2px solid var(--accent-gold,#e8c37e);outline-offset:2px}

@media (max-width:420px){
  .age-card{padding:24px 18px 20px}
  .age-title{font-size:1.4rem}
}

/* ══ THE VAULT ══
   A card at the top of the chat, a chip at the top of the shaft, a badge beside BET. Never a
   modal, never over the cabin; the ride, the multiplier and CASH OUT are untouched by all of
   it. Gold is used only in the moment the vault opens. Countdown: the ring runs down around
   a locked door. At zero the wheel turns a turn and a half, the bolts draw back, light comes
   out of the middle and the card's rim warms once. A claim sends a ticket to the BET key.
   Transform and opacity only — nothing here repaints a layer per frame. */
.vault{flex:0 0 auto;margin:0 10px 8px;border-radius:10px;padding:12px;position:relative;overflow:hidden;
  background:linear-gradient(180deg,#0f1420,#0a0d14);border:1px solid rgba(232,195,126,.22);
  transition:border-color .6s,opacity .4s}
.vault[hidden]{display:none}
.vault.glow{border-color:rgba(232,195,126,.6);box-shadow:0 0 0 1px rgba(232,195,126,.15),0 0 26px rgba(232,195,126,.22)}
.vault.closed{opacity:.6}
.vault::before{content:"";position:absolute;top:0;left:14%;right:14%;height:1px;
  background:linear-gradient(90deg,transparent,#e8c37e,transparent);opacity:.7}
.vault::after{content:"";position:absolute;top:0;bottom:0;width:40%;left:-45%;pointer-events:none;
  background:linear-gradient(100deg,transparent,rgba(255,236,190,.16),transparent)}
.vault.shimmer::after{animation:vShim .8s ease-out}
.v-row{display:flex;align-items:center;gap:12px}
.v-door{width:46px;height:46px;flex:0 0 auto}
.v-door svg{width:46px;height:46px;overflow:visible;display:block}
.v-wheel,.v-bolts,.v-burst{transform-box:view-box;transform-origin:24px 24px}
.v-burst{opacity:0;transform:scale(.4)}
.v-arc{transition:stroke-dashoffset 1s linear}
.vault.opening .v-wheel{animation:vSpin 1.15s cubic-bezier(.55,0,.2,1)}
.vault.opening .v-bolts{animation:vBolts .45s .95s cubic-bezier(.3,.7,.2,1) both}
.vault.opening .v-burst{animation:vBurst 1.3s 1s ease-out both}
.vault.opening{animation:vWarm 1.6s .95s ease-out both}
.vault.opened .v-bolts{transform:scale(.8);opacity:.35}
.vault.opened .v-burst{opacity:.35;transform:scale(1)}
.v-text{flex:1;min-width:0}
.v-k{font:800 .5rem 'Inter',sans-serif;letter-spacing:2.4px;color:#e8c37e}
.v-h{font-family:'Bebas Neue',sans-serif;font-size:1.3rem;letter-spacing:1.5px;line-height:1.05;margin-top:2px;color:#fff}
.v-s{font-size:.62rem;color:var(--ink-dim);margin-top:2px}
.v-s b{font-family:'Share Tech Mono',monospace;font-weight:400;color:#fff}
.v-claim{flex:0 0 auto;min-height:0;font-family:'Bebas Neue',sans-serif;letter-spacing:2px;font-size:1.05rem;
  padding:9px 16px;border-radius:7px;border:0;cursor:pointer;background:linear-gradient(180deg,#f0d38c,#c79a48);color:#1c1305}
.v-claim[hidden]{display:none}
.v-claim:active{transform:translateY(1px)}
.v-claim.done{background:transparent;border:1px solid rgba(95,224,138,.45);color:#5fe08a;font-size:.88rem;cursor:default}
.v-claim:disabled:not(.done){opacity:.6}
.v-prog{margin-top:10px;height:3px;border-radius:2px;background:rgba(255,255,255,.07);overflow:hidden}
.v-prog i{display:block;height:100%;background:linear-gradient(90deg,#c79a48,#f0d38c);
  transform:scaleX(0);transform-origin:left;transition:transform .5s}
.v-meta{display:flex;justify-content:space-between;gap:8px;margin-top:6px;font-size:.56rem;color:var(--ink-faint)}
.v-meta b{font-family:'Share Tech Mono',monospace;font-weight:400;color:var(--ink-dim)}

.v-hint{position:absolute;z-index:6;top:10px;left:50%;transform:translateX(-50%);min-height:0;cursor:pointer;
  display:flex;align-items:center;gap:8px;white-space:nowrap;padding:6px 12px 6px 8px;border-radius:18px;
  background:rgba(6,8,12,.86);border:1px solid rgba(232,195,126,.32);animation:vHintIn .35s ease-out}
.v-hint[hidden]{display:none}
.v-hint-ring{width:20px;height:20px;flex:0 0 auto}
.v-hint-t{font:800 .5rem 'Inter',sans-serif;letter-spacing:2.2px;color:#e8c37e}
.v-hint-n{font-family:'Share Tech Mono',monospace;font-size:.7rem;color:#fff}

/* the chat mark turns gold while a vault is announced or open and not yet claimed */
.hdr-ico.vault-on{color:#f0d089}
.hdr-ico.vault-on::before{content:"";position:absolute;top:1px;right:0;width:7px;height:7px;border-radius:50%;background:#e8c37e}

.free-badge{position:absolute;z-index:3;right:16px;top:50%;transform:translateY(-50%);min-height:0;cursor:pointer;
  font:800 .52rem 'Inter',sans-serif;letter-spacing:1.5px;color:#241906;background:#fbe7b0;border:0;border-radius:10px;padding:5px 9px}
.free-badge[hidden]{display:none}
.free-badge.off{background:rgba(0,0,0,.35);color:#fbe7b0;box-shadow:inset 0 0 0 1px rgba(251,231,176,.5)}
.free-badge.pop{animation:vPop .45s cubic-bezier(.34,1.56,.64,1)}

.v-ticket{position:fixed;left:0;top:0;z-index:400;pointer-events:none;opacity:0;
  font:800 .52rem 'Inter',sans-serif;letter-spacing:1.6px;color:#241906;padding:5px 9px;border-radius:5px;
  background:linear-gradient(180deg,#fbe7b0,#d6aa55);box-shadow:0 6px 18px rgba(0,0,0,.5),0 0 16px rgba(242,196,90,.45)}

@keyframes vSpin{to{transform:rotate(540deg)}}
@keyframes vBolts{to{transform:scale(.8);opacity:.35}}
@keyframes vBurst{0%{opacity:0;transform:scale(.4)}35%{opacity:1;transform:scale(1.35)}100%{opacity:.35;transform:scale(1)}}
@keyframes vWarm{0%{box-shadow:0 0 0 1px rgba(232,195,126,0),0 0 0 rgba(232,195,126,0)}
  40%{box-shadow:0 0 0 1px rgba(232,195,126,.35),0 0 38px rgba(232,195,126,.35)}
  100%{box-shadow:0 0 0 1px rgba(232,195,126,.15),0 0 26px rgba(232,195,126,.22)}}
@keyframes vShim{to{transform:translateX(360%)}}
@keyframes vPop{0%{transform:translateY(-50%) scale(.6)}60%{transform:translateY(-50%) scale(1.15)}100%{transform:translateY(-50%) scale(1)}}
@keyframes vHintIn{from{opacity:0;transform:translate(-50%,-6px)}to{opacity:1;transform:translateX(-50%)}}
@media (prefers-reduced-motion:reduce){
  .vault,.vault *,.vault::after,.v-hint,.free-badge{animation:none!important;transition:none!important}
}

/* Phone: the read-out's glow in two shadows instead of five (see the phone block above). */
@media (max-width:700px), (max-width:1000px) and (max-height:620px) and (orientation:landscape){
  .cab-mult{text-shadow:
      0 0 calc(8px + var(--mx-glow,0) * 14px) color-mix(in srgb,var(--accent) calc(40% + var(--mx-glow,0) * 45%),transparent),
      0 2px 4px rgba(0,0,0,.78)}
}

/* ══ THE LAST ROUNDS ON A PHONE ══
   The same as the desktop: the bar stays black, and the multipliers get a band of their own
   under it, a shade lighter, with a hairline — two separate things instead of one block. */
@media (max-width:999px){
  :root{--strip-m:26px}
  .hdr{gap:0}
  .hdr .hist-strip{height:var(--strip-m)}
  .hdr::before{bottom:var(--strip-m)}
  .hdr::after{content:'';position:absolute;left:calc(50% - 50vw);right:calc(50% - 50vw);bottom:0;
    height:var(--strip-m);background:#0b0d12;border-bottom:1px solid rgba(255,255,255,.06);pointer-events:none}
  .hdr > *{z-index:1}
}
