:root{
  --bg:#0f0d09;--surface:#1c1810;--s2:#26210f;--s3:#332b16;--line:rgba(255,255,255,.09);
  --txt:#f7f1e4;--txt2:#a89a7e;--txt3:#8a7f68;--ok:#46c56a;--okd:#2b9a4c;--bad:#f05a48;
  --acc:#f4a72c;--demo:#38b9cb;--real:#ffce3a;--wood:#c8843f;--wire:#9aa0ac;--concrete:#8a847a;
  --safe-t:env(safe-area-inset-top,0px);--safe-b:env(safe-area-inset-bottom,0px);
}
*{box-sizing:border-box}
/* App shell: lock the document so mobile URL/toolbars can't leave the
   game scrolled off-screen (classic "pull down → stuck under chrome" bug). */
html,body{
  margin:0;width:100%;height:100%;height:100dvh;height:100svh;
  background:var(--bg);overflow:hidden;overscroll-behavior:none;
  touch-action:none;position:fixed;inset:0;
  -webkit-text-size-adjust:100%
}
body{font-family:'Space Grotesk',system-ui,sans-serif;color:var(--txt);-webkit-tap-highlight-color:transparent}
.tnum{font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1}
button{font-family:inherit;-webkit-tap-highlight-color:transparent}

#app{
  position:fixed;left:0;right:0;top:0;
  height:var(--app-h,100dvh);height:var(--app-h,100svh);
  display:flex;flex-direction:column;
  touch-action:manipulation;overflow:hidden;
  padding-left:env(safe-area-inset-left,0px);
  padding-right:env(safe-area-inset-right,0px)
}

/* ===== Scene ===== */
/* Layered farm scene: sky → clouds → bg-far → grass → world → ram → fx */
#scene{position:relative;flex:1;min-height:0;overflow:hidden;background:#aee0f5;container-type:size}
#scene.risk-1{filter:none}
#scene.risk-2{filter:saturate(1.05) hue-rotate(-4deg)}
#scene.risk-3{filter:saturate(1.15) hue-rotate(-9deg) brightness(.97)}

.layer{position:absolute;inset:0;pointer-events:none}
/* Sky belongs to the LOCATION (see biome block below); risk stage layers a
   dusk wash on top of whichever sky is showing, so tension reads the same in
   all three biomes without nine hand-written gradients. The wash is its own
   layer rather than a #sky pseudo so the warp animation can pick it up with
   the other scene layers. */
#sky{background:linear-gradient(180deg,#aee0f5 0%,#cdeefb 55%,#e8f7ff 100%);transition:background 900ms ease}
#dusk{background:linear-gradient(180deg,rgba(58,44,110,.6) 0%,rgba(206,118,58,.5) 58%,rgba(240,152,84,.6) 100%);
  opacity:0;transition:opacity 900ms ease}
#scene.risk-2 #dusk{opacity:.4}
#scene.risk-3 #dusk{opacity:.8}

/* drifting clouds: slow ambient CSS loop + -0.15x dash parallax on the container */
#clouds{transition:transform 450ms cubic-bezier(.6,.02,.9,.6);will-change:transform;contain:layout style;backface-visibility:hidden}
.cloud-slot{position:absolute;pointer-events:none}
.cloud-slot img{width:100%;display:block;animation:cloud-drift linear infinite}
/* fade at both ends so the loop restart never pops on screen */
@keyframes cloud-drift{0%{transform:translateX(14vw);opacity:0}10%{opacity:1}88%{opacity:1}100%{transform:translateX(-120vw);opacity:0}}

/* far farm objects strip: -0.45x dash parallax */
#bg-far{position:absolute;left:0;width:100%;bottom:20cqw;height:44cqw;pointer-events:none;transition:transform 450ms cubic-bezier(.6,.02,.9,.6);will-change:transform;contain:layout style;backface-visibility:hidden}
.bg-obj{position:absolute;bottom:0;transform:translateX(-50%);pointer-events:none}
.bg-obj img{height:100%;width:auto;display:block;filter:saturate(.75) brightness(.96) opacity(.92)}

/* ground strip the ram runs over: -1.0x dash scroll via background-position-x.
   The tile image comes from the biome; the gradient underneath is the fallback
   when that tile is missing. JS only ever sets --ground-tile, so the fallback
   gradient underneath it is never clobbered by a tile swap. */
#grass{position:absolute;left:0;right:0;bottom:0;height:22cqw;pointer-events:none}
/* The ground scroll rides on a 400%-wide inner track translated by JS.
   transform is compositor-only; the old background-position-x transition
   repainted the whole strip every frame and was the main dash jank on
   weak phones. The fallback gradient lives on the track so a missing tile
   still shows grass. */
#grass-track{position:absolute;top:0;bottom:0;left:0;width:400%;
  will-change:transform;backface-visibility:hidden;
  background-image:var(--ground-tile,none),linear-gradient(180deg,#79b447 0%,#4f8a2e 60%,#3c6a22 100%);
  background-repeat:repeat-x;background-size:auto 100%;
  transition:transform 450ms cubic-bezier(.6,.02,.9,.6)}
/* haze that melts the strip's top edge into the sky */
#grass::before{content:'';position:absolute;left:0;right:0;bottom:100%;height:34%;
  background:linear-gradient(180deg,rgba(146,196,110,0) 0%,rgba(146,196,110,.35) 55%,rgba(110,166,80,.75) 100%)}

/* ===== Locations ===== */
/* Difficulty picks the world: Lamb → home farm, Normal → deep forest,
   Full Ram → city street. Each biome owns its sky, ground fallback, horizon
   haze and the tint applied to the far scenery and cloud sprites. */
#scene.loc-forest #sky{background:linear-gradient(180deg,#2f5b4c 0%,#5d8a5f 42%,#9dbc80 78%,#c3d49a 100%)}
#scene.loc-forest #grass-track{
  background-image:var(--ground-tile,none),linear-gradient(180deg,#4f7a35 0%,#395a25 60%,#2a431c 100%)}
#scene.loc-forest #grass::before{
  background:linear-gradient(180deg,rgba(92,140,96,0) 0%,rgba(76,120,80,.4) 55%,rgba(52,88,58,.8) 100%)}
#scene.loc-forest .bg-obj img{filter:saturate(.8) brightness(.78) opacity(.94)}
/* clouds double as low mist here: bleached out and soft */
#scene.loc-forest .cloud-slot img{filter:saturate(.15) brightness(1.06) blur(2px)}

#scene.loc-city #sky{background:linear-gradient(180deg,#4c6182 0%,#8497ac 46%,#bcc4cc 80%,#d8dade 100%)}
#scene.loc-city #grass-track{
  background-image:var(--ground-tile,none),linear-gradient(180deg,#5a5f66 0%,#3d4147 60%,#2b2e33 100%)}
#scene.loc-city #grass::before{
  background:linear-gradient(180deg,rgba(140,150,162,0) 0%,rgba(118,128,140,.4) 55%,rgba(84,92,102,.8) 100%)}
#scene.loc-city .bg-obj img{filter:saturate(.55) brightness(.86) opacity(.9)}
/* clouds double as smog here: grey, flat, heavy */
#scene.loc-city .cloud-slot img{filter:saturate(.08) brightness(.82) blur(1px)}

/* ===== Location warp ===== */
/* A dark band sweeps across, the world dims to a near-black blink under it,
   the new biome is built at the darkest point, and the location name punches
   in. Dark, not white — a white-out is blinding on a phone at night. */
#warp{opacity:0;z-index:6;background-size:280% 100%;background-position:-90% 0;
  background-image:linear-gradient(102deg,
    rgba(10,12,20,0) 36%,rgba(90,140,200,.25) 43%,rgba(10,12,20,.94) 48%,
    rgba(70,115,180,.22) 53%,rgba(10,12,20,0) 62%)}
#scene.warping #warp{animation:warp-sweep 760ms cubic-bezier(.45,0,.3,1)}
@keyframes warp-sweep{
  0%{opacity:0;background-position:-90% 0}
  14%{opacity:1}
  86%{opacity:1}
  100%{opacity:0;background-position:190% 0}
}
/* the world itself dims down and back up — transform is off-limits on these
   layers (parallax owns it), so the blink is filter + opacity only.
   Darkest span is 40-46% of 760ms = 304-350ms, covering the 330ms swap. */
#scene.warping #sky,#scene.warping #dusk,#scene.warping #clouds,#scene.warping #bg-far,
#scene.warping #grass,#scene.warping #world,#scene.warping #ram{
  animation:warp-bloom 760ms cubic-bezier(.45,0,.3,1)}
@keyframes warp-bloom{
  0%{filter:none;opacity:1}
  40%{filter:brightness(.35) saturate(.6) blur(5px);opacity:.5}
  46%{filter:brightness(.2) saturate(.4) blur(7px);opacity:.35}
  62%{filter:brightness(.6) saturate(.85) blur(3px);opacity:.75}
  100%{filter:none;opacity:1}
}
#scene.warping{animation:warp-punch 760ms cubic-bezier(.45,0,.3,1)}
@keyframes warp-punch{
  0%{transform:scale(1)}
  44%{transform:scale(1.06)}
  100%{transform:scale(1)}
}

/* ===== Soft reset ===== */
/* Every-round blink (crash "Next round" / win "Continue"): a gentle 280ms dip
   on the same layer set the warp uses. Filter + opacity only — no transform
   (parallax owns it), no sweep band, no scale punch. The world swaps at the
   50% mark (140ms), hidden under the soft dim. Barely noticeable on purpose:
   this plays every round, the full warp is reserved for biome switches. */
