/* OWNER: Charlie, register lane (checkout screen, and the Glamaroo Pay reader sheet by DOM contract with
   lane P2), refined September 29 2026. Loaded after css/motion.css. Scope: [data-testid="total"] and
   [data-testid="paid-today"] (unique attribute hooks on the sale total and the paid counter), .co-line /
   .co-tenders .btn (checkout's own co- prefix), and [data-pay-state] (P2's reader sheet root; M2 never sees
   or edits P2's markup, only keys off that attribute). Transform and opacity only, color and background-color
   allowed as static values. Never width, height, top, left, right, bottom, margin, padding on anything animated. */

/* Moment 1: the total pops when its text changes (class toggled by js/motion-register.js on a MutationObserver).
   Refined Sep 29: was var(--mo-fast), 160ms, under this release's 180-420ms floor. Moved to var(--mo-base). */
[data-testid="total"]{position:relative}
[data-testid="total"].mo-reg-pop{animation:moRegPop var(--mo-base) var(--mo-spring)}
@keyframes moRegPop{0%{transform:scale(1)}45%{transform:scale(1.06)}100%{transform:scale(1)}}

/* Moment 2: the paid overlay (a drawn check + one shimmer sweep), appended and removed by js/motion-register.js.
   Zero text nodes inside .mo-reg-paid: it must never change [data-testid="total"].textContent.
   Refined Sep 29: check-in moved off var(--mo-fast) onto the 180-420ms floor; the shimmer is dialed down,
   never louder than before, a narrower and dimmer sweep instead of a flash, its ceiling (--mo-slow) unchanged. */
.mo-reg-paid{position:absolute;inset:0;display:flex;align-items:center;justify-content:flex-end;overflow:hidden;pointer-events:none}
.mo-reg-check{width:.9em;height:.9em;flex:none;color:var(--ok,var(--accent));opacity:0;transform:scale(.4) rotate(-10deg);animation:moRegCheckIn var(--mo-base) var(--mo-spring) forwards}
@keyframes moRegCheckIn{to{opacity:1;transform:scale(1) rotate(0)}}
.mo-reg-shimmer{position:absolute;inset:0;background:linear-gradient(100deg,transparent 40%,color-mix(in srgb,var(--accent) 30%,transparent) 50%,transparent 60%);transform:translateX(-120%);animation:moRegShimmer var(--mo-slow) var(--mo-ease) forwards}
@keyframes moRegShimmer{to{transform:translateX(120%)}}

/* Moment 3: ticket lines and tender buttons rise in once, only inside the real mount's data-mo-enter window,
   so a save-triggered re-render never replays it. First 8 items only, whole stagger under 300ms. */
[data-mo-enter="checkout"] .co-line:nth-child(-n+8),[data-mo-enter="checkout"] .co-tenders .btn:nth-child(-n+8){opacity:0;transform:translateY(var(--mo-rise));animation:moRegRise var(--mo-base) var(--mo-ease-out) both}
@keyframes moRegRise{to{opacity:1;transform:translateY(0)}}
[data-mo-enter="checkout"] .co-line:nth-child(1),[data-mo-enter="checkout"] .co-tenders .btn:nth-child(1){animation-delay:calc(var(--mo-stagger) * 0)}
[data-mo-enter="checkout"] .co-line:nth-child(2),[data-mo-enter="checkout"] .co-tenders .btn:nth-child(2){animation-delay:calc(var(--mo-stagger) * 1)}
[data-mo-enter="checkout"] .co-line:nth-child(3),[data-mo-enter="checkout"] .co-tenders .btn:nth-child(3){animation-delay:calc(var(--mo-stagger) * 2)}
[data-mo-enter="checkout"] .co-line:nth-child(4),[data-mo-enter="checkout"] .co-tenders .btn:nth-child(4){animation-delay:calc(var(--mo-stagger) * 3)}
[data-mo-enter="checkout"] .co-line:nth-child(5),[data-mo-enter="checkout"] .co-tenders .btn:nth-child(5){animation-delay:calc(var(--mo-stagger) * 4)}
[data-mo-enter="checkout"] .co-line:nth-child(6),[data-mo-enter="checkout"] .co-tenders .btn:nth-child(6){animation-delay:calc(var(--mo-stagger) * 5)}
[data-mo-enter="checkout"] .co-line:nth-child(7),[data-mo-enter="checkout"] .co-tenders .btn:nth-child(7){animation-delay:calc(var(--mo-stagger) * 6)}
[data-mo-enter="checkout"] .co-line:nth-child(8),[data-mo-enter="checkout"] .co-tenders .btn:nth-child(8){animation-delay:calc(var(--mo-stagger) * 7)}

/* Moment 4: the Glamaroo Pay reader sheet (lane P2, built in a worktree this lane cannot see). Coordinated
   through the DOM only, per DIRECTION-PAY.md: the sheet's root carries data-pay-state with the current state.
   M2 never touches P2's markup, only this attribute, proved with a synthetic element in tests/motion-register.html.
   Busy states get a soft breathing pulse; a capture gets a gentle settle; a failure gets a small shake, never a
   jolt; a step back (canceled or a timeout) gets a soft fade, calmer than the shake since neither is an error. */
[data-pay-state="sending"],[data-pay-state="waiting"],[data-pay-state="tapped"],[data-pay-state="processing"]{animation:moPayPulse var(--mo-slow) var(--mo-ease) infinite alternate}
@keyframes moPayPulse{from{transform:scale(1);opacity:1}to{transform:scale(1.015);opacity:.92}}

[data-pay-state="captured"]{animation:moPaySettle var(--mo-base) var(--mo-ease-out)}
@keyframes moPaySettle{0%{transform:scale(1.03);opacity:.85}100%{transform:scale(1);opacity:1}}

[data-pay-state="failed"]{animation:moPayShake var(--mo-base) var(--mo-ease)}
@keyframes moPayShake{0%,100%{transform:translateX(0)}20%{transform:translateX(-4px)}40%{transform:translateX(4px)}60%{transform:translateX(-3px)}80%{transform:translateX(3px)}}

[data-pay-state="canceled"],[data-pay-state="timed_out"]{animation:moPayFade var(--mo-base) var(--mo-ease)}
@keyframes moPayFade{0%{opacity:1}50%{opacity:.82}100%{opacity:1}}
