/* Moonlit v5: the motion of the game while you play -- multiplier, lane tags,
   buttons, bet stepper, menu, dialogs, entrance. Paired with shared/hud-fx.js.
   Loaded after club.css and result-fx.css.

   The owner asked for "that level of animations" of his Crocodile Temple --
   every press answers at once, every event is a primary motion with one or two
   follow-throughs a few tens of ms behind it, tension builds in steps you can
   see, and between rounds one small thing happens at a time -- and then, first
   of all, "make sure betting panel buttons are animated". In Moonlit's own
   look: no new colour on the labels, no new panels, and quiet glows.

   THE RULES THIS FILE KEEPS, all of them from the owner's corrections:
   - Only transform, translate, scale and opacity move. Never a filter, a
     shadow, a layout property or a custom property per frame; glows are
     painted once on their own element and faded.
   - The deck and the road never move: app.js watches the bar's top edge every
     frame (a transform moves it) and re-sizes the road. The deck only fades on
     load; presses, lifts and pops are on the controls inside it, about their
     own centres, in their own cells.
   - Everything that moves is inside `prefers-reduced-motion: no-preference`;
     with motion reduced the controls keep club.css's own small press. Every
     decoration is pointer-events:none, and a press acts on the click exactly
     as before: the motion only follows it.
   - club.css kills the animations of `.deck`, `.deck>*`, `.lane-tag`, the
     number, `.drive-controls` and the two drive buttons with !important (to
     keep glows from repainting). Where a moment here must animate one of those
     it restates !important, at higher specificity, inside the motion query --
     so reduced motion still stops it. */

/* hud-fx.js decorates the page only when this is in force. The two curves
   every press uses: down, and the spring back (y1 1.9 overshoots by about a
   fifth of the way it travels, so a .9 key comes back through ~1.02). */
:root{--hud-css:1;--hud-spring:cubic-bezier(.3,1.9,.6,1);--hud-down:cubic-bezier(.3,.7,.4,1)}

/* 1. PRESSES IN THE BET BAR ----------------------------------------------------
   The owner, twice: "make sure betting panel buttons are animated", then
   "better animation for betting panel". Every button in the bar -- − and +,
   ½ and 2×, BET, CASH OUT, the AUTO CASH OUT − and +, AUTO PLAY -- squashes
   hard the moment it is pressed, a light flashes inside it
   and a ring spreads from the point that was pressed, then it springs back
   through an overshoot.

   hud-fx.js plays it (hud-down, then hud-up) rather than :active, because a
   phone tap can be over in 40ms, before a squash has been seen: the squash
   holds at least 90ms and the spring back always plays in full. With a mouse
   each control also lifts 2px under the pointer. `scale` and `translate` are
   properties of their own, so they compose with any `transform` a control
   carries and never touch its layout: the bar is the same box in every frame.
   Without the script, club.css's own small :active press is left as it was. */
.deck{--hud-lift:-2px}
/* How deep each kind of control squashes, and how far it springs past rest:
   small keys the most; the long toggle and the two drive buttons more in
   height than in width, so the press reads the same size on a 36px key and on
   a 300px button. */
.deck .bet-stepper>button,.deck .auto-target>button{--hud-sq:.86;--hud-over:1.05}
.deck .auto-toggle{--hud-sq:.96 .86;--hud-over:1.012 1.04}
.deck .play-button,.deck .cash-button{--hud-sq:.93 .88;--hud-over:1.02 1.035}
/* The light and the ring live in one layer per control, under its label:
   the control isolates, the layer is z-index -1, clipped to the control. */