#scene.soft-reset #sky,#scene.soft-reset #dusk,#scene.soft-reset #clouds,#scene.soft-reset #bg-far,
#scene.soft-reset #grass,#scene.soft-reset #world,#scene.soft-reset #ram{
  animation:soft-dip 280ms ease-in-out}
@keyframes soft-dip{
  0%{filter:none;opacity:1}
  50%{filter:brightness(.8) saturate(.9) blur(1.5px);opacity:.85}
  100%{filter:none;opacity:1}
}

#loc-toast{position:absolute;left:50%;top:38%;transform:translate(-50%,-50%) scale(.7);
  z-index:7;pointer-events:none;opacity:0;
  font-weight:800;font-size:clamp(18px,7cqw,40px);letter-spacing:.14em;text-transform:uppercase;
  color:#fff;text-shadow:0 2px 0 rgba(0,0,0,.45),0 0 18px rgba(140,220,255,.55);white-space:nowrap}
#loc-toast.show{animation:loc-toast-in 900ms cubic-bezier(.2,.9,.3,1)}
@keyframes loc-toast-in{
  0%{opacity:0;transform:translate(-50%,-50%) scale(.7)}
  28%{opacity:1;transform:translate(-50%,-50%) scale(1.06)}
  40%{transform:translate(-50%,-50%) scale(1)}
  74%{opacity:1}
  100%{opacity:0;transform:translate(-50%,-58%) scale(1)}
}

/* Vignette: static radial gradient, only opacity animates (compositor-only).
   The old inset box-shadow transition repainted the full scene every frame. */
#vignette{opacity:0;transition:opacity 400ms ease;
  background:radial-gradient(ellipse 106% 94% at 50% 46%,rgba(140,20,10,0) 50%,rgba(150,20,10,.38) 82%,rgba(170,20,10,.55) 100%)}
#scene.risk-2 #vignette{opacity:.4}
#scene.risk-3 #vignette{opacity:.7}
#scene.crash-tint #vignette{opacity:1}

/* ===== World strip (scrolling pen) ===== */
#world{position:absolute;left:0;right:-300%;bottom:9cqw;height:52cqw;will-change:transform;transition:transform 450ms cubic-bezier(.6,.02,.9,.6);contain:layout style;backface-visibility:hidden}
.world-item{position:absolute;bottom:0;transform:translateX(-50%)}
.world-item svg,.world-item img{width:100%;height:100%;object-fit:contain;display:block;filter:drop-shadow(0 6px 8px rgba(0,0,0,.35))}

/* Ram: fixed on screen, outside the world strip */
#ram{position:absolute;left:28%;bottom:9cqw;width:30cqw;aspect-ratio:12/10;transform:translateX(-50%);will-change:transform;z-index:3}
#ram svg,#ram img,#ram div{width:100%;height:100%;object-fit:contain;display:block;filter:drop-shadow(0 6px 8px rgba(0,0,0,.35))}
#ram.running{animation:ram-bounce .22s ease-in-out infinite}
/* forwards: hold the impact pose if the network lags past DASH_MS (mobile). */
#ram.lunge{animation:ram-lunge 450ms cubic-bezier(.6,.02,.9,.6) forwards}
@keyframes ram-lunge{
  0%{transform:translateX(-50%) scale(1,1)}
  20%{transform:translateX(calc(-50% - 14px)) rotate(2deg) scale(1.04,0.94)}   /* gather back, slight vertical squash */
  100%{transform:translateX(calc(-50% + 30px)) rotate(-4deg) scale(0.86,1.16)} /* thrust: horizontal stretch + vertical compression at impact */
}
/* Crash choreography, three one-shots in a row (see playKnockdown in game.js):
   .crashed  — impact squash, driven back, hooves leave the ground, tips over
   .ko-land  — sprite is now the seated pose: rump slams down, squash, bounce
   .ko-stunned — resting hold, keeps him sitting where he landed
   Pivot is the hooves so the topple rotates around his feet, not his middle. */
#ram.crashed{animation:ram-topple 480ms cubic-bezier(.4,0,.7,1) forwards;transform-origin:50% 100%}
#ram.ko-land{animation:ko-land 320ms cubic-bezier(.2,.9,.3,1) forwards;transform-origin:50% 100%}
/* Offsets are cqw, not px: #ram is sized in cqw, so px offsets would push him
   off the left edge of the scene on narrow phones. */
#ram.ko-stunned{transform:translate(calc(-50% - 11cqw),2.1cqw)}
/* Idle breathing: subtle inhale/exhale when ram is at rest (spritesheet or static).
   Gated by .reduced-motion. Phones use a slightly stronger, cheaper loop
   (transform only — no spritesheet decode). */
#ram:not(.running):not(.lunge):not(.crashed):not(.ko-land):not(.ko-stunned){
  animation:ram-idle-breath 3.2s ease-in-out infinite;will-change:transform
}
@keyframes ram-idle-breath{
  0%,100%{transform:translateX(-50%) scale(1,1) translateY(0) rotate(0)}
  45%{transform:translateX(-50%) scale(1.028,1.055) translateY(-1%) rotate(-.6deg)}
}
/* Lite: more readable bob, still compositor-only (no background-position sheet). */
html.lite-fx #ram:not(.running):not(.lunge):not(.crashed):not(.ko-land):not(.ko-stunned){
  animation:ram-idle-breath-lite 2.4s ease-in-out infinite
}
@keyframes ram-idle-breath-lite{
  0%,100%{transform:translateX(-50%) scale(1,1) translateY(0) rotate(0)}
  35%{transform:translateX(-50%) scale(1.045,1.07) translateY(-2.2%) rotate(-1.2deg)}
  70%{transform:translateX(-50%) scale(1.02,1.03) translateY(-.6%) rotate(.4deg)}
}
.page-hidden #ram{animation-play-state:paused}
.reduced-motion #ram:not(.running):not(.lunge):not(.crashed):not(.ko-land):not(.ko-stunned){animation:none}
@keyframes ram-bounce{0%,100%{transform:translateX(-50%) translateY(0) rotate(0)}50%{transform:translateX(-50%) translateY(-10%) rotate(-3deg)}}
/* Knocked off his hooves: squash on impact, driven backwards, front legs come
   up, then he tips over onto his rump. Ends mid-air just before the landing —
   .ko-land picks the motion up from there with the seated sprite. */
@keyframes ram-topple{
  0%{transform:translateX(-50%) rotate(0) scale(1,1)}
  12%{transform:translate(calc(-50% - 4.3cqw),.5cqw) rotate(-8deg) scale(0.92,1.09)}  /* impact squash */
  34%{transform:translate(calc(-50% - 10cqw),-2cqw) rotate(-22deg) scale(0.9,1.11)}   /* hooves leave the ground */
  62%{transform:translate(calc(-50% - 14cqw),-3.7cqw) rotate(-34deg) scale(0.95,1.05)}/* peak of the tip-over */
  100%{transform:translate(calc(-50% - 15.5cqw),-3.2cqw) rotate(-40deg) scale(1,1)}   /* rump about to hit */
}
/* Rump lands. Starts on exactly the transform ram-topple ends on — same values,
   same pivot — so swapping in the seated sprite at this instant does not pop. */
@keyframes ko-land{
  0%{transform:translate(calc(-50% - 15.5cqw),-3.2cqw) rotate(-40deg) scale(1,1)}
  38%{transform:translate(calc(-50% - 14cqw),2.1cqw) rotate(-8deg) scale(1.22,0.8)}   /* thud — flattens on the ground */
  62%{transform:translate(calc(-50% - 12.5cqw),.5cqw) rotate(4deg) scale(0.93,1.08)}  /* rebound */
  82%{transform:translate(calc(-50% - 11.5cqw),2.1cqw) rotate(-2deg) scale(1.07,0.95)}
  100%{transform:translate(calc(-50% - 11cqw),2.1cqw) rotate(0) scale(1,1)}           /* settle into the sit */
}

/* Cartoon stars circling the head while he is stunned. The ring rotates and
   each star counter-rotates by the same amount so it never tumbles. */
/* Parked over the seated ram's head. Selectors must be #ram-scoped: the plain
   `#ram div` sizing rule above is an ID selector and would otherwise win and
   blow the ring up to the full sprite box. The head renders slightly ABOVE
   #ram's top edge (the sheet is scaled 2x about a 78% origin), hence top < 0.
   The ring stays circular — flattening the container squashes the stars too. */
#ram .ko-stars{position:absolute;left:67%;top:-11cqw;width:11cqw;height:11cqw;
  transform:translate(-50%,-50%);pointer-events:none;z-index:2}
#ram .ko-stars i{position:absolute;left:50%;top:50%;width:3.6cqw;height:3.6cqw;margin:-1.8cqw 0 0 -1.8cqw;
  background:#ffd94a;filter:drop-shadow(0 1px 0 rgba(140,90,0,.55));
  clip-path:polygon(50% 0,61% 35%,98% 35%,68% 57%,79% 91%,50% 70%,21% 91%,32% 57%,2% 35%,39% 35%);
  animation:ko-star-orbit 1.5s linear infinite}
