/* Round 35 lane M (Nov 1 2026, r3129): motion and bounce. Loads LAST on every page. Spec: docs/MOTION.md.
   Only transform, opacity and clip-path move. Every moving rule sits inside (prefers-reduced-motion: no-preference); the
   reduce block at the end turns off every class this layer adds. Nothing loops. Colours come from the :root tokens below,
   which are made from the one button colour (--go-bg). Classes this layer adds from r35m.js: r35m-pop, r35m-back,
   r35m-still, r35m-rest, r35m-count, r35m-fig, r35m-land, r35m-notch. */
:root{
  --m-pop:cubic-bezier(.34,1.56,.64,1);
  --m-spring:cubic-bezier(.22,1.35,.36,1);
  --m-slide:cubic-bezier(.3,1.25,.4,1);
  --m-return:340ms; --m-popd:360ms; --m-slided:380ms; --m-dropd:260ms; --m-countd:380ms;
  --m-ledge:4px;
  --r35m-ledge-mix:var(--ink);
  --r35m-ledge:color-mix(in oklab, var(--go-bg) 70%, var(--r35m-ledge-mix));
  /* r3134, r3135, r3137 glows. Light: no blur, no halo on the price (the ruling allows nothing), crisp violet rings on the
     pressed button only, no resting glow, no tile glow. Every colour here reads a token, so a class on <html> (lane H's local
     themes, r3136) re-points the whole layer by re-valuing --go-bg, --link and --focus. */
  --glow-price:none;
  --glow-price-card:none;
  --glow-go:0 0 0 3px var(--bg), 0 0 0 5px var(--focus);
  --glow-cta:none;
  --glow-tile:none;
}
@media (prefers-color-scheme: dark){
  :root{
    --r35m-ledge-mix:var(--bg);
    /* r3134 (3 Opus seats), r3151: a pre-blurred gold halo under the one all-in marker; alpha .25 is the maximum (muted text
       nearby stays 4.93:1 on the page at .25 and 5.20:1 on a card at .18, measured in design/polish/contrast.py). The card's halo is softer because the grey ad price sits within 24px of the marker. The button ring
       (r3135: violet, #C084FF based) shows on :focus-visible and :active: 3px page, 2px violet, a 16px violet glow. r3137: the one
       primary call to action may rest in a soft violet glow (alpha .22, under the halo's .25 so the price wins the first look),
       and a chosen tile gets a violet edge glow. */
    --glow-price:0 0 0 1px var(--price-bg), 0 0 20px 2px rgba(255,200,20,.25);
    --glow-price-card:0 0 0 1px var(--price-bg), 0 0 20px 2px rgba(255,200,20,.18);
    --glow-go:0 0 0 3px var(--bg), 0 0 0 5px var(--focus), 0 0 16px rgba(192,132,255,.40);
    --glow-cta:0 0 18px 2px rgba(192,132,255,.22);
    --glow-tile:0 0 0 1px var(--focus), 0 0 14px rgba(192,132,255,.25);
  }
}

/* r3136: San Francisco's blue action carries blue glows. With no theme class this block does nothing. */
@media (prefers-color-scheme: dark){
  html.theme-sf{
    --glow-go:0 0 0 3px var(--bg), 0 0 0 5px var(--focus), 0 0 16px rgba(159,176,255,.40);
    --glow-cta:0 0 18px 2px rgba(159,176,255,.22);
    --glow-tile:0 0 0 1px var(--focus), 0 0 14px rgba(159,176,255,.25);
  }
}

/* Round 35 release: the Gap key names the colour that is drawn. Violet by default, Blue on a San Francisco page (server class or the link's theme). */
.gk-b{display:none}
html.theme-sf .gk-v{display:none}
html.theme-sf .gk-b{display:inline}

/* ---- r3137 neon: the chosen tile keeps its ink fill (reads in greyscale) and gains a neon violet edge; in dark mode the edge glows.
   The tick stays. The tile's text is page colour on ink, so AA holds. */
.wz-tile.on,.wz-tile[aria-pressed=true]{border-color:var(--go-bg);box-shadow:var(--glow-tile)}
/* r3137: the one primary call to action may rest in a soft glow (dark only; light's token is none). The pressed ring replaces it. */
.r35-cta{box-shadow:var(--glow-cta)}

