/* Whisperin — Motion (performance-safe: transform/opacity only; reduced-motion respected)
   Implements the 6 signature moves from deliverables/06-motion/whisper-in-motion-system.md */

/* 1. Scroll-reveal cascade (fade + 24px rise, staggered, once) */
[data-reveal]{opacity:0;transform:translateY(24px);transition:opacity var(--dur-slow) var(--ease-decelerate),transform var(--dur-slow) var(--ease-decelerate);transition-delay:calc(var(--i,0)*var(--stagger-line));will-change:transform,opacity}
[data-reveal].in{opacity:1;transform:none}

/* 2. Hero mask line-reveal (lines rise from clip mask) */
.line-mask{display:block;overflow:hidden;padding-bottom:.04em}
.line-mask>span{display:block;transform:translateY(115%);transition:transform var(--dur-cinematic) var(--ease-emphasized);transition-delay:calc(var(--i,0)*var(--stagger-line))}
.loaded .line-mask>span{transform:none}

/* 3. One-shot rose ripple behind hero */
.ripple{position:absolute;border-radius:50%;pointer-events:none;max-width:100vw;background:radial-gradient(circle,rgba(240,176,200,.5),transparent 62%);filter:blur(30px)}
.loaded .ripple{animation:wi-ripple 1.7s var(--ease-decelerate) .25s both}
@keyframes wi-ripple{0%{transform:scale(.5);opacity:0}28%{opacity:.55}100%{transform:scale(1.7);opacity:0}}

/* 4. Shimmer sweep (skeletons / accent) */
@keyframes wi-shimmer{0%{background-position:-150% 0}100%{background-position:250% 0}}
.shimmer{background:linear-gradient(120deg,transparent 28%,rgba(255,255,255,.14) 50%,transparent 72%);background-size:200% 100%;animation:wi-shimmer 2.2s linear infinite}

/* 5. Float (subtle ambient on hero visuals) */
@keyframes wi-float{0%,100%{transform:translateY(0)}50%{transform:translateY(-8px)}}
.float{animation:wi-float 6s var(--ease-standard) infinite}

/* 6. Pulse dot (live/launch badge) */
@keyframes wi-pulse{0%{box-shadow:0 0 0 0 rgba(240,176,200,.5)}70%{box-shadow:0 0 0 8px rgba(240,176,200,0)}100%{box-shadow:0 0 0 0 rgba(240,176,200,0)}}
.eyebrow .dot{animation:wi-pulse 2.4s var(--ease-standard) infinite}

/* Header logo / fade-in helper for first paint */
.fade-up-now{animation:wi-fadeup var(--dur-slow) var(--ease-decelerate) both}
@keyframes wi-fadeup{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}

/* ===== Journey/studio motion (v5) — transform/opacity only, reduced-motion-safe ===== */
/* Modal entrance: keyframe (plays on .open even from display:none) */
@keyframes wi-modal-in{from{opacity:0;transform:translateY(12px) scale(.985)}to{opacity:1;transform:none}}
.modal-backdrop.open .modal-card{animation:wi-modal-in var(--dur-base) var(--ease-emphasized) both}
/* Toast: rise + fade (element exists in DOM, transition runs) */
.toast{opacity:0;transform:translateY(10px);transition:opacity var(--dur-base),transform var(--dur-base) var(--ease-decelerate)}
.toast.in{opacity:1;transform:none}
/* Generation pipeline: active-step pulse (decorative; state still readable via color) */
@keyframes wi-pipe-pulse{0%,100%{opacity:.5}50%{opacity:1}}
.pipeline-step.is-active{animation:wi-pipe-pulse 1.1s var(--ease-standard) infinite}
/* Async spinner (checkout / generation simulate) */
@keyframes wi-spin{to{transform:rotate(360deg)}}
.spinner{width:22px;height:22px;border-radius:50%;border:2px solid rgba(255,255,255,.2);border-top-color:var(--wi-accent);animation:wi-spin .8s linear infinite}

/* ===== Accessibility: kill non-essential motion ===== */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important}
  [data-reveal],.line-mask>span{opacity:1!important;transform:none!important}
  .float,.shimmer,.eyebrow .dot{animation:none!important}
}