#ram .ko-stars i:nth-child(2){animation-delay:-.5s}
#ram .ko-stars i:nth-child(3){animation-delay:-1s}
@keyframes ko-star-orbit{
  0%{transform:rotate(0) translateX(115%) rotate(0) scale(.75);opacity:.45}
  50%{transform:rotate(180deg) translateX(115%) rotate(-180deg) scale(1.15);opacity:1}
  100%{transform:rotate(360deg) translateX(115%) rotate(-360deg) scale(.75);opacity:.45}
}

/* the ewe waits in her cabrio — reads as a whole car scene */
#sheep{width:52cqw;aspect-ratio:916/353}
#sheep img,#sheep svg{filter:drop-shadow(0 6px 8px rgba(0,0,0,.35)) drop-shadow(0 0 0 rgba(255,255,255,0));transition:filter 400ms ease}
#sheep.stage-2 img,#sheep.stage-2 svg{filter:drop-shadow(0 6px 8px rgba(0,0,0,.35)) drop-shadow(0 0 10px rgba(240,162,90,.5))}
#sheep.stage-3 img,#sheep.stage-3 svg{filter:drop-shadow(0 6px 8px rgba(0,0,0,.35)) drop-shadow(0 0 16px rgba(239,122,107,.65))}

#sheep.stage-up{animation:ewe-stage-pulse 500ms ease}
@keyframes ewe-stage-pulse{0%{transform:translateX(-50%) scale(1)}40%{transform:translateX(-50%) scale(1.06)}100%{transform:translateX(-50%) scale(1)}}

.heart-particle{position:absolute;font-size:16px;pointer-events:none;opacity:0;animation:heart-float 900ms ease-out forwards}
@keyframes heart-float{0%{opacity:0;transform:translate(0,0) scale(.5) rotate(0deg)}20%{opacity:1;transform:translate(-4px,-14px) scale(1) rotate(-8deg)}40%{transform:translate(6px,-28px) scale(1.1) rotate(5deg)}70%{transform:translate(-2px,-48px) scale(.9) rotate(-3deg)}100%{opacity:0;transform:translate(3px,-72px) scale(.6) rotate(10deg)}}

/* world is 400% of the scene, so scene-relative sizing goes through min(px, vw) */
.obstacle{width:37cqw;aspect-ratio:1/1;bottom:0}
.obstacle img.flip{transform:scaleX(-1)}
.obstacle.standing-shake{animation:obstacle-stand-shake .45s ease}
@keyframes obstacle-stand-shake{0%,100%{transform:translateX(-50%)}20%{transform:translate(calc(-50% + 5px),0) rotate(2deg)}45%{transform:translate(calc(-50% - 4px),0) rotate(-1.6deg)}70%{transform:translate(calc(-50% + 3px),0) rotate(1deg)}}
/* broken fences disappear entirely — no wreckage stays on the ground */
/* flying shards on break */
.shard{position:absolute;inset:0;pointer-events:none}
.shard>img,.shard>svg{width:100%;height:100%;object-fit:contain}
.shard.s1{clip-path:polygon(0 0,60% 0,35% 100%,0 100%);animation:shard-fly-1 560ms cubic-bezier(.2,.7,.4,1) forwards}
.shard.s2{clip-path:polygon(60% 0,100% 0,100% 55%,35% 100%);animation:shard-fly-2 560ms cubic-bezier(.2,.7,.4,1) forwards}
.shard.s3{clip-path:polygon(100% 55%,100% 100%,35% 100%);animation:shard-fly-3 560ms cubic-bezier(.2,.7,.4,1) forwards}
@keyframes shard-fly-1{to{opacity:0;transform:translate(-70px,-90px) rotate(-70deg)}}
@keyframes shard-fly-2{to{opacity:0;transform:translate(60px,-110px) rotate(55deg)}}
@keyframes shard-fly-3{to{opacity:0;transform:translate(40px,-40px) rotate(120deg)}}
.reduced-motion .shard{display:none}

/* Phone shatter: transform/opacity only — no clip-path clones */
.obstacle.shatter-pop{animation:obstacle-shatter-pop 380ms cubic-bezier(.2,.7,.4,1) forwards}
@keyframes obstacle-shatter-pop{
  0%{opacity:1;transform:translateX(-50%) scale(1) rotate(0)}
  35%{opacity:1;transform:translateX(-50%) scale(1.18,1.05) rotate(-6deg)}
  100%{opacity:0;transform:translateX(calc(-50% + 18px)) scale(1.35,.55) rotate(12deg)}
}
.reduced-motion .obstacle.shatter-pop{animation:none;opacity:0}

/* ===== Tension telegraph: obstacle quivers during dash approach ===== */
@keyframes obstacle-tension-shake{
  0%{transform:translateX(-50%) translate(0,0) rotate(0)}
  18%{transform:translateX(-50%) translate(3px,0.5px) rotate(1.2deg)}
  36%{transform:translateX(-50%) translate(-2.5px,-0.5px) rotate(-0.9deg)}
  54%{transform:translateX(-50%) translate(3.5px,0.3px) rotate(1.5deg)}
  72%{transform:translateX(-50%) translate(-2px,-0.3px) rotate(-0.6deg)}
  88%{transform:translateX(-50%) translate(2px,0.2px) rotate(0.8deg)}
  100%{transform:translateX(-50%) translate(0,0) rotate(0)}
}
.obstacle.tension-shudder{
  animation:obstacle-tension-shake 350ms ease-in-out forwards;
  will-change:transform;
}

/* pen dressing: small fence posts along the ground line */
/* pre-broken fence piece behind the ram at round start */

.burst{position:absolute;width:120px;height:120px;transform:translate(-50%,-50%);pointer-events:none;opacity:0}
.burst.play{animation:burst-play 480ms ease-out forwards}
@keyframes burst-play{0%{opacity:0;transform:translate(-50%,-50%) scale(.4)}25%{opacity:1}100%{opacity:0;transform:translate(-50%,-50%) scale(1.6)}}

.dust{position:absolute;bottom:6%;width:200px;height:80px;transform:translate(-50%,0);background:radial-gradient(ellipse at center,rgba(120,90,60,.55),transparent 70%);opacity:0;pointer-events:none}
.dust.play{animation:dust-play 650ms ease-out forwards}
@keyframes dust-play{0%{opacity:0;transform:translate(-50%,0) scale(.5)}20%{opacity:.8}100%{opacity:0;transform:translate(-50%,0) scale(1.6)}}

/* spark/flint particles on impact — per-material color tint via inline style */
.spark{position:absolute;width:6px;height:6px;border-radius:50%;transform:translate(-50%,-50%);pointer-events:none;opacity:0}
.spark.play{animation:spark-fly 440ms ease-out forwards}
@keyframes spark-fly{0%{opacity:0;transform:translate(-50%,-50%) scale(0)}30%{opacity:1;transform:translate(calc(var(--sx,0)*1px),calc(var(--sy,0)*1px)) scale(1)}100%{opacity:0;transform:translate(calc(var(--sx,0)*1.5px),calc(var(--sy,0)*1.5px)) scale(.3)}}

/* hoof-print trail — small dark stamps left behind the ram */
.hoof-print{position:absolute;bottom:max(8%,24px);width:14px;height:10px;background:rgba(40,28,12,.35);border-radius:40% 40% 50% 50%;transform:translate(-50%,0) scale(0);pointer-events:none;opacity:0}
.hoof-print.play{animation:hoof-print-fade 1200ms ease-out forwards}
@keyframes hoof-print-fade{0%{opacity:0;transform:translate(-50%,0) scale(0)}15%{opacity:.7;transform:translate(-50%,0) scale(1)}100%{opacity:0;transform:translate(-50%,0) scale(.8)}}

#scene.shake{animation:screen-shake 380ms cubic-bezier(.36,.07,.19,.97)}
#scene.shake-big{animation:screen-shake-big 550ms cubic-bezier(.36,.07,.19,.97)}
@keyframes screen-shake{0%,100%{transform:translate(0,0)}20%{transform:translate(-6px,3px)}40%{transform:translate(5px,-3px)}60%{transform:translate(-4px,2px)}80%{transform:translate(3px,-1px)}}
@keyframes screen-shake-big{0%,100%{transform:translate(0,0)}10%{transform:translate(-14px,6px) rotate(-.6deg)}25%{transform:translate(12px,-8px) rotate(.6deg)}40%{transform:translate(-10px,6px)}55%{transform:translate(8px,-4px)}70%{transform:translate(-6px,3px)}85%{transform:translate(4px,-2px)}}

#impact-flash{position:absolute;inset:0;background:#fff;opacity:0;pointer-events:none}
#impact-flash.play{animation:impact-flash-play 220ms ease-out forwards}
@keyframes impact-flash-play{0%{opacity:.85}100%{opacity:0}}

.float-win{position:absolute;left:50%;top:40%;transform:translate(-50%,0);font-family:'Fredoka',sans-serif;font-weight:700;font-size:clamp(22px,5vw,34px);color:var(--ok);text-shadow:0 2px 10px rgba(0,0,0,.5);opacity:0;pointer-events:none}
.float-win.play{animation:float-win-play 1100ms ease-out forwards}
@keyframes float-win-play{0%{opacity:0;transform:translate(-50%,10px) scale(.8)}15%{opacity:1;transform:translate(-50%,-6px) scale(1.1)}30%{transform:translate(-50%,0) scale(1)}100%{opacity:0;transform:translate(-50%,-60px) scale(1)}}