/* ---- r3134 price halo: a ::after under the final all-in marker (the hero receipt total, today's hero marker, the deal receipt
   sum) and under the #1 result card's marker. Never on a warn price, never on the tip card, never as text-shadow. At most one at
   rest: once results show (body.wz-done) only the #1 card keeps its halo. The end state is static; only its fade-in is motion. */
.rc-sum,.r35-rcpt-total b,.r35-rcpt-total .r35-allin,.r35m-fig{position:relative;isolation:isolate}
.r35m-fig{display:inline-block}
.r26-real::after,.rc-sum::after,.r35-rcpt-total b::after,.wz-cards>.dcard:first-child .dcard-price b::after{content:"";position:absolute;inset:0;z-index:-1;border-radius:var(--r2);box-shadow:var(--glow-price);pointer-events:none}
.wz-cards>.dcard:first-child .dcard-price b::after{box-shadow:var(--glow-price-card)}
.receipt.unv .rc-sum::after,.dcard.unv .dcard-price b::after,.r35-rcpt-total.unv b::after,.tipw b::after,.tipw .rc-sum::after{content:none;box-shadow:none}
.wz-done .r26-real::after,.wz-done .rc-sum::after,.wz-done .r35-rcpt-total b::after{content:none}
/* the side preview on a wide first screen has its own marker; only the hero's marker glows, so at most one halo is at rest */
.r26-pv .r26-real::after{content:none}
/* a card below the fold waits for its marker (gap.js mark-wait); its halo waits too, so a ring never shows round an unmarked price */
.mark-wait .dcard-price b::after{opacity:0}

/* ---- r3134 button glow ring: pressed or keyboard-focused primary buttons only, never at rest, never the tip card's button */
.btn:not(.ghost):not(.tipw-go):focus-visible,.btn:not(.ghost):not(.tipw-go):active,.r35-cta:focus-visible,.r35-cta:active{box-shadow:var(--glow-go);outline:none}

/* ---- the chunky button: a violet face on a darker ledge. The face is ::after, the ledge is ::before; the button's own
   background goes clear so both can sit behind the label. The ledge is drawn in every mode (it is a shape, not motion). */
.btn:not(.ghost){position:relative;isolation:isolate;background:transparent;box-shadow:none}
.r35-cta{position:relative;isolation:isolate;background:transparent}
.r35-cta{--m-ledge:5px}
.btn:not(.ghost)::after,.r35-cta::after{content:"";position:absolute;inset:0;z-index:-1;border-radius:calc(var(--r2) - 2px);background:var(--go-bg)}
.btn:not(.ghost)::before,.r35-cta::before{content:"";position:absolute;inset:-2px;z-index:-2;border-radius:var(--r2);border:2px solid var(--edge);
  background:var(--edge);background:var(--r35m-ledge);transform:translateY(var(--m-ledge))}
.btn:not(.ghost):hover{box-shadow:none;filter:none}
.r35-cta:hover{box-shadow:var(--glow-cta);filter:none}
/* the active transform from highlighter.css moved into the ledge rule below; in reduce mode the press is a plain colour change */
.btn:not(.ghost):active,.r35-cta:active{transform:none}