.deck :is(.bet-stepper>button,.auto-target>button,.auto-toggle){position:relative;isolation:isolate}
.hud-tap{position:absolute;inset:0;z-index:-1;border-radius:inherit;overflow:hidden;pointer-events:none}
.hud-tap::before{content:"";position:absolute;inset:0;opacity:0;
  background:radial-gradient(circle at var(--hud-x,50%) var(--hud-y,50%),#ffffff8c,#ffffff2e 42%,#fff0 72%)}
.hud-tap>.hud-tap-ring{position:absolute;left:var(--hud-x,50%);top:var(--hud-y,50%);
  width:var(--hud-d,60px);height:var(--hud-d,60px);translate:-50% -50%;border-radius:50%;
  border:2px solid #ffffffc7;opacity:0;scale:0}

@media (prefers-reduced-motion:no-preference){
  /* The lift, and back down to be pressed. The colour transitions are
     club.css's own, restated because `transition` is one list; the shadow and
     filter ones are dropped (they are not animated). */
  .deck .bet-stepper>button,.deck .auto-target>button{transition:background .14s,translate 160ms ease-out}
  .deck .auto-toggle{transition:background .15s,border-color .15s,color .15s,translate 160ms ease-out}
  .deck .play-button,.deck .cash-button{transition:translate 160ms ease-out}
  /* With the script in charge, club.css's own :active transforms step aside
     so the squash is not applied twice. */
  html.hud-live .deck :is(.bet-stepper>button,.auto-target>button,.auto-toggle,.play-button,.cash-button):not(:disabled):active{
    transform:none;translate:0 0}
  .deck :is(.bet-stepper>button,.auto-target>button,.auto-toggle,.play-button,.cash-button).hud-down{
    animation:hud-down 80ms cubic-bezier(.3,.7,.4,1) forwards!important}
  .deck :is(.bet-stepper>button,.auto-target>button,.auto-toggle,.play-button,.cash-button).hud-up{
    animation:hud-up 340ms cubic-bezier(.25,.8,.35,1)!important}
  .hud-tap.is-on::before{animation:hud-tap-light 360ms linear}
  .hud-tap.is-on>.hud-tap-ring{animation:hud-tap-ring 420ms cubic-bezier(.2,.65,.3,1)}
}
@media (prefers-reduced-motion:no-preference) and (hover:hover) and (pointer:fine){
  .deck :is(.bet-stepper>button,.auto-target>button,.auto-toggle,.play-button,.cash-button):not(:disabled):hover{
    translate:0 var(--hud-lift)}
}

/* 2. WHAT IS THERE WITH MOTION OR WITHOUT IT ------------------------------ */

/* The decorations hud-fx.js adds: empty, out of the flow, never in the way.
   The glint holds a copy of the number, so it is only ever seen through its
   own animation. */
.hud-glow,.hud-flash,.hud-ring,.hud-glint,.hud-tag-light,.hud-sheen,.hud-fill,.hud-knob-ring,.hud-ghost,
.hud-rays,.hud-sparks,.hud-gold{position:absolute;pointer-events:none}
.hud-glint{opacity:0}

/* The rolls clip at the field's own edges. `.bet-value` and `.auto-value` are
   flex items with min-width:0 already, so clipping them changes no size. */
.deck .bet-value,.deck .auto-value{position:relative;overflow:hidden}
.deck .auto-toggle{position:relative}
/* The ghost of the old amount: laid over the field's box by hud-fx.js, in the
   field's own type (it inherits the well's or the button's font). */
.hud-ghost{display:flex;align-items:center;justify-content:center;white-space:nowrap;font-style:normal;
  font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1}
/* BET's amount rolls in the amount's own face (club.css, THE MONEY ON THE
   BUTTONS), not the button's: laid over the amount's box, one line of its
   height, so the old figures leave from exactly where they stood. */
.play-button>.hud-ghost{display:block;text-align:center;font:900 1.24em/1 var(--title);letter-spacing:.01em}
.auto-value>.hud-ghost{gap:1px}
.hud-ghost b{font:inherit;color:var(--cash-tint)}

/* A disabled stepper key gets no click, so its press falls through to the row,
   where hud-fx.js answers it with the stepper's "no". The row takes the key's
   `manipulation` so a double tap there still cannot zoom the page. */
html.hud-live .deck .bet-stepper>button:disabled,
html.hud-live .deck .auto-target>button:disabled{pointer-events:none}
html.hud-live .deck .bet-stepper,html.hud-live .deck .auto-target{touch-action:manipulation}

/* THE NUMBER'S HEAT. hud-fx.js sets one of five bands on the readout from
   app.js's --heat (2x, 4x, 8x, 16x). The glow behind the number is painted
   once and only its opacity and scale step up; from 4x the digits warm a
   little from white toward amber. The safe lane's countdown colours
   (.is-ticking / .is-draining, higher specificity) still win over the warmth,
   and the crash's red wins over both. */
.readout>.hud-glow,.readout>.hud-flash,.readout>.hud-ring{
  left:50%;top:50%;translate:-50% -50%;border-radius:50%;z-index:-1;opacity:0}
.readout>.hud-glow{width:150%;height:200%;scale:.92;
  background:radial-gradient(closest-side,#ffd58a5c,#ffc46a24 55%,#ffc46a00)}
.readout[data-hud-heat="1"]>.hud-glow{opacity:.3;scale:.96}
.readout[data-hud-heat="2"]>.hud-glow{opacity:.5;scale:1}
.readout[data-hud-heat="3"]>.hud-glow{opacity:.7;scale:1.06}
.readout[data-hud-heat="4"]>.hud-glow{opacity:.9;scale:1.12}
.road:is(.is-ticking,.is-draining) .readout>.hud-glow{opacity:.15}
.readout[data-hud-heat="2"]>b{color:#f8f5ea}
.readout[data-hud-heat="3"]>b{color:#faf1de}
.readout[data-hud-heat="4"]>b{color:#fcecd0}
.readout>.hud-flash{width:130%;height:170%;
  background:radial-gradient(closest-side,#fff3d2a8,#ffe3a03d 50%,#ffe3a000)}
/* A soft ring rather than a border: a thin bright band in a radial, painted
   once, then only scaled and faded. */
.readout>.hud-ring{width:118%;height:150%;
  background:radial-gradient(closest-side,#fff1cc00 85%,#fff6dcc2 90.5%,#fff1cc00 96%)}
/* A MILESTONE'S BURST, all of it painted once and only moved and faded: from
   8x short, faint rays behind the number (a conic fan, masked to a narrow
   band), a few small sparks in the lane's colour (hud-fx.js aims each one),
   and a gold copy of the number that glints over it. */
.readout>.hud-rays{left:50%;top:50%;width:175%;aspect-ratio:1;translate:-50% -50%;border-radius:50%;z-index:-1;opacity:0;
  background:repeating-conic-gradient(from 6deg,#fff3cfd9 0deg 2.4deg,#fff3cf00 2.4deg 22.5deg);
  -webkit-mask:radial-gradient(closest-side,#0000 34%,#000 43%,#000 52%,#0000 76%);
  mask:radial-gradient(closest-side,#0000 34%,#000 43%,#000 52%,#0000 76%)}
.readout>.hud-sparks{left:50%;top:50%;width:0;height:0;z-index:-1}
.hud-sparks>.hud-spark{position:absolute;left:-5px;top:-1.5px;width:10px;height:3px;border-radius:2px;opacity:0;
  background:linear-gradient(90deg,#fff0,var(--hud-spark,var(--amber)) 40%,#fffdf2);
  box-shadow:0 0 4px var(--hud-spark,var(--amber))}
/* (an <i>, never a <b>: `.readout>b` is the number's own selector, and
   club.css holds every animation on it) */
.readout>.hud-gold{z-index:1;opacity:0;display:block;margin:0;
  font-family:var(--title);font-weight:900;font-style:normal;line-height:.82;letter-spacing:.01em;text-align:center;white-space:nowrap;
  font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1;
  color:#ffd65a;text-shadow:0 0 14px #ffc93d99,0 2px 0 #7a4b0080}
.readout>.hud-gold small{font-size:.78em;letter-spacing:0;vertical-align:.12em;margin-left:.04em}
/* The glint: a copy of the number, bright, seen only through a moving band.
   The band travels right while the copy inside it travels left by the same
   amount, so the copy stays exactly over the number (both are transforms). */
.readout>.hud-glint{z-index:1;opacity:0}
.hud-glint-band{position:absolute;left:0;top:-20%;width:40%;height:140%;overflow:hidden;
  -webkit-mask:linear-gradient(100deg,#0000 8%,#000 42%,#000 58%,#0000 92%);
  mask:linear-gradient(100deg,#0000 8%,#000 42%,#000 58%,#0000 92%)}
.hud-glint-copy{position:absolute;left:0;top:14.2857%;width:250%;height:71.4286%;display:block;
  font-family:var(--title);font-weight:900;font-style:normal;line-height:.82;letter-spacing:.01em;text-align:center;white-space:nowrap;
  font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1;color:#fff;text-shadow:0 0 10px #ffffffa6,0 0 2px #fff}
.hud-glint-copy small{font-size:.78em;letter-spacing:0;vertical-align:.12em;margin-left:.04em}

/* THE LANE TAG'S LIGHT: a lane-coloured wash (::before) that flashes on a
   lane change and on "go", and a white band (::after) for the idle sweep.
   Masked the way the tag's own tint is, so it never draws the tag's box. */
.lane-tag>.hud-tag-light{inset:0;overflow:hidden;
  -webkit-mask:linear-gradient(#000,#0000 90%);mask:linear-gradient(#000,#0000 90%)}
.lane-tags.run-on .lane-tag>.hud-tag-light{
  -webkit-mask:linear-gradient(#0000,#000 34%,#0000 90%);mask:linear-gradient(#0000,#000 34%,#0000 90%)}
.lane-tag.hot{--hud-wash:#ff405257}
.lane-tag.warm{--hud-wash:#ffe6404d}
.lane-tag.safe{--hud-wash:#38ed704d}
.lane-tag>.hud-tag-light::before,.lane-tag>.hud-tag-light::after{content:"";position:absolute;opacity:0}
.lane-tag>.hud-tag-light::before{inset:0;background:var(--hud-wash)}
.lane-tag>.hud-tag-light::after{top:0;bottom:0;left:0;width:56%;transform:translateX(-100%);
  background:linear-gradient(100deg,#fff0,#ffffff52 50%,#fff0)}

/* THE DRIVE BUTTONS' LIGHTS sit under the label: the button isolates, the
   lights are z-index -1, above its fill and below its text. */
.deck .play-button,.deck .cash-button{isolation:isolate}
.drive-controls .hud-sheen{inset:0;z-index:-1;overflow:hidden;border-radius:inherit}
.drive-controls .hud-sheen::before{content:"";position:absolute;top:-10%;bottom:-10%;left:0;width:34%;
  background:linear-gradient(100deg,#fff0,#ffffff7a 50%,#fff0);transform:translateX(-120%) skewX(-18deg);opacity:0}
.drive-controls .play-button>.hud-fill{inset:0;z-index:-1;border-radius:inherit;transform-origin:0 50%;
  transform:scaleX(0);opacity:0;background:linear-gradient(90deg,#fff0,#ffffff38 70%,#ffffff6b)}

/* THE DRIVE BUTTON CHANGES FACE. BET's words leave upward as GETTING READY
   comes in; at the start of a ride a copy of BET -- its green and its words
   -- lies over CASH OUT and fades while CASH OUT's own words flip in, and at
   the end the same the other way. The copies sit where the label sits: the
   button's own flex row, padding and gap, under the real label (z -1 in the
   isolated button), over its colour. */
.drive-controls :is(.hud-face,.hud-label-ghost){position:absolute;inset:0;display:flex;align-items:baseline;justify-content:center;
  flex-wrap:wrap;gap:inherit;padding:inherit;pointer-events:none;font-style:normal;align-content:center}
.drive-controls :is(.hud-face,.hud-label-ghost)>i{font-style:normal}
.drive-controls :is(.hud-face,.hud-label-ghost)>i:last-child{font:900 1.24em/1 var(--title);letter-spacing:.01em;
  font-variant-numeric:tabular-nums}
.drive-controls .hud-face{z-index:-1;border-radius:inherit;opacity:0}
.drive-controls .hud-face.is-bet{background:var(--bet-face);box-shadow:var(--bet-lip);color:var(--drive-ink)}
.drive-controls .hud-face.is-cash{background:var(--cash-face);box-shadow:var(--cash-lip);color:var(--drive-ink)}
.drive-controls .hud-label-ghost{color:inherit}

/* THE WELL'S GLOW when its value changes: painted once, under the digits. */
.deck .bet-value,.deck .auto-value{isolation:isolate}
.hud-well-glow{position:absolute;inset:0;z-index:-1;border-radius:inherit;pointer-events:none;opacity:0;
  background:radial-gradient(70% 90% at 50% 55%,#f2fff766,#e2ffee24 60%,#fff0)}

/* THE RIM'S LIGHT: a ring the shape of the bar's neon rim (club.css's
   masked ::before), holding one soft band that crosses it. The band moves;
   the ring's mask does not, so the light runs along the rim. A child of the
   deck taken out of the deck's grid and out of the touch fold. */
.deck>.hud-rim{position:absolute!important;display:block!important;inset:-2px;padding:2px;border-radius:inherit;
  pointer-events:none;z-index:1;overflow:hidden;opacity:0;
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);-webkit-mask-composite:xor;
  mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);mask-composite:exclude}
.hud-rim-band{position:absolute;top:0;bottom:0;left:0;width:26%;transform:translateX(-100%);
  background:linear-gradient(90deg,#fff0,#fffbe8d9 50%,#fff0)}

/* THE PHONE'S ROW SWAP: the still copy of the row that left, over the cell. */
.deck>.hud-row-ghost{position:absolute!important;margin:0!important;pointer-events:none;z-index:2}

/* THE AUTO KNOB'S RING, placed on the knob by hud-fx.js. */
.deck .auto-toggle>.hud-knob-ring{left:0;top:0;width:var(--hud-knob,22px);height:var(--hud-knob,22px);
  translate:-50% -50%;border-radius:50%;border:1.5px solid var(--cash-tint);opacity:0}

/* THE MENU'S x: the three lines of the burger meet in the middle when the
   menu is open. A state, so it holds with motion off too. */
.deck-extras[open] .burger>i:nth-child(1){transform:translateY(5px) rotate(45deg)}
.deck-extras[open] .burger>i:nth-child(2){opacity:0;transform:scaleX(.2)}
.deck-extras[open] .burger>i:nth-child(3){transform:translateY(-5px) rotate(-45deg)}


/* 3. THE MOTION -------------------------------------------------------------- */

@media (prefers-reduced-motion:no-preference){

  /* 3a. THE ENTRANCE, on the page's shared timeline (ms from the page's
     start): the sky 0-500, the tubes 200-1000 and the car 700-1200 are the
     road's; here the deck's glass fades in 800-1120 and its neon rim lights
     980-1340, its three sections rise one after another 850-1390, the lane
     tags drop in one by one 900-1380, the number rises 1000-1400 and the
     options button slides in 1200-1600. `--hud-shift` (hud-fx.js) moves all
     of it so it counts from the page's start, or from the road's own intro.
     The deck itself only fades: its sections do the rising.

     Before hud-fx.js has run, the HUD is held back, so it never shows at rest
     for a frame and then drops out for its entrance; without the script it
     simply appears at rest at 1.5s. */
  html:not(.hud-fx) :is(.deck,.lane-tags,.readout,.deck-extras>summary){animation:hud-hold 1ms 1.5s backwards!important}
  html.hud-entering .deck{animation:hud-fade-in 320ms ease-out calc(800ms + var(--hud-shift,0ms)) backwards!important}
  html.hud-entering .deck::before{animation:hud-fade-in 360ms ease-out calc(980ms + var(--hud-shift,0ms)) backwards}
  html.hud-entering .deck>*{
    animation:hud-sec-in 420ms cubic-bezier(.2,.8,.3,1) calc(850ms + var(--i,0) * 60ms + var(--hud-shift,0ms)) backwards!important}
  html.hud-entering .lane-tags .lane-tag{
    animation:hud-tag-in 300ms cubic-bezier(.2,.8,.3,1.25) calc(900ms + var(--n,0) * 90ms + var(--hud-shift,0ms)) backwards!important}
  html.hud-entering .readout{animation:hud-mult-in 400ms cubic-bezier(.2,.8,.3,1) calc(1000ms + var(--hud-shift,0ms)) backwards}
  html.hud-entering .deck-extras>summary{
    animation:hud-burger-in 400ms cubic-bezier(.2,.8,.3,1) calc(1200ms + var(--hud-shift,0ms)) backwards}

  /* 3b. PRESSES BEYOND THE BAR, on section 1's spring. A lane tag is skewed
     about its top edge, so it presses about its middle by also moving down
     half of what the scale takes off its height. */
  .lane-tags .lane-tag{transition:opacity .15s,scale 180ms var(--hud-spring),translate 180ms var(--hud-spring)}
  .lane-tags .lane-tag:not(:disabled):active{scale:.94;translate:0 3%;
    transition:opacity .15s,scale 70ms var(--hud-down),translate 70ms var(--hud-down)}
  .deck-extras>summary{transition:background .16s,scale 170ms var(--hud-spring)}
  .deck-extras>summary:active{scale:.88;transition:background .16s,scale 70ms var(--hud-down)}
  dialog .play-button,.dialog-close{transition:scale 170ms var(--hud-spring)}
  dialog .play-button:not(:disabled):active{transform:none;scale:.97 .93;transition:scale 70ms var(--hud-down)}
  .dialog-close:active{scale:.86;transition:scale 70ms var(--hud-down)}

  /* 3c. THE BET. A new amount rolls in 170ms -- from below when it rises,
     from above when it falls -- while a ghost of the old one rolls out the
     other way. A refused press (a disabled key) shakes the stepper sideways:
     "no". */
  .hud-in-up{animation:hud-in-up 170ms cubic-bezier(.2,.75,.25,1) both}
  .hud-in-down{animation:hud-in-down 170ms cubic-bezier(.2,.75,.25,1) both}
  .hud-out-up{animation:hud-out-up 150ms cubic-bezier(.4,0,.7,.4) both}
  .hud-out-down{animation:hud-out-down 150ms cubic-bezier(.4,0,.7,.4) both}
  .deck .hud-no{animation:hud-no 300ms cubic-bezier(.3,.6,.4,1)}

  /* 3d. THE MULTIPLIER. At `launching` it rises into place as the 0.00 ->
     1.00 count starts; at `playing` it stamps once. Each milestone -- every
     doubling, 2x, 4x, 8x ... -- stamps it (1 -> 1.14 -> .98 -> 1, wider than
     tall at the peak), a ring spreads from behind it and the glow flashes --
     see the burst below. Between the stamps it is still: it no longer
     breathes while a round plays (the owner, 2026-09-26: "too much animation
     on multiplier ... should be on 2x 4x and so on otherwise too fast"). The
     readout's own transform is its centring, so its keyframes carry
     translateX(-50%) throughout. */
  html.hud-entering body[data-phase=launching] .readout,
  body[data-phase=launching] .readout{animation:hud-mult-rise 440ms cubic-bezier(.2,.8,.3,1) both}
  body[data-phase=playing] .readout.hud-stamp-go{animation:hud-stamp-go 280ms cubic-bezier(.3,.7,.4,1)}
  body[data-phase=playing] .readout.hud-stamp-1{animation:hud-stamp-1 300ms cubic-bezier(.25,.7,.35,1)}
  body[data-phase=playing] .readout.hud-stamp-2{animation:hud-stamp-2 320ms cubic-bezier(.25,.7,.35,1)}
  body[data-phase=playing] .readout.hud-stamp-3{animation:hud-stamp-3 340ms cubic-bezier(.25,.7,.35,1)}
  .readout>.hud-glow{transition:opacity .7s ease-out,scale .7s cubic-bezier(.2,.8,.3,1)}
  .readout>.hud-flash.is-on{animation:hud-flash 400ms ease-out}
  /* The stamp takes 300-340ms. One thin ring, and from 16x a second 60ms
     behind it; from 8x short, faint rays; the gold glint is gone by 220ms;
     the whole moment is over by 450ms, and the number reads throughout. */
  .readout>.hud-ring.is-t1{animation:hud-ring-1 400ms cubic-bezier(.15,.65,.3,1)}
  .readout>.hud-ring.is-t2{animation:hud-ring-2 420ms cubic-bezier(.15,.65,.3,1)}
  .readout>.hud-ring.is-t3{animation:hud-ring-3 380ms cubic-bezier(.15,.65,.3,1)}
  .readout>.hud-ring-late.is-t3{animation-delay:60ms;animation-fill-mode:backwards}
  .readout>.hud-rays.is-t2{animation:hud-rays-2 360ms cubic-bezier(.2,.6,.3,1)}
  .readout>.hud-rays.is-t3{animation:hud-rays-3 400ms cubic-bezier(.2,.6,.3,1)}
  .readout>.hud-sparks:is(.is-t1,.is-t2,.is-t3)>.hud-spark{animation:hud-spark 380ms cubic-bezier(.12,.6,.3,1) var(--t,0ms) backwards}
  .readout>.hud-sparks.is-t3>.hud-spark{animation-duration:400ms}
  .readout>.hud-sparks.is-t1>.hud-spark:nth-child(n+5),.readout>.hud-sparks.is-t2>.hud-spark:nth-child(n+7){display:none}
  .readout>.hud-gold.is-on{animation:hud-gold-flash 220ms ease-out}
  .readout>.hud-glint.is-on{animation:hud-glint-show 860ms linear}
  .readout>.hud-glint.is-on .hud-glint-band{animation:hud-glint-band 860ms cubic-bezier(.45,.1,.4,1)}
  .readout>.hud-glint.is-on .hud-glint-copy{animation:hud-glint-copy 860ms cubic-bezier(.45,.1,.4,1)}

  /* 3e. THE LANE TAGS. On a lane change the tag being driven to pops and its
     lane colour flashes through it, and its underline slides across from the
     tag being left for exactly the lane change's length (.34s a lane), so it
     arrives with the car. At `playing` the three give a left-to-right "go";
     between rounds a light can sweep across them. */
  .lane-tag .lane-label.hud-pop{animation:hud-label-pop 280ms cubic-bezier(.3,.7,.4,1)}
  .lane-tags.hud-go .lane-label{animation:hud-label-pop 300ms cubic-bezier(.3,.7,.4,1) calc(var(--n,0) * 70ms) backwards}
  .lane-tag>.hud-tag-light.is-flash::before{animation:hud-tag-flash 360ms ease-out}
  .lane-tag>.hud-tag-light.is-go::before{animation:hud-tag-flash 300ms ease-out calc(var(--n,0) * 70ms) backwards}
  .lane-tag>.hud-tag-light.is-sweep::after{animation:hud-tag-sweep 560ms cubic-bezier(.45,.1,.45,1) calc(var(--n,0) * 130ms) backwards}
  .lane-tags .lane-tag.hud-rule-slide::after{animation:hud-rule-slide var(--hud-rule-ms,340ms) cubic-bezier(.45,.05,.35,1) both}

  /* 3f. CASH OUT RIPENS. It arrives out of BET (3l) at `playing`. Then a sheen
     crosses its amber every 3.2s, 2.7s, 2.2s, 1.7s, 1.2s by heat band, and
     from 4x the button gives a small beat with each one (hud-fx.js times
     both; this replaces club.css's old cash-beat, which read --heat inside its
     keyframes and has been switched off by the !important kill since v3). Its
     amount pops with every milestone, and when the cars touch -- the round
     already lost, the button dimmed -- it gives one short sideways nudge. */
  .deck .cash-button.hud-beat{animation:hud-beat 320ms cubic-bezier(.3,.6,.4,1)!important}
  .deck .cash-button.hud-locked{animation:hud-locked 260ms ease-out!important}
  .drive-controls .hud-sheen.is-on::before{animation:hud-sheen 640ms cubic-bezier(.4,.1,.35,1)}
  .deck #cashAmount.hud-pop{animation:hud-amount-pop 260ms cubic-bezier(.3,.7,.4,1) 40ms backwards}

  /* club.css's old drive glow and BET sheen (rgbVersion's) are infinite
     animations on two pseudo-elements the Signal palette hides with
     display:none. Chrome drops them; WebKit keeps them ticking, so on an
     iPhone they cost work every frame for nothing. The sheens replace them. */
  .drive-controls::before,.play-button:not(:disabled)::after{animation:none}

  /* 3g. BET. The launch fill runs left to right for exactly the run-up
     (app.js writes --launch-seconds), under GETTING READY. Between rounds a
     sheen can cross it, and ~1.4s after a result it invites the next round
     once: a sheen, and its label lifts 3px and settles (the label, never the
     button's box). A roll on the amount outranks the lift. */
  body[data-phase=launching] .drive-controls .play-button>.hud-fill{opacity:1;
    animation:hud-launch-fill var(--launch-seconds,2.4s) linear both}
  #playBtn.hud-invite>span{animation:hud-lift 420ms cubic-bezier(.3,.7,.4,1)}
  #playBtn.hud-invite>b:not(.hud-in-up,.hud-in-down){animation:hud-lift 420ms cubic-bezier(.3,.7,.4,1) 40ms backwards}

  /* 3h. AUTO: the knob slides (club.css, 200ms); switching it on sends one
     ring out from the knob once it has arrived. The target rolls like the bet
     (3c). */
  .deck .auto-toggle>.hud-knob-ring.is-on{animation:hud-knob-ring 520ms cubic-bezier(.2,.7,.3,1) 110ms backwards}

  /* 3i. THE MENU. The burger's lines turn into an x (a little overshoot
     opening, quicker closing) and the links cascade in, 30ms apart. The menu
     is a <details>, so closing is instant; only the x turns back. */
  .burger>i{transition:transform 150ms cubic-bezier(.4,0,.6,1),opacity 110ms linear}
  .deck-extras[open] .burger>i{transition:transform 240ms cubic-bezier(.3,1.45,.55,1),opacity 110ms linear}
  .deck-extras[open]>.deck-links{transform-origin:0 0;animation:hud-menu-in 200ms cubic-bezier(.2,.8,.3,1)}
  .deck-extras[open]>.deck-links>*{animation:hud-menu-item 220ms cubic-bezier(.2,.8,.3,1) var(--hud-k,0ms) backwards}
  .deck-links>:nth-child(1){--hud-k:20ms}
  .deck-links>:nth-child(2){--hud-k:50ms}
  .deck-links>:nth-child(3){--hud-k:80ms}
  .deck-links>:nth-child(4){--hud-k:110ms}
  .deck-links>:nth-child(5){--hud-k:140ms}
  .deck-links>:nth-child(6){--hud-k:170ms}
  .deck-links>:nth-child(7){--hud-k:200ms}
  .deck-links>:nth-child(n+8){--hud-k:230ms}

  /* 3j. THE DIALOGS open with a short scale and fade over a fading backdrop,
     and their lines cascade in behind the heading; a close is instant. The
     GOT IT and VERIFY buttons are .play-buttons, which club.css's kill would
     otherwise hold still. */
  dialog[open]{animation:hud-dialog-in 220ms cubic-bezier(.2,.8,.3,1)}
  dialog[open]::backdrop{animation:hud-fade-in 220ms ease-out}
  dialog[open]>:not(ol,.dialog-close),dialog[open]>ol>li{
    animation:hud-dialog-item 240ms cubic-bezier(.2,.8,.3,1) var(--hud-k,0ms) backwards!important}
  dialog>:nth-child(2){--hud-k:30ms}
  dialog>:nth-child(3){--hud-k:60ms}
  dialog>:nth-child(4){--hud-k:90ms}
  dialog>:nth-child(5){--hud-k:110ms}
  dialog>:nth-child(6){--hud-k:130ms}
  dialog>:nth-child(7){--hud-k:150ms}
  dialog>:nth-child(8){--hud-k:170ms}
  dialog>:nth-child(9){--hud-k:190ms}
  dialog>:nth-child(10){--hud-k:210ms}
  dialog>:nth-child(n+11){--hud-k:230ms}
  dialog>ol>li:nth-child(1){--hud-k:90ms}
  dialog>ol>li:nth-child(2){--hud-k:120ms}
  dialog>ol>li:nth-child(3){--hud-k:150ms}
  dialog>ol>li:nth-child(4){--hud-k:180ms}
  dialog>ol>li:nth-child(n+5){--hud-k:210ms}
  dialog>ol~:nth-child(n){--hud-k:240ms}

  /* 3l. THE PANEL CHANGES FACE. BET -> GETTING READY: the old words go up
     and out in 180ms while the new ones rise in behind them. BET -> CASH OUT
     at the start of a ride, and CASH OUT -> BET at its end: the old face
     (colour and words, from its dimmed self after a crash) holds for 60ms
     and fades over 300ms while the new words flip in, 60-420ms. On a phone,
     the row that takes the other's cell rises in as the old one's copy
     leaves upward. A changed value lights its well. A round's start and end
     send one light along the bar's neon rim. */
  .drive-controls .hud-label-ghost.is-on{animation:hud-label-out 180ms cubic-bezier(.4,0,.8,.4) both}
  .drive-controls .hud-label-in>:is(span,b){animation:hud-label-in 240ms cubic-bezier(.2,.8,.3,1) 50ms backwards}
  .drive-controls .hud-face.is-on{animation:hud-face-out 300ms ease-in 60ms both}
  .drive-controls .hud-face.is-on>i{animation:hud-words-out 140ms ease-in 40ms both}
  .drive-controls .hud-flip-in>:is(span,b){animation:hud-flip-in 360ms cubic-bezier(.2,.75,.3,1.15) 60ms backwards}
  .deck>.hud-row-ghost{animation:hud-row-out 180ms cubic-bezier(.4,0,.8,.4) both!important}
  .deck>.hud-row-in{animation:hud-row-in 280ms cubic-bezier(.2,.8,.3,1) 60ms backwards!important}
  .hud-well-glow.is-on{animation:hud-well-glow 460ms ease-out}
  .deck>.hud-rim.is-on{animation:hud-rim-show 950ms linear!important}
  .deck>.hud-rim.is-on>.hud-rim-band{animation:hud-rim-sweep 950ms cubic-bezier(.45,.05,.4,1)}

  /* 3k. THE TOAST rises from below with a small overshoot and fades out. */
  #toast{scale:.96;transition:opacity 170ms ease-in,transform 170ms ease-in,scale 170ms ease-in}
  #toast.show{scale:1;transition:opacity 120ms ease-out,transform 300ms cubic-bezier(.3,1.6,.5,1),scale 300ms cubic-bezier(.3,1.6,.5,1)}
}

/* 4. THE KEYFRAMES, by the moment they belong to. ---------------------------- */

/* The entrance. */
@keyframes hud-hold{from,to{opacity:0}}
@keyframes hud-sec-in{from{opacity:0;translate:0 16px}to{opacity:1;translate:0 0}}
@keyframes hud-tag-in{from{opacity:0;translate:0 -16px}to{opacity:1;translate:0 0}}
@keyframes hud-mult-in{from{opacity:0;transform:translateX(-50%) translateY(22%) scale(.94)}to{opacity:1;transform:translateX(-50%)}}
@keyframes hud-burger-in{from{opacity:0;translate:-6px -6px}to{opacity:1;translate:0 0}}

/* The press. The light comes up in ~60ms and is gone by 360ms. */
@keyframes hud-down{to{scale:var(--hud-sq)}}
@keyframes hud-up{0%{scale:var(--hud-sq)}42%{scale:var(--hud-over)}72%{scale:.992}100%{scale:1}}
@keyframes hud-tap-light{0%{opacity:0}17%{opacity:1}100%{opacity:0}}
@keyframes hud-tap-ring{0%{opacity:.9;scale:.08}100%{opacity:0;scale:1}}

/* The bet. */
@keyframes hud-in-up{from{opacity:0;transform:translateY(.75em)}to{opacity:1;transform:none}}
@keyframes hud-in-down{from{opacity:0;transform:translateY(-.75em)}to{opacity:1;transform:none}}
@keyframes hud-out-up{from{opacity:1;transform:none}to{opacity:0;transform:translateY(-.75em)}}
@keyframes hud-out-down{from{opacity:1;transform:none}to{opacity:0;transform:translateY(.75em)}}
@keyframes hud-no{0%,100%{translate:0 0}18%{translate:-4px 0}38%{translate:3.5px 0}58%{translate:-2.5px 0}78%{translate:1.2px 0}}

/* The multiplier. */
@keyframes hud-mult-rise{
  0%{opacity:0;transform:translateX(-50%) translateY(30%) scale(.88)}
  60%{opacity:1;transform:translateX(-50%) translateY(-2%) scale(1.02)}
  100%{opacity:1;transform:translateX(-50%)}
}
@keyframes hud-stamp-go{
  0%{transform:translateX(-50%) scale(1)}
  30%{transform:translateX(-50%) scale(1.1)}
  100%{transform:translateX(-50%) scale(1)}
}
/* A milestone stamps the number: out to 1.1 at 2x, 1.14 at 4x and 8x, 1.18
   from 16x, a little wider than tall, one small rebound, settled by
   300-340ms. */
@keyframes hud-stamp-1{
  0%{transform:translateX(-50%) scale(1)}
  22%{transform:translateX(-50%) scale(1.1,1.07)}
  52%{transform:translateX(-50%) scale(.985,1.01)}
  100%{transform:translateX(-50%) scale(1)}
}
@keyframes hud-stamp-2{
  0%{transform:translateX(-50%) scale(1)}
  21%{transform:translateX(-50%) scale(1.14,1.09)}
  50%{transform:translateX(-50%) scale(.98,1.012)}
  100%{transform:translateX(-50%) scale(1)}
}
@keyframes hud-stamp-3{
  0%{transform:translateX(-50%) scale(1)}
  20%{transform:translateX(-50%) scale(1.18,1.11)}
  48%{transform:translateX(-50%) scale(.975,1.015)}
  100%{transform:translateX(-50%) scale(1)}
}
@keyframes hud-flash{0%{opacity:0}24%{opacity:.45}100%{opacity:0}}
@keyframes hud-ring-1{0%{opacity:0;scale:.78}15%{opacity:.55}100%{opacity:0;scale:1.28}}
@keyframes hud-ring-2{0%{opacity:0;scale:.76}15%{opacity:.62}100%{opacity:0;scale:1.38}}
@keyframes hud-ring-3{0%{opacity:0;scale:.74}14%{opacity:.7}100%{opacity:0;scale:1.5}}
@keyframes hud-rays-2{0%{opacity:0;scale:.62;rotate:-4deg}30%{opacity:.34}100%{opacity:0;scale:.95;rotate:4deg}}
@keyframes hud-rays-3{0%{opacity:0;scale:.62;rotate:-5deg}28%{opacity:.45}100%{opacity:0;scale:1.08;rotate:5deg}}
@keyframes hud-spark{
  0%{opacity:1;transform:translate(0,0) rotate(var(--a)) scaleX(1.3)}
  70%{opacity:.9}
  100%{opacity:0;transform:translate(var(--x),var(--y)) rotate(var(--a)) scaleX(.35)}
}
@keyframes hud-gold-flash{0%{opacity:0}25%{opacity:.45}100%{opacity:0}}
@keyframes hud-glint-show{0%,100%{opacity:0}18%,80%{opacity:.95}}
@keyframes hud-glint-band{from{transform:translateX(-100%)}to{transform:translateX(250%)}}
@keyframes hud-glint-copy{from{transform:translateX(40%)}to{transform:translateX(-100%)}}

/* The lane tags. */
@keyframes hud-label-pop{0%{scale:1;translate:0 0}32%{scale:1.08;translate:0 -4%}100%{scale:1;translate:0 0}}
@keyframes hud-tag-flash{0%{opacity:0}28%{opacity:1}100%{opacity:0}}
@keyframes hud-tag-sweep{from{opacity:1;transform:translateX(-100%)}to{opacity:1;transform:translateX(215%)}}
@keyframes hud-rule-slide{from{transform:translateX(var(--hud-rule-from,0px))}to{transform:none}}

/* CASH OUT and BET. */
@keyframes hud-beat{0%,100%{transform:none}38%{transform:scale(1.022)}}
@keyframes hud-locked{0%,100%{transform:none}22%{transform:translateX(-3px)}48%{transform:translateX(3px)}74%{transform:translateX(-1.5px)}}
@keyframes hud-sheen{from{opacity:1;transform:translateX(-120%) skewX(-18deg)}to{opacity:1;transform:translateX(320%) skewX(-18deg)}}
@keyframes hud-amount-pop{0%{transform:none}36%{transform:scale(1.14)}100%{transform:none}}
@keyframes hud-launch-fill{from{transform:scaleX(0)}to{transform:scaleX(1)}}
@keyframes hud-lift{0%,100%{translate:0 0}40%{translate:0 -3px}}

/* The panel changing face. */
@keyframes hud-label-out{from{opacity:1;translate:0 0}to{opacity:0;translate:0 -70%}}
@keyframes hud-label-in{from{opacity:0;translate:0 70%}to{opacity:1;translate:0 0}}
@keyframes hud-face-out{from{opacity:var(--hud-from,1)}to{opacity:0}}
@keyframes hud-words-out{from{opacity:1}to{opacity:0}}
@keyframes hud-flip-in{from{opacity:0;transform:perspective(320px) rotateX(-88deg)}to{opacity:1;transform:none}}
@keyframes hud-row-out{from{opacity:1;translate:0 0}to{opacity:0;translate:0 -24%}}
@keyframes hud-row-in{from{opacity:0;translate:0 24%}to{opacity:1;translate:0 0}}
@keyframes hud-well-glow{0%{opacity:0}13%{opacity:1}100%{opacity:0}}
@keyframes hud-rim-show{0%,100%{opacity:0}12%,85%{opacity:1}}
@keyframes hud-rim-sweep{from{transform:translateX(-100%)}to{transform:translateX(385%)}}

/* AUTO, the menu, the dialogs (the backdrop's fade is the entrance's too). */
@keyframes hud-fade-in{from{opacity:0}to{opacity:1}}
@keyframes hud-knob-ring{0%{opacity:0;scale:.6}12%{opacity:.9}100%{opacity:0;scale:2.2}}
@keyframes hud-menu-in{from{opacity:0;transform:translateY(-6px) scale(.97)}to{opacity:1;transform:none}}
@keyframes hud-menu-item{from{opacity:0;translate:-8px 0}to{opacity:1;translate:0 0}}
@keyframes hud-dialog-in{from{opacity:0;scale:.96}to{opacity:1;scale:1}}
@keyframes hud-dialog-item{from{opacity:0;translate:0 8px}to{opacity:1;translate:0 0}}