/* ===== Header ===== */
#header{position:relative;z-index:5;display:flex;align-items:flex-start;gap:10px;padding:calc(10px + var(--safe-t)) 14px 10px;background:linear-gradient(180deg,rgba(15,13,9,.92),rgba(15,13,9,.55));border-bottom:1px solid var(--line);backdrop-filter:blur(6px)}
#brand-col{display:flex;flex-direction:column;gap:3px}
#wordmark{display:flex;align-items:center;gap:8px}
#logo{width:36px;height:36px;border-radius:10px;background:linear-gradient(150deg,#f4a72c,#e07c2b);display:grid;place-items:center;font-family:'Fredoka';font-weight:700;font-size:18px;color:#231705;flex:none}
#brand{font-family:'Fredoka';font-weight:700;font-size:18px;line-height:1}
#tagline{font-family:'Fredoka';font-weight:500;font-size:11px;color:var(--txt2);line-height:1.3;letter-spacing:.02em}
.badge{font-size:9.5px;font-weight:600;color:var(--txt2);border:1px solid color-mix(in srgb,var(--txt2) 40%,transparent);background:color-mix(in srgb,var(--txt2) 12%,transparent);padding:2px 7px;border-radius:20px;white-space:nowrap;width:fit-content}
#balance-wrap{margin-left:auto;text-align:right;line-height:1.1}
#balance-label{font-size:11px;color:var(--txt3);text-transform:uppercase;letter-spacing:.06em}
#balance{font-family:'Fredoka';font-weight:600;font-size:17px}
#balance.pop{animation:pop .28s ease}
@keyframes pop{0%{transform:scale(1)}45%{transform:scale(1.15)}100%{transform:scale(1)}}
#balance.balance-flash-up{animation:balance-flash-up 400ms ease, pop .28s ease}
@keyframes balance-flash-up{0%{background-color:transparent}25%{background-color:color-mix(in srgb,var(--ok) 28%,transparent)}100%{background-color:transparent}}
#balance.balance-flash-down{animation:balance-flash-down 400ms ease, pop .28s ease}
@keyframes balance-flash-down{0%{background-color:transparent}25%{background-color:color-mix(in srgb,var(--bad) 28%,transparent)}100%{background-color:transparent}}
#settings-btn{margin-left:8px;width:36px;height:36px;min-width:36px;border-radius:10px;border:1px solid var(--line);background:var(--surface);color:var(--txt2);display:grid;place-items:center;cursor:pointer;font-size:16px;position:relative}
#settings-btn::after{content:'';position:absolute;inset:-6px}
#settings-btn:active{transform:scale(.92)}
#rules-btn{margin-left:6px;width:36px;height:36px;min-width:36px;border-radius:10px;border:1px solid var(--line);background:var(--surface);color:var(--txt2);display:grid;place-items:center;cursor:pointer;font-family:'Fredoka';font-weight:700;font-size:17px;position:relative}
#rules-btn::after{content:'';position:absolute;inset:-6px}
#rules-btn:hover{background:var(--s3);color:var(--txt)}
#rules-btn:active{transform:scale(.92)}
#rules-btn:focus-visible{box-shadow:0 0 0 2px var(--acc)}