@media (prefers-reduced-motion:no-preference){
  /* hover lifts, fine pointer only (first, so a press below wins while the pointer is down) */
  @media (hover:hover) and (pointer:fine){
    .btn:not(.ghost):hover,.r35-cta:hover{transform:translateY(-1px)}
    .btn:not(.ghost):hover::before,.r35-cta:hover::before{transform:translateY(calc(var(--m-ledge) + 1px))}
    .dcard{transition:transform 200ms var(--e-land)}
    .dcard:hover{transform:translateY(-2px)}
    .wz-tile:hover,.mchip:hover,.chip:hover{transform:translateY(-1px)}
  }

  /* press down 90 ms, spring back 340 ms. The ledge counter-moves on the same curve, so it stays still on screen. */
  .btn:not(.ghost),.r35-cta{transition:transform var(--m-return) var(--m-spring)}
  .btn:not(.ghost)::before,.r35-cta::before{transition:transform var(--m-return) var(--m-spring)}
  .btn:not(.ghost):active,.r35-cta:active{transform:translateY(var(--m-ledge));transition-duration:var(--d-press);transition-timing-function:var(--e-arrive)}
  .btn:not(.ghost):active::before,.r35-cta:active::before{transform:translateY(0);transition-duration:var(--d-press);transition-timing-function:var(--e-arrive)}

  /* ghost buttons, chips and tiles: a scale press with the same springy return */
  .btn.ghost,.chip,.mchip,.wz-tile,.wz-kind,.tipw-skip,.linkbtn{transition:transform var(--m-return) var(--m-spring)}
  .btn.ghost:active,.chip:active,.mchip:active,.wz-tile:active,.wz-kind:active{transform:scale(.96);transition-duration:var(--d-press);transition-timing-function:var(--e-arrive)}

  /* the thing just chosen pops; the tick on a kind tile draws in from the left */
  @keyframes r35m-pop{0%{transform:scale(1)}45%{transform:scale(1.06)}75%{transform:scale(.98)}100%{transform:scale(1)}}
  .r35m-pop{animation:r35m-pop var(--m-popd) var(--e-land)}
  @keyframes r35m-check{from{clip-path:inset(0 100% 0 0)}to{clip-path:inset(0 0 0 0)}}
  .wz-kind.r35m-pop::after{animation:r35m-check 240ms var(--e-land) 80ms backwards}

  /* a step slides in with a 3 px overshoot; Back slides the other way (r35m.js sets r35m-back on the mount for one render) */
  @keyframes r35m-slide{0%{opacity:0;transform:translateX(32px)}70%{opacity:1;transform:translateX(-3px)}100%{opacity:1;transform:none}}
  @keyframes r35m-slide-back{0%{opacity:0;transform:translateX(-32px)}70%{opacity:1;transform:translateX(3px)}100%{opacity:1;transform:none}}
  .wz-in{animation:r35m-slide var(--m-slided) var(--m-slide) backwards}
  .r35m-back .wz-in{animation-name:r35m-slide-back}

  /* results cards pop in, the first six 60 ms apart, the rest together; a card already on screen keeps still */
  @keyframes r35m-cardpop{0%{opacity:0;transform:translateY(16px) scale(.97)}65%{opacity:1;transform:translateY(-3px) scale(1.01)}100%{opacity:1;transform:none}}
  @keyframes r35m-fade{from{opacity:0}to{opacity:1}}
  .wz-cards>.dcard:nth-child(n){animation:r35m-cardpop var(--m-slided) var(--e-land) backwards;animation-delay:var(--r35m-d,0ms)}
  .wz-cards>.dcard.r35m-rest:nth-child(n){animation:r35m-fade 220ms var(--e-land) backwards;animation-delay:var(--r35m-d,300ms)}
  .wz-cards>.dcard.r35m-still:nth-child(n){animation:none}
  /* the marker swipes 60 ms after its card starts to show; in dark mode the digits are dark ink until it covers them, so the gap stays short (about 300 ms) */
  .wz-cards>.dcard:nth-child(n) .dcard-price b::before{animation-delay:calc(var(--r35m-d,0ms) + 60ms)}
  .wz-cards>.dcard.r35m-still:nth-child(n) .dcard-price b::before{animation:none}

  /* the gold marker swipe, now with overshoot: the pen runs 4 px past the end and settles (same name, defined last) */
  @keyframes mark-swipe{0%{clip-path:inset(0 100% 0 0);transform:translateX(-3px)}70%{clip-path:inset(0 0 0 0);transform:translateX(4px)}100%{clip-path:inset(0 0 0 0);transform:none}}

  /* the receipt (lane H prints it): lines drop in one by one, CSS only, and only when scripts run, so JS off shows all at once */
  @media (scripting:enabled){
    @keyframes r35m-drop{from{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:none}}
    .r35-rcpt .r35-rcpt-line,.r35-rcpt .r35-rcpt-total{animation:r35m-drop var(--m-dropd) var(--e-land) backwards}
    .r35-rcpt .r35-rcpt-line:nth-of-type(2){animation-delay:55ms}
    .r35-rcpt .r35-rcpt-line:nth-of-type(3){animation-delay:110ms}
    .r35-rcpt .r35-rcpt-line:nth-of-type(4){animation-delay:165ms}
    .r35-rcpt .r35-rcpt-line:nth-of-type(n+5){animation-delay:220ms}
    .r35-rcpt .r35-rcpt-total:nth-of-type(n){animation-delay:220ms}
  }
  /* the count-up figure keeps the final width (r35m.js measures it once); the landing bounce scales the figure and its marker */
  .r35m-count{display:inline-block;min-width:var(--r35m-w,0);text-align:right;font-variant-numeric:tabular-nums}
  @keyframes r35m-land{0%{transform:scale(1)}40%{transform:scale(1.08)}70%{transform:scale(.98)}100%{transform:scale(1)}}
  .r35m-land{animation:r35m-land 420ms var(--e-land)}

  /* r3134: the halo fades in once, opacity only, right after its marker lands (the swipe is 400 ms; the card's starts at d + 60 ms;
     the receipt total lands at 600 ms and bounces to 1,020 ms, so its halo rises through the bounce). The blur never animates. */
  @keyframes r35m-halo{from{opacity:0}to{opacity:1}}
  .r26-real::after,.rc-sum::after{animation:r35m-halo 300ms var(--e-land) 400ms backwards}
  .wz-cards>.dcard:first-child .dcard-price b::after{animation:r35m-halo 300ms var(--e-land) backwards;animation-delay:calc(var(--r35m-d,0ms) + 460ms)}
  .wz-cards>.dcard.r35m-still:first-child .dcard-price b::after{animation:none}
  .wz-cards>.dcard.mark-wait:first-child .dcard-price b::after{animation:none}   /* restarts on mark-go, so it follows the late swipe */
  @media (scripting:enabled){ .r35-rcpt-total b::after{animation:r35m-halo 300ms var(--e-land) 700ms backwards} }

  /* the "?" beside a big number (lane H, r3130): the answer pops open from the control's corner with a spring; it closes at
     once (display none), so the close is faster than the open. A details or a hidden toggle both restart the animation. */
  @keyframes r35m-whyopen{0%{opacity:0;transform:scale(.94)}100%{opacity:1;transform:scale(1)}}
  .r35-why-body{transform-origin:var(--r35m-why-origin,top right)}
  .r35-why-body.r35m-open{animation:r35m-whyopen 280ms var(--m-pop) backwards}   /* r35m.js restarts the class on each open (WebKit does not restart an animation on a details child by itself) */

  /* the tip slider: the thumb bounces at each notch (r35m.js restarts the class), the stage photo pops */
  @keyframes r35m-thumb{0%{transform:scale(1)}40%{transform:scale(1.3)}70%{transform:scale(.94)}100%{transform:scale(1)}}
  .tipw-range.r35m-notch::-webkit-slider-thumb{animation:r35m-thumb 320ms var(--e-land)}
  .tipw-range.r35m-notch::-moz-range-thumb{animation:r35m-thumb 320ms var(--e-land)}
  @keyframes r35m-stagepop{0%{transform:scale(.97)}60%{transform:scale(1.015)}100%{transform:scale(1)}}
  .tipw-js .tipw-item.is-on .tipw-fig{animation:r35m-stagepop 300ms var(--e-land)}   /* on the photo, not the item: tip.css already transitions the item's transform and filter, and both at once crashed WebKit */
}

/* ---- reduced motion: nothing this layer adds moves; every final state is simply there */
@media (prefers-reduced-motion:reduce){
  .btn:not(.ghost),.r35-cta,.btn:not(.ghost)::before,.r35-cta::before,.btn.ghost,.chip,.mchip,.wz-tile,.wz-kind,.tipw-skip,.linkbtn,
  .r35m-pop,.wz-kind.r35m-pop::after,.wz-in,.r35m-back .wz-in,.wz-cards>.dcard,.wz-cards>.dcard .dcard-price b::before,.dcard,
  .r35-rcpt .r35-rcpt-line,.r35-rcpt .r35-rcpt-total,.r35m-count,.r35m-land,.tipw-range.r35m-notch::-webkit-slider-thumb,
  .tipw-range.r35m-notch::-moz-range-thumb,.tipw-js .tipw-item.is-on .tipw-fig,.r35-why-body,
  .r26-real::after,.rc-sum::after,.r35-rcpt-total b::after,.wz-cards>.dcard:first-child .dcard-price b::after{animation:none;transition:none}
}
