/* motion.css — scroll reveals, ambient loops, and the reduced-motion contract.
 *
 * [data-reveal] elements rise in when js/reveal.js marks them .is-in; --d is the
 * element's beat in its section's stagger (x --stagger).
 *
 * A hidden element waits IN PLACE (opacity 0, no transform). The rise is a one-shot
 * keyframe animation with fill-mode `backwards`: it holds the start pose through the
 * stagger delay, then ends and lets go. Resting offsets on hidden elements pushed each
 * block into the next one's box, and Chrome chained the whole page into one
 * overlap layer (measured 390x7492 at DPR 3); `forwards` fills would keep every
 * revealed block on the GPU for good.
 *
 * Reduced motion: every reveal is already in place, every decorative loop is off,
 * and every interaction still completes (the JS modules check the same query).
 */

[data-reveal] {
  opacity: 0;
}

[data-reveal].is-in {
  opacity: 1;
  animation: reveal-rise 950ms var(--ease-out) backwards;
  animation-delay: calc(var(--d, 0) * var(--stagger));
}

@keyframes reveal-rise {
  from { opacity: 0; transform: translateY(var(--rise)); }
  to   { opacity: 1; transform: none; }
}

/* the shloka "inks in": a small blur-to-sharp on each short line */
.shloka__line[data-reveal].is-in {
  animation-name: reveal-ink;
}

@keyframes reveal-ink {
  from { opacity: 0; transform: translateY(var(--rise)); filter: blur(6px); }
  to   { opacity: 1; transform: none; filter: blur(0); }
}

/* shared celebration pieces (js/fx.js) */
.burst-flower {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 3;
  width: var(--s, 26px);
  height: auto;
  pointer-events: none;
}

.toran {
  animation: toran-sway 6.5s var(--ease-soft) infinite alternate;
}

@keyframes toran-sway {
  from { transform: rotate(-0.8deg) translateY(0); }
  to   { transform: rotate(0.8deg) translateY(2px); }
}

/* js/ambient.js marks sections far from the viewport .is-away: their perpetual loops
   stop, so they hold no compositor layers (and cost no battery) while unseen. The
   loops are seamless, so restarting from frame 0 on return is invisible. */
.is-away .toran,
.is-away .flame::before,
.is-away .flame::after,
.is-away .aarti__guide,
.is-away .aarti__thali-glow,
.is-away .wish__mooshak > img,
.is-away .wish__ear-ring,
.is-away .darshan__next {
  animation-name: none;
}

/* the names carry [reveal, sheen]; renaming would replay the reveal, so only pause the sheen */
.is-away .couple__name.is-in {
  animation-play-state: running, paused;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  [data-reveal],
  [data-reveal].is-in {
    opacity: 1;
    animation: none;
  }

  .toran,
  .gate__bloom,
  .gate__flare,
  .gate__cue,
  .gate__hint,
  .darshan__next,
  .couple__name,
  .couple__name[data-reveal].is-in,
  .aarti__guide,
  .aarti__thali-glow,
  .wish__mooshak > img,
  .wish__ear-ring,
  .flame::before,
  .flame::after {
    animation: none !important;
  }

  .event__niche,
  .event__img {
    opacity: 1;
    transform: none;
    transition: none;
  }

  .gate {
    transition-duration: 400ms;
  }
}