/* ===== History strip ===== */
#history-row{position:relative;z-index:5;display:flex;align-items:center;background:rgba(15,13,9,.55);border-bottom:1px solid var(--line)}
#history{flex:1;min-width:0;display:flex;gap:6px;padding:8px 14px;overflow-x:auto;scrollbar-width:none;touch-action:pan-x;-webkit-overflow-scrolling:touch}
#history::-webkit-scrollbar{display:none}
.hchip{flex:none;font-size:11.5px;font-weight:700;padding:4px 9px;border-radius:8px;font-family:'Fredoka'}
.hchip.tier-gray{color:#a9b0bc;background:color-mix(in srgb,#a9b0bc 14%,transparent);border:1px solid color-mix(in srgb,#a9b0bc 35%,transparent)}
.hchip.tier-blue{color:#7db6ff;background:color-mix(in srgb,#7db6ff 16%,transparent);border:1px solid color-mix(in srgb,#7db6ff 40%,transparent)}
.hchip.tier-gold{color:#ffcf33;background:color-mix(in srgb,#ffcf33 16%,transparent);border:1px solid color-mix(in srgb,#ffcf33 40%,transparent)}
.hchip.tier-crash{color:#ff5d6c;background:color-mix(in srgb,#ff5d6c 14%,transparent);border:1px solid color-mix(in srgb,#ff5d6c 35%,transparent)}
.hchip.empty{color:var(--txt3);font-weight:500}

/* Empty history strip — centered welcome that reads as deliberate design
   rather than a missing feature. Same compact height as the filled strip. */
.history-empty{flex:1;text-align:center;font-family:'Fredoka';font-weight:500;font-size:11.5px;color:var(--txt3);padding:4px 9px;border:1px dashed color-mix(in srgb,var(--txt3) 30%,transparent);border-radius:8px;background:color-mix(in srgb,var(--txt3) 5%,transparent)}

/* "View all" button — pinned at the right end of the history strip */
#history-view-all{display:none;flex:none;margin:0 14px 0 8px;padding:8px 16px;border-radius:8px;border:1px solid var(--line);background:var(--s2);color:var(--txt2);font-family:'Fredoka';font-weight:600;font-size:11px;cursor:pointer;transition:background .15s ease;position:relative;box-shadow:-12px 0 10px -6px rgba(15,13,9,.8)}
#history-view-all::after{content:'';position:absolute;inset:-6px}
#history-view-all:hover{background:var(--s3);color:var(--txt)}
#history-view-all:active{transform:scale(.96)}
#history-view-all:focus-visible{box-shadow:0 0 0 2px var(--acc)}

/* ===== HUD over scene ===== */
#hud{position:absolute;top:8px;left:0;right:0;display:flex;flex-direction:column;align-items:center;pointer-events:none;z-index:4}
#mult-display{text-align:center;background:rgba(15,13,9,.55);border:1px solid var(--line);border-radius:14px;padding:6px 18px;backdrop-filter:blur(4px)}
#mult-label{font-size:11px;color:var(--txt3);text-transform:uppercase;letter-spacing:.08em}
#mult-value{font-family:'Fredoka';font-weight:700;font-size:clamp(24px,7vw,34px);line-height:1.1;transition:color 300ms ease}
#mult-value.pop{animation:pop .3s ease}
/* multiplier color tiers — cream (safe) → amber (warming) → coral (hot) */
#mult-value.mult-safe{color:#efe0c8}
#mult-value.mult-warming{color:var(--acc)}
#mult-value.mult-hot{color:#ff6b5b}
#payout-preview{font-size:12.5px;color:var(--txt2)}
#payout-preview b{color:var(--txt)}
#tension-meter{display:flex;gap:5px;justify-content:center;margin-top:6px;background:rgba(15,13,9,.55);border:1px solid var(--line);border-radius:14px;padding:4px 10px;backdrop-filter:blur(4px)}
.tm-dot{width:12px;height:12px;border-radius:50%;background:var(--s3);border:1.5px solid var(--line);transition:background-color 300ms ease}
.tm-dot.filled{background:var(--tm-fill);border-color:transparent}
.reduced-motion .tm-dot{transition-duration:.001ms}
#stage-badge{position:absolute;top:8px;right:10px;font-size:10.5px;font-weight:600;padding:4px 9px;border-radius:20px;background:rgba(15,13,9,.55);border:1px solid var(--line);z-index:4}

/* ===== Control panel ===== */
#panel{position:relative;z-index:5;background:var(--surface);border-top:1px solid var(--line);padding:12px 14px calc(12px + var(--safe-b));display:flex;flex-direction:column;gap:10px}
.row{display:flex;align-items:center;gap:8px}
.row.between{justify-content:space-between}
#bet-row{gap:8px}
#bet-stepper{display:flex;align-items:center;background:var(--s2);border:1px solid var(--line);border-radius:12px;flex:1;overflow:hidden}
.step-btn{width:44px;height:44px;min-width:44px;border:none;background:transparent;color:var(--txt);font-size:20px;font-family:'Fredoka';cursor:pointer;display:flex;align-items:center;justify-content:center;line-height:1}
.step-btn:active{background:var(--s3);transform:scale(.96)}
.step-btn:disabled{opacity:.35;cursor:default}
#bet-input{flex:1;text-align:center;font-family:'Fredoka';font-weight:600;font-size:18px;color:var(--txt);background:transparent;border:none;outline:none;padding:0;margin:0;width:100%;min-width:0}
#bet-input::placeholder{color:var(--txt3)}
#bet-input:focus-visible{box-shadow:0 0 0 2px var(--acc);border-radius:4px;outline:none}
#chips{display:flex;gap:6px;overflow-x:auto;scrollbar-width:none;padding-bottom:2px;touch-action:pan-x;-webkit-overflow-scrolling:touch}
#chips::-webkit-scrollbar{display:none}
.chip{flex:none;min-width:44px;height:40px;padding:0 10px;border-radius:10px;border:1px solid var(--line);background:var(--s2);color:var(--txt2);font-size:12.5px;font-weight:600;cursor:pointer;position:relative}
.chip::after{content:'';position:absolute;inset:-4px}
.chip:active{transform:scale(.94);background:var(--s3)}

#diff-row{display:flex;gap:6px}
.diff-btn{flex:1;padding:8px 4px;border-radius:12px;border:1px solid var(--line);background:var(--s2);color:var(--txt2);font-size:12px;font-weight:600;cursor:pointer;text-align:center;transition:transform .12s ease}
.diff-btn small{display:block;font-weight:500;color:var(--txt3);font-size:10px;margin-top:2px}
.diff-btn.active{background:color-mix(in srgb,var(--acc) 18%,var(--s2));border-color:color-mix(in srgb,var(--acc) 55%,transparent);color:var(--txt)}
.diff-btn:active{transform:scale(.96)}
.diff-btn:disabled{opacity:.5;cursor:default}
.diff-btn .diff-detail{display:none;font-weight:500;color:var(--txt3);font-size:10px;margin-top:1px}
.diff-btn.active .diff-detail{display:block}
.diff-btn.active[data-diff="easy"] .diff-detail{color:color-mix(in srgb,var(--wood) 60%,var(--txt))}
.diff-btn.active[data-diff="normal"] .diff-detail{color:color-mix(in srgb,var(--wire) 60%,var(--txt))}
.diff-btn.active[data-diff="hard"] .diff-detail{color:color-mix(in srgb,var(--concrete) 60%,var(--txt))}

#cta{width:100%;padding:16px;border-radius:16px;border:none;font-family:'Fredoka';font-weight:700;font-size:18px;cursor:pointer;color:#1a1200;background:linear-gradient(150deg,#ffce3a,#f4a72c);box-shadow:0 8px 22px rgba(244,167,44,.3);transition:transform .12s ease}
#cta:active{transform:scale(.97)}
#cta:disabled{opacity:.45;cursor:default;box-shadow:none}
#cta.danger{background:linear-gradient(150deg,#f7856f,#f05a48);color:#2a0a05}

#choice-row{display:flex;gap:8px}
#btn-cashout{flex:1.3;padding:16px 8px;border-radius:16px;border:none;font-family:'Fredoka';font-weight:700;font-size:16px;color:#062a12;background:linear-gradient(150deg,#6be18c,#46c56a);cursor:pointer;box-shadow:0 8px 22px rgba(70,197,106,.35);animation:cta-pulse 1.6s ease-in-out infinite}
#btn-continue{flex:1;padding:16px 8px;border-radius:16px;border:1px solid var(--line);font-family:'Fredoka';font-weight:700;font-size:15px;color:var(--txt);background:var(--s2);cursor:pointer}
#btn-cashout:active,#btn-continue:active{transform:scale(.96)}
#crash-row{display:flex;gap:8px;animation:crash-row-in 200ms ease-out}
#btn-crash-skip{flex:1;padding:16px 8px;border-radius:16px;border:1px solid var(--line);font-family:'Fredoka';font-weight:700;font-size:15px;color:var(--txt);background:var(--s2);cursor:pointer}
#btn-crash-skip:active{transform:scale(.96)}
#btn-crash-skip:disabled{opacity:.4;cursor:default}
@keyframes crash-row-in{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}
.reduced-motion #crash-row{animation:none}
@keyframes cta-pulse{0%,100%{transform:scale(1);box-shadow:0 8px 22px rgba(70,197,106,.35)}50%{transform:scale(1.02);box-shadow:0 10px 30px rgba(70,197,106,.55)}}
.reduced-motion #btn-cashout{animation:none}

#cta-hint{font-size:11px;color:var(--txt3);text-align:center;padding:0;margin:0;min-height:0}
#cta-hint:empty{display:none}
/* Survival-odds hint, shown over the scene during CHOICE. */
#scene-hint{display:none;position:absolute;left:50%;top:max(30%,116px);transform:translateX(-50%);z-index:4;pointer-events:none;background:rgba(15,13,9,.62);border:1px solid var(--line);border-radius:14px;backdrop-filter:blur(4px);padding:8px 16px;font-family:'Fredoka',sans-serif;font-weight:600;font-size:clamp(14px,4.5cqw,19px);color:var(--txt);text-align:center;white-space:nowrap;max-width:92%}
#scene-hint.show{display:block;animation:scene-hint-pop 220ms ease-out}
#scene-hint b{color:var(--acc);font-weight:700}
@keyframes scene-hint-pop{from{opacity:0;transform:translateX(-50%) scale(.9)}to{opacity:1;transform:translateX(-50%) scale(1)}}
.reduced-motion #scene-hint.show{animation:none}

#min-bet-note{font-family:'Fredoka';font-size:10.5px;color:var(--txt2);text-align:center;line-height:1.4;letter-spacing:.02em}

/* ===== Daily bonus banner ===== */
#daily-bonus{position:relative;z-index:5;margin:0 14px;padding:14px 16px;border-radius:14px;
  background:linear-gradient(150deg,color-mix(in srgb,var(--acc) 18%,var(--surface)),color-mix(in srgb,var(--ok) 10%,var(--surface)));
  border:1px solid color-mix(in srgb,var(--acc) 40%,transparent);
  box-shadow:0 6px 18px rgba(244,167,44,.15);
  animation:daily-bonus-in 360ms cubic-bezier(.2,1.2,.4,1)}
@keyframes daily-bonus-in{0%{opacity:0;transform:translateY(-8px)}100%{opacity:1;transform:translateY(0)}}
.daily-bonus-title{font-family:'Fredoka';font-weight:700;font-size:15px;color:var(--acc);margin-bottom:4px}
.daily-bonus-sub{font-family:'Fredoka';font-weight:500;font-size:12px;color:var(--txt2);margin-bottom:10px}
#daily-bonus-btn{width:100%;padding:12px;border-radius:12px;border:none;
  font-family:'Fredoka';font-weight:700;font-size:15px;cursor:pointer;
  color:#1a1200;background:linear-gradient(150deg,#ffce3a,#f4a72c);
  box-shadow:0 6px 18px rgba(244,167,44,.25);transition:transform .12s ease}
#daily-bonus-btn:active{transform:scale(.97)}
#daily-bonus-btn:disabled{opacity:.5;cursor:default;box-shadow:none}
#daily-bonus-btn:focus-visible{outline:2px solid var(--acc);outline-offset:2px}
#daily-bonus-countdown-text{color:var(--txt);font-weight:600}

/* ===== Win banner — celebratory overlay on the scene ===== */
#win-banner{display:none;position:absolute;left:50%;top:max(46%,160px);transform:translate(-50%,-50%);z-index:5;pointer-events:none;background:rgba(15,13,9,.82);border:1px solid color-mix(in srgb,var(--real) 55%,transparent);border-radius:18px;box-shadow:0 0 40px rgba(255,206,58,.25);backdrop-filter:blur(4px);padding:14px 22px;text-align:center;max-width:92%}
#win-banner.show{display:block;animation:win-pop 450ms cubic-bezier(.2,1.4,.4,1)}
@keyframes win-pop{0%{opacity:0;transform:translate(-50%,-50%) scale(.5)}70%{opacity:1;transform:translate(-50%,-50%) scale(1.06)}100%{opacity:1;transform:translate(-50%,-50%) scale(1)}}
.reduced-motion #win-banner.show{animation:none}
#win-banner-title{font-family:'Fredoka';font-weight:700;font-size:14px;color:var(--real);text-transform:uppercase;letter-spacing:.08em}
#win-banner-amount{font-family:'Fredoka';font-weight:700;font-size:clamp(30px,11cqw,46px);line-height:1.1;margin:2px 0;color:var(--ok);text-shadow:0 2px 12px rgba(0,0,0,.55),0 0 24px rgba(70,197,106,.35)}
#win-banner-sub{font-size:12.5px;color:var(--txt2)}

/* ===== Crash banner — loss overlay on the scene (heavier, quicker, no bounce) ===== */
#crash-banner{display:none;position:absolute;left:50%;top:max(46%,160px);transform:translate(-50%,-50%);z-index:5;pointer-events:none;background:rgba(15,13,9,.82);border:1px solid color-mix(in srgb,var(--bad) 55%,transparent);border-radius:18px;box-shadow:0 0 34px rgba(240,90,72,.22);backdrop-filter:blur(4px);padding:14px 22px;text-align:center;max-width:92%}
#crash-banner.show{display:block;animation:crash-pop 260ms ease-out}
@keyframes crash-pop{0%{opacity:0;transform:translate(-50%,-58%) scale(1.06);filter:brightness(.7)}100%{opacity:1;transform:translate(-50%,-50%) scale(1);filter:brightness(1)}}
.reduced-motion #crash-banner.show{animation:none}
#crash-banner-title{font-family:'Fredoka';font-weight:700;font-size:14px;color:var(--bad);text-transform:uppercase;letter-spacing:.08em}
#crash-banner-amount{font-family:'Fredoka';font-weight:700;font-size:clamp(30px,11cqw,46px);line-height:1.1;margin:2px 0;color:var(--bad);text-shadow:0 2px 12px rgba(0,0,0,.55),0 0 24px rgba(240,90,72,.35)}
#crash-banner-sub{font-size:12.5px;color:var(--txt2)}

/* ===== Broke banner — persistent "out of chips" overlay (IDLE + balance 0).
   Mirrors #crash-banner geometry/loss chrome, but a soft fade-in (not the heavy
   crash drop) since it's a standing state, not a momentary outcome. Informational
   only — pointer-events:none; the settings gear stays the way to reset. */
#broke-banner{display:none;position:absolute;left:50%;top:max(46%,160px);transform:translate(-50%,-50%);z-index:5;pointer-events:none;background:rgba(15,13,9,.82);border:1px solid color-mix(in srgb,var(--bad) 55%,transparent);border-radius:18px;box-shadow:0 0 34px rgba(240,90,72,.22);backdrop-filter:blur(4px);padding:14px 22px;text-align:center;max-width:92%}
#broke-banner.show{display:block;animation:broke-fade 220ms ease-out}
@keyframes broke-fade{0%{opacity:0;transform:translate(-50%,-52%)}100%{opacity:1;transform:translate(-50%,-50%)}}
.reduced-motion #broke-banner.show{animation:none}
#broke-banner-title{font-family:'Fredoka';font-weight:700;font-size:14px;color:var(--bad);text-transform:uppercase;letter-spacing:.08em}
#broke-banner-sub{font-size:12.5px;color:var(--txt2)}

/* squat scenes (short viewports): center vertically and shrink instead of clipping.
   Must come AFTER both banners' base rules — equal specificity, cascade order decides. */
@container (max-height:280px){
  #win-banner,#crash-banner,#broke-banner{top:50%;padding:10px 16px}
  #win-banner-amount,#crash-banner-amount{font-size:26px}
}

/* one-shot confetti pieces (JS-spawned into #fx-layer) */
.confetti{position:absolute;z-index:5;pointer-events:none;opacity:0;animation:confetti-fall 1100ms ease-in forwards}
@keyframes confetti-fall{0%{opacity:0;transform:translate(0,0) rotate(0)}12%{opacity:1}100%{opacity:0;transform:translate(var(--cx,0),var(--cy,100px)) rotate(540deg)}}
.reduced-motion .confetti{display:none}

/* ===== Win row — Same bet | Continue in the bottom panel ===== */
#win-row{display:flex;gap:8px;animation:crash-row-in 200ms ease-out}
#btn-win-continue{flex:1.3;padding:16px 8px;border-radius:16px;border:none;font-family:'Fredoka';font-weight:700;font-size:16px;color:#1a1200;background:linear-gradient(150deg,#ffce3a,#f4a72c);cursor:pointer;box-shadow:0 8px 22px rgba(244,167,44,.3)}
#btn-win-samebet{flex:1;padding:16px 8px;border-radius:16px;border:1px solid var(--line);font-family:'Fredoka';font-weight:700;font-size:15px;color:var(--txt);background:var(--s2);cursor:pointer}
#btn-win-continue:active,#btn-win-samebet:active{transform:scale(.96)}
#btn-win-continue:disabled{opacity:.45;cursor:default;box-shadow:none;filter:brightness(.85)}
#btn-win-samebet:disabled{opacity:.4;cursor:default}
.reduced-motion #win-row{animation:none}

/* ===== Bonus event toast ===== */
#toast-container{position:fixed;top:12px;left:50%;transform:translateX(-50%);z-index:22;display:flex;flex-direction:column;align-items:center;gap:8px;pointer-events:none;width:min(380px,90vw)}
.toast{pointer-events:auto;max-width:100%;background:rgba(15,13,9,.92);border:1px solid color-mix(in srgb,var(--acc) 45%,transparent);border-radius:14px;padding:12px 18px;box-shadow:0 8px 30px rgba(0,0,0,.5);backdrop-filter:blur(8px);display:flex;align-items:flex-start;gap:12px;animation:toast-enter 340ms cubic-bezier(.2,1.1,.4,1) forwards}
.toast.toast-exit{animation:toast-exit 280ms ease-in forwards}
@keyframes toast-enter{0%{opacity:0;transform:translateY(-16px) scale(.94)}100%{opacity:1;transform:translateY(0) scale(1)}}
@keyframes toast-exit{0%{opacity:1;transform:translateY(0) scale(1)}100%{opacity:0;transform:translateY(-12px) scale(.96)}}
.reduced-motion .toast,.reduced-motion .toast.toast-exit{animation:none;transition:opacity 180ms ease}
.toast-icon{font-size:22px;line-height:1;flex:none;margin-top:2px}
.toast-body{flex:1;min-width:0}
.toast-title{font-family:'Fredoka';font-weight:700;font-size:14px;color:var(--acc);line-height:1.2;margin-bottom:3px}
.toast-message{font-family:'Space Grotesk',system-ui,sans-serif;font-weight:500;font-size:12px;color:var(--txt2);line-height:1.35;word-break:break-word}

/* ===== Full-history modal — slides from right ===== */
#history-modal-backdrop{position:fixed;inset:0;background:rgba(5,4,2,.6);opacity:0;pointer-events:none;transition:opacity 220ms ease;z-index:27}
#history-modal-backdrop.show{opacity:1;pointer-events:auto}
#history-modal{position:fixed;top:0;right:0;bottom:0;width:min(420px,92vw);background:var(--surface);border-left:1px solid var(--line);transform:translateX(100%);transition:transform 280ms cubic-bezier(.2,.8,.3,1);z-index:28;display:flex;flex-direction:column;overflow:hidden;box-shadow:-10px 0 40px rgba(0,0,0,.4)}
#history-modal.show{transform:translateX(0)}
#history-modal-header{display:flex;align-items:center;justify-content:space-between;padding:18px 20px 12px;flex:none;border-bottom:1px solid var(--line)}
#history-modal-header h2{font-family:'Fredoka';font-size:17px;margin:0;color:var(--txt)}
#history-modal-close{width:34px;height:34px;min-width:34px;border-radius:10px;border:1px solid var(--line);background:var(--s2);color:var(--txt2);cursor:pointer;font-size:16px;display:grid;place-items:center;position:relative}
#history-modal-close::after{content:'';position:absolute;inset:-6px}
#history-modal-close:hover{background:var(--s3);color:var(--txt)}
#history-modal-close:active{transform:scale(.92)}
#history-modal-close:focus-visible{box-shadow:0 0 0 2px var(--acc)}

/* Two-panel track — slides horizontally for list↔detail */
.hist-track{flex:1;overflow:hidden;display:flex;width:200%;transition:transform 320ms cubic-bezier(.22,.61,.36,1);will-change:transform}
.hist-track.show-detail{transform:translateX(-50%)}
.hist-panel{width:50%;overflow-y:auto;padding:16px 20px 18px;display:flex;flex-direction:column;gap:6px;touch-action:pan-y;-webkit-overflow-scrolling:touch;overscroll-behavior:contain}
.hist-panel-detail{padding:16px 20px 18px}

/* Pagination footer */
.hist-pager{display:flex;align-items:center;justify-content:center;gap:12px;padding:10px 0 4px;flex:none}
.hist-pager button{padding:5px 12px;border-radius:8px;border:1px solid var(--line);background:var(--s2);color:var(--txt2);font-family:'Fredoka';font-weight:600;font-size:11px;cursor:pointer}
.hist-pager button:hover{background:var(--s3);color:var(--txt)}
.hist-pager button:disabled{opacity:.35;cursor:default}
.hist-page-num{font-family:'Fredoka';font-weight:600;font-size:12px;color:var(--txt3)}

/* History list (inside panel 1) */
#history-modal-list{flex:1;overflow-y:auto;display:flex;flex-direction:column;gap:6px}
#history-modal-list:empty::after{content:'No rounds yet';display:block;text-align:center;padding:28px 0;font-family:'Fredoka';font-weight:500;font-size:14px;color:var(--txt3)}
.hrow{display:flex;align-items:center;gap:10px;padding:10px 12px;border-radius:10px;background:var(--bg);border-left:4px solid transparent;font-size:13px}
.hrow.win{border-left-color:var(--ok)}
.hrow.loss{border-left-color:var(--bad)}
.hrow-diff{flex:none;min-width:56px;font-family:'Fredoka';font-weight:600;font-size:11.5px;text-transform:capitalize;color:var(--txt2)}
.hrow-mult{flex:1;font-family:'Fredoka';font-weight:700;font-size:14px;white-space:nowrap}
.hrow-mult.win-text{color:var(--ok)}
.hrow-mult.loss-text{color:var(--bad)}
.hrow-steps{flex:none;font-size:11.5px;color:var(--txt3);white-space:nowrap}
.hrow-bet{flex:none;font-family:'Fredoka';font-weight:600;font-size:13px;color:var(--txt);text-align:right;min-width:52px;white-space:nowrap}

/* Per-round detail panel */
.hist-back-btn{width:fit-content;padding:6px 14px;margin-bottom:12px;border-radius:8px;border:1px solid var(--line);background:var(--s2);color:var(--txt2);font-family:'Fredoka';font-weight:600;font-size:12px;cursor:pointer}
.hist-back-btn:hover{background:var(--s3);color:var(--txt)}
.hist-detail-banner{text-align:center;padding:16px;border-radius:14px;margin-bottom:14px}
.hist-detail-banner.win{background:color-mix(in srgb,var(--ok) 12%,var(--bg));border:1px solid color-mix(in srgb,var(--ok) 30%,transparent)}
.hist-detail-banner.loss{background:color-mix(in srgb,var(--bad) 12%,var(--bg));border:1px solid color-mix(in srgb,var(--bad) 30%,transparent)}
.hist-detail-banner .hd-outcome{font-family:'Fredoka';font-weight:700;font-size:11px;text-transform:uppercase;letter-spacing:.06em;color:var(--txt3);margin-bottom:4px}
.hist-detail-banner.win .hd-outcome{color:var(--ok)}
.hist-detail-banner.loss .hd-outcome{color:var(--bad)}
.hist-detail-banner .hd-mult{font-family:'Fredoka';font-weight:700;font-size:42px;line-height:1.1}
.hist-detail-banner.win .hd-mult{color:var(--ok)}
.hist-detail-banner.loss .hd-mult{color:var(--bad)}
.hist-detail-rows{display:flex;flex-direction:column;gap:8px}
.hd-row{display:flex;justify-content:space-between;align-items:center;padding:8px 10px;border-radius:8px;background:var(--bg);font-size:13px}
.hd-row-label{color:var(--txt3);font-size:12px}
.hd-row-value{font-family:'Fredoka';font-weight:600;color:var(--txt);text-align:right}
.hd-row-value.win{color:var(--ok)}
.hd-row-value.loss{color:var(--bad)}
.hist-detail-fairness{margin-top:14px;padding:12px;border-radius:10px;background:var(--bg);border:1px solid var(--line);font-size:11px;color:var(--txt3);line-height:1.5}
.hist-detail-fairness .hd-fair-title{font-family:'Fredoka';font-weight:600;font-size:12px;color:var(--txt2);margin-bottom:6px}

/* ===== Settings drawer ===== */
#drawer-backdrop{position:fixed;inset:0;background:rgba(5,4,2,.6);opacity:0;pointer-events:none;transition:opacity 220ms ease;z-index:25}
#drawer-backdrop.show{opacity:1;pointer-events:auto}
#drawer{position:fixed;top:0;right:0;bottom:0;width:min(340px,86vw);background:var(--surface);border-left:1px solid var(--line);transform:translateX(100%);transition:transform 260ms cubic-bezier(.2,.8,.3,1);z-index:26;padding:calc(18px + var(--safe-t)) 18px calc(18px + var(--safe-b));overflow-y:auto;touch-action:pan-y;-webkit-overflow-scrolling:touch;overscroll-behavior:contain}
#drawer.show{transform:translateX(0)}
#drawer h2{font-family:'Fredoka';font-size:18px;margin:0 0 16px}
.drawer-row{display:flex;align-items:center;justify-content:space-between;padding:12px 0;border-bottom:1px solid var(--line)}
.drawer-row-label{font-size:13.5px}
.drawer-row-sub{font-size:11px;color:var(--txt3);margin-top:2px}
.switch{width:44px;height:26px;border-radius:20px;background:var(--s3);border:1px solid var(--line);position:relative;cursor:pointer;flex:none}
/* hit-pad uses ::before — ::after is the switch knob */
.switch::before{content:'';position:absolute;inset:-8px}
.switch::after{content:'';position:absolute;top:2px;left:2px;width:20px;height:20px;border-radius:50%;background:var(--txt2);transition:transform .18s ease,background .18s ease}
.switch.on{background:color-mix(in srgb,var(--ok) 45%,var(--s3))}
.switch.on::after{transform:translateX(18px);background:var(--ok)}
#drawer-reset{width:100%;margin-top:16px;padding:12px;border-radius:12px;border:1px solid color-mix(in srgb,var(--bad) 45%,transparent);background:color-mix(in srgb,var(--bad) 12%,transparent);color:var(--bad);font-weight:600;font-size:13px;cursor:pointer}
#drawer-info{margin-top:18px;font-size:11.5px;color:var(--txt3);line-height:1.5}
#drawer-close{position:absolute;top:calc(14px + var(--safe-t));right:14px;width:34px;height:34px;border-radius:10px;border:1px solid var(--line);background:var(--s2);color:var(--txt2);cursor:pointer;display:grid;place-items:center}
#drawer-close::after{content:'';position:absolute;inset:-6px}

/* ===== Fairness panel (in settings drawer) ===== */
#fairness-panel{margin-top:16px;padding-top:16px;border-top:1px solid var(--line)}
#fairness-panel h3{font-family:'Fredoka';font-size:15px;margin:0 0 12px;color:var(--txt)}
.fairness-msg{font-size:12px;color:var(--txt3);line-height:1.5;padding:8px 0}
.fairness-row{display:flex;justify-content:space-between;align-items:center;padding:5px 0;font-size:12px;color:var(--txt2)}
.fairness-row span:first-child{color:var(--txt3);margin-right:10px}
.fairness-mono{font-family:monospace;font-size:10.5px;word-break:break-all;text-align:right;max-width:55%}
#fairness-verify-btn{width:100%;margin:12px 0 8px;padding:10px;border-radius:10px;border:1px solid var(--line);background:var(--s2);color:var(--txt);font-family:'Fredoka';font-weight:600;font-size:13px;cursor:pointer}
#fairness-verify-btn:active{transform:scale(.96)}
#fairness-verify-btn:disabled{opacity:.45;cursor:default}
#fairness-verify-result{margin-top:8px;padding:8px;border-radius:8px;background:var(--bg);border:1px solid var(--line)}
.fairness-error-text{color:var(--bad)}

/* ===== Achievements panel (in settings drawer) ===== */
#achievements-panel{margin-top:16px;padding-top:16px;border-top:1px solid var(--line)}
#achievements-panel h3{font-family:'Fredoka';font-size:15px;margin:0 0 12px;color:var(--txt)}
.ach-msg{font-size:12px;color:var(--txt3);line-height:1.5;padding:8px 0}
.ach-error{color:var(--bad)}
#ach-list{display:flex;flex-direction:column;gap:8px}
.ach-card{display:flex;flex-direction:column;gap:6px;padding:10px 12px;border-radius:10px;background:var(--bg);border:1px solid var(--line)}
.ach-card.locked{opacity:.55}
.ach-card-header{display:flex;align-items:center;gap:8px}
.ach-icon{font-size:20px;line-height:1;flex:none}
.ach-name{font-family:'Fredoka';font-weight:600;font-size:13px;color:var(--txt)}
.ach-earned-badge{flex:none;font-size:9.5px;font-weight:600;padding:2px 7px;border-radius:20px;white-space:nowrap;margin-left:auto}
.ach-earned-badge.unlocked{color:var(--ok);border:1px solid color-mix(in srgb,var(--ok) 40%,transparent);background:color-mix(in srgb,var(--ok) 12%,transparent)}
.ach-earned-badge.locked{color:var(--txt3);border:1px solid var(--line);background:transparent}
.ach-desc{font-size:11px;color:var(--txt3);line-height:1.4}
.ach-progress{display:flex;align-items:center;gap:7px}
.ach-progress-bar{flex:1;height:5px;border-radius:5px;background:var(--s3);overflow:hidden}
.ach-progress-fill{height:100%;border-radius:5px;background:var(--acc);transition:width .4s ease}
.ach-progress-fill.complete{background:var(--ok)}
.ach-progress-text{font-size:10px;color:var(--txt3);white-space:nowrap;min-width:38px;text-align:right}
.ach-tier-dots{display:flex;gap:5px}
.ach-tier-dot{width:8px;height:8px;border-radius:50%;background:var(--s3)}
.ach-tier-dot.on{background:var(--acc)}
.ach-tier-dot.complete{background:var(--ok)}

/* ===== Leaderboard panel (in settings drawer) ===== */
#leaderboard-panel{margin-top:16px;padding-top:16px;border-top:1px solid var(--line)}
#leaderboard-panel h3{font-family:'Fredoka';font-size:15px;margin:0 0 12px;color:var(--txt)}
.lb-msg{font-size:12px;color:var(--txt3);line-height:1.5;padding:8px 0}
.lb-error{color:var(--bad)}
.lb-tab-bar{display:flex;gap:6px;margin-bottom:12px}
.lb-tab{flex:1;padding:7px 10px;border-radius:10px;border:1px solid var(--line);background:var(--s2);color:var(--txt2);font-size:12px;font-weight:600;cursor:pointer;text-align:center;transition:transform .12s ease,background .18s ease;font-family:inherit}
.lb-tab:active{transform:scale(.96)}
.lb-tab.active{background:color-mix(in srgb,var(--acc) 18%,var(--s2));border-color:color-mix(in srgb,var(--acc) 55%,transparent);color:var(--txt)}
#lb-list{display:flex;flex-direction:column;gap:4px}
.lb-row{display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:8px;background:var(--bg);border:1px solid var(--line)}
.lb-rank{font-family:'Fredoka';font-weight:700;font-size:14px;color:var(--txt);min-width:28px;text-align:center}
.lb-rank:empty{display:none}
.lb-diff{flex:none;font-size:10px;font-weight:600;padding:2px 7px;border-radius:20px;white-space:nowrap;text-transform:capitalize}
.lb-diff-easy{color:var(--wood);border:1px solid color-mix(in srgb,var(--wood) 40%,transparent);background:color-mix(in srgb,var(--wood) 12%,transparent)}
.lb-diff-normal{color:var(--wire);border:1px solid color-mix(in srgb,var(--wire) 40%,transparent);background:color-mix(in srgb,var(--wire) 12%,transparent)}
.lb-diff-hard{color:var(--concrete);border:1px solid color-mix(in srgb,var(--concrete) 40%,transparent);background:color-mix(in srgb,var(--concrete) 12%,transparent)}
.lb-value{flex:1;font-size:12.5px;font-weight:600;color:var(--txt);text-align:right;font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1}
.lb-time{flex:none;font-size:10px;color:var(--txt3);min-width:42px;text-align:right}

/* ===== Focus-visible accessibility rings ===== */
/* controls with existing box-shadow styling → use outline to avoid clobbering */
#cta:focus-visible{outline:2px solid var(--acc);outline-offset:2px}
#btn-cashout:focus-visible{outline:2px solid var(--acc);outline-offset:2px}

/* controls without existing box-shadow → box-shadow ring inherits the element's border-radius */
#btn-continue:focus-visible{box-shadow:0 0 0 2px var(--acc)}
#btn-crash-skip:focus-visible{box-shadow:0 0 0 2px var(--acc)}
#btn-win-continue:focus-visible{box-shadow:0 0 0 2px var(--acc)}
#btn-win-samebet:focus-visible{box-shadow:0 0 0 2px var(--acc)}
#bet-dec:focus-visible,#bet-inc:focus-visible{box-shadow:0 0 0 2px var(--acc);border-radius:6px;outline:none}
.chip:focus-visible{box-shadow:0 0 0 2px var(--acc)}
.diff-btn:focus-visible{box-shadow:0 0 0 2px var(--acc)}
#settings-btn:focus-visible{box-shadow:0 0 0 2px var(--acc)}
#drawer-reset:focus-visible,#drawer-close:focus-visible{box-shadow:0 0 0 2px var(--acc)}
.switch:focus-visible{box-shadow:0 0 0 2px var(--acc);border-radius:20px}

.sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0)}

