/* STEEP motion, shared by the Versus pages (cpu/, join/, room/) since 22 Oct 2026, so every way
   to play feels like Play STEEP (Joe: "dont have the advanced sound backgrounds, animations").
   The moves and timings are Play STEEP's own (site/index.html, "motion" block): a new question
   RISES so it is unmistakably new, the answers CASCADE so the eye lands on A first, a right answer
   GLOWS once, a miss SHAKES because it must not be missable, a result POPS, a score BUMPS, and a
   final score lands on REELS (catalog slot-machine-roll, as on the solo results). Transform and
   opacity only; nothing loops or idles; reduced motion gets the finished state with no movement.
   Classes are fx-prefixed so they cannot collide with a page's own. Helpers: site/fx.js. */

@keyframes fxRise{from{opacity:0;transform:translateY(16px)}to{opacity:1;transform:none}}
@keyframes fxCascade{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
@keyframes fxShake{0%,100%{transform:translateX(0)}20%{transform:translateX(-7px)}40%{transform:translateX(6px)}60%{transform:translateX(-4px)}80%{transform:translateX(2px)}}
@keyframes fxBump{0%{transform:scale(1)}40%{transform:scale(1.28)}100%{transform:scale(1)}}
@keyframes fxPop{from{opacity:0;transform:scale(.86)}60%{transform:scale(1.04)}to{opacity:1;transform:scale(1)}}
/* Right-answer glow (23 Oct 2026): a ring that scales and fades (transform + opacity only), in the world's mint (--right). */
@keyframes fxGlow{from{transform:scale(1);opacity:.75}to{transform:scale(1.07,1.25);opacity:0}}
@keyframes fxReel{from{transform:translateY(0)}}

/* Film grain over the whole page, as on the home screen: a still texture (an animated one
   repaints every frame), above everything, never in the way of a tap. */
body.fx-grain::after{content:"";position:fixed;inset:0;z-index:9000;pointer-events:none;opacity:.045;
  background:url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.72' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 .86 0 0 0 0 .62 0 0 0 1 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E")}
@media print{body.fx-grain::after{display:none}}

/* Final score on reels: each digit is a strip resting at its digit (the painted default is the
   real number); the keyframe only says where it starts. Later reels spin longer, so they stop
   left to right. Screen readers get the number from .fx-sr. */
.fx-reels{display:inline-flex;align-items:flex-start;font-variant-numeric:tabular-nums}
.fx-dig{display:inline-block;height:1em;line-height:1;overflow:hidden}
.fx-strip{display:flex;flex-direction:column;transform:translateY(calc(var(--n) * -1em))}
.fx-strip b{display:block;height:1em;line-height:1;font-weight:inherit}
.fx-sep{line-height:1}
.fx-sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}

@media (prefers-reduced-motion:no-preference){
  .fx-rise{animation:fxRise .42s cubic-bezier(.2,.85,.25,1) both}
  .fx-cascade > *{animation:fxCascade .38s cubic-bezier(.2,.85,.25,1) both}
  .fx-cascade > :nth-child(2){animation-delay:.07s}
  .fx-cascade > :nth-child(3){animation-delay:.14s}
  .fx-cascade > :nth-child(4){animation-delay:.21s}
  .fx-cascade > :nth-child(n+5){animation-delay:.28s}
  .fx-glow{position:relative}
  .fx-glow::after{content:"";position:absolute;inset:-2px;border-radius:inherit;border:3px solid var(--right,#4fd6a0);pointer-events:none;animation:fxGlow .75s ease-out 1 both}
  .fx-shake{animation:fxShake .42s ease-in-out 1}
  .fx-pop{animation:fxPop .6s cubic-bezier(.2,.85,.25,1) both}
  .fx-bump{display:inline-block;animation:fxBump .5s cubic-bezier(.2,.85,.25,1) 1}
  .fx-strip{animation:fxReel calc(.5s + var(--i) * .1s) cubic-bezier(.12,.7,.2,1) both}
}