/* page-hidden: pause all ambient animations + drop will-change hints when tab is hidden */
.page-hidden .cloud-slot img{animation-play-state:paused}
.page-hidden #world{will-change:auto}
.page-hidden #bg-far{will-change:auto}
.page-hidden #clouds{will-change:auto}
.page-hidden #grass-track{will-change:auto}

/* ===== Mobile / lite-fx (pointer:coarse or ≤640px) =====
   Strip GPU-heavy filters that hitch dashes on phones. Impact juice still
   runs via transform/opacity (burst, lite shatter, reduced sparks). */
html.lite-fx #scene.risk-2,
html.lite-fx #scene.risk-3{filter:none}
html.lite-fx .bg-obj img,
html.lite-fx .cloud-slot img,
html.lite-fx #scene.loc-forest .bg-obj img,
html.lite-fx #scene.loc-forest .cloud-slot img,
html.lite-fx #scene.loc-city .bg-obj img,
html.lite-fx #scene.loc-city .cloud-slot img{filter:none}
html.lite-fx #ram svg,html.lite-fx #ram img,html.lite-fx #ram div,
html.lite-fx .world-item svg,html.lite-fx .world-item img,
html.lite-fx #sheep img,html.lite-fx #sheep svg{filter:none}
/* Ambient cloud drift competes with dash parallax — freeze on phones. */
html.lite-fx .cloud-slot img{animation:none}
html.lite-fx .spark{display:none}
/* backdrop-filter over the animated scene re-blurs every frame — the single
   most expensive effect on weak phone GPUs. Swap for more opaque fills. */
html.lite-fx #mult-display,html.lite-fx #tension-meter,html.lite-fx #scene-hint,
html.lite-fx #win-banner,html.lite-fx #crash-banner,html.lite-fx #broke-banner,
html.lite-fx .toast{backdrop-filter:none;-webkit-backdrop-filter:none}
html.lite-fx #mult-display,html.lite-fx #tension-meter{background:rgba(15,13,9,.8)}
html.lite-fx #scene-hint{background:rgba(15,13,9,.85)}
html.lite-fx #win-banner,html.lite-fx #crash-banner,html.lite-fx #broke-banner{background:rgba(15,13,9,.92)}
/* Warp / soft-reset animate blur() on seven full-scene layers — way too heavy
   for weak GPUs. Lite swaps in opacity-only variants (same timing/shape). */
html.lite-fx #scene.warping #sky,html.lite-fx #scene.warping #dusk,html.lite-fx #scene.warping #clouds,
html.lite-fx #scene.warping #bg-far,html.lite-fx #scene.warping #grass,html.lite-fx #scene.warping #world,
html.lite-fx #scene.warping #ram{animation-name:warp-bloom-lite}
@keyframes warp-bloom-lite{
  0%{opacity:1}
  40%{opacity:.5}
  46%{opacity:.35}
  62%{opacity:.75}
  100%{opacity:1}
}
html.lite-fx #scene.soft-reset #sky,html.lite-fx #scene.soft-reset #dusk,html.lite-fx #scene.soft-reset #clouds,
html.lite-fx #scene.soft-reset #bg-far,html.lite-fx #scene.soft-reset #grass,html.lite-fx #scene.soft-reset #world,
html.lite-fx #scene.soft-reset #ram{animation-name:soft-dip-lite}
@keyframes soft-dip-lite{
  0%{opacity:1}
  50%{opacity:.82}
  100%{opacity:1}
}
html.lite-fx #world,html.lite-fx #bg-far,html.lite-fx #clouds,html.lite-fx #grass-track{
  transition-duration:380ms}
html.lite-fx #ram.lunge{animation-duration:380ms}

/* ===== How to Play modal ===== */
/* Full-screen overlay: z-index 60 sits above settings drawer (26/25), header (5),
 *  history modal (28/27), and all scene/panel chrome. */
@keyframes fadeIn{from{opacity:0}to{opacity:1}}
#how-to-modal{display:none;position:fixed;inset:0;z-index:60;align-items:center;justify-content:center;padding:18px;background:rgba(8,5,12,.88);touch-action:none}
#how-to-modal.show{display:flex;animation:fadeIn .22s ease-out}
#how-to-card{width:100%;max-width:370px;max-height:min(92dvh,640px);overflow-y:auto;touch-action:pan-y;-webkit-overflow-scrolling:touch;overscroll-behavior:contain;background:var(--surface);border:2px solid color-mix(in srgb,var(--acc) 42%,transparent);border-radius:20px;padding:22px;box-shadow:0 20px 60px rgba(0,0,0,.55),0 0 40px rgba(244,167,44,.08)}
#how-to-title{text-align:center;font-family:'Fredoka';font-weight:700;font-size:26px;color:var(--acc);letter-spacing:.03em;text-shadow:0 2px 0 rgba(100,60,10,.4)}
#how-to-sub{text-align:center;font-family:'Fredoka';font-weight:500;font-size:12.5px;color:var(--txt2);margin:4px 0 18px;line-height:1.45}
#how-to-rules{display:flex;flex-direction:column;gap:12px}
.ht-rule{display:flex;gap:10px;align-items:flex-start}
.ht-icon{flex:none;font-size:20px;width:26px;text-align:center;line-height:1.3}
.ht-text{font-family:'Space Grotesk',system-ui,sans-serif;font-weight:500;font-size:12.5px;color:var(--txt);line-height:1.5}
.ht-text b{color:var(--acc)}
#how-to-footer{margin-top:16px;text-align:center;font-family:'Fredoka';font-weight:500;font-size:10px;color:var(--txt3);letter-spacing:.03em}
#how-to-btn{margin-top:14px;width:100%;padding:14px;border-radius:14px;border:none;font-family:'Fredoka';font-weight:700;font-size:17px;cursor:pointer;color:#1a1200;background:linear-gradient(150deg,#ffce3a,#f4a72c);box-shadow:0 8px 22px rgba(244,167,44,.3);transition:transform .12s ease}
#how-to-btn:active{transform:scale(.96)}
#how-to-btn:focus-visible{outline:2px solid var(--acc);outline-offset:2px}
.reduced-motion #how-to-modal.show{animation:none}

@media (min-width:720px){
  #app{max-width:520px;margin:0 auto;box-shadow:0 0 60px rgba(0,0,0,.5)}
  /* pin right-slide panels to the centered app column's right edge; backdrops stay full-window */
  #history-modal,#drawer{right:max(0px,calc((100vw - 520px) / 2))}
  /* hidden state must clear the column gap + 40px shadow bleed, not just the panel's own width */
  #history-modal,#drawer{transform:translateX(calc(100% + max(0px,(100vw - 520px) / 2) + 40px))}
}

/* ===== Desktop hover feedback (pointer devices only) ===== */
@media (hover:hover){
  .chip:hover:not(:disabled),.diff-btn:hover:not(:disabled),.step-btn:hover:not(:disabled),#btn-continue:hover:not(:disabled),#btn-crash-skip:hover:not(:disabled),#btn-win-samebet:hover:not(:disabled),#settings-btn:hover{background:var(--s3);color:var(--txt)}
  .diff-btn.active:hover:not(:disabled){background:color-mix(in srgb,var(--acc) 18%,var(--s2))}
  #cta:hover:not(:disabled),#daily-bonus-btn:hover:not(:disabled),#btn-win-continue:hover:not(:disabled){filter:brightness(1.06)}
}

/* Reduced motion is opt-in via Settings (.reduced-motion on <html>), not OS media. */
.reduced-motion *{animation-duration:.001ms !important;animation-iteration-count:1 !important;transition-duration:.001ms !important}

/* ===== Volume sliders ===== */
.vol-slider{-webkit-appearance:none;appearance:none;width:100%;height:6px;border-radius:3px;background:var(--s3);outline:none;cursor:pointer}
.vol-slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:18px;height:18px;border-radius:50%;background:var(--acc);border:2px solid var(--bg);cursor:pointer;box-shadow:0 1px 4px rgba(0,0,0,.3)}
.vol-slider::-moz-range-thumb{width:18px;height:18px;border-radius:50%;background:var(--acc);border:2px solid var(--bg);cursor:pointer;box-shadow:0 1px 4px rgba(0,0,0,.3)}
