/*
 * site-anim.css — shared site-animation runtime (behavior only, no colours).
 * Companion to /site-anim.js. Served by the bot at /site-anim.css so any theme
 * (client sites + demos) can opt in with one <link> + data-attributes.
 *
 * SAFE BY DEFAULT: effects arm ONLY when the runtime adds `saa-on` to <html>
 * (it does that only when JS runs, IntersectionObserver exists, and the user has
 * NOT asked to reduce motion). No JS / old browser / reduced-motion => every
 * element renders fully visible and static. Nothing here sets a colour — the
 * curtain colour is a CSS var the theme overrides (default: deep navy).
 *
 * API (attributes the theme adds to its own markup):
 *   data-reveal[="up|left|right|scale"]  fade/slide in once on scroll
 *   data-stagger                          on a parent: its [data-reveal] children cascade
 *   data-curtain[="#hex"]                 a panel lifts off the section once (needs its own colour)
 *   data-count="1234"                     count up 0→N once in view (text is the final value)
 *   data-parallax="0.2"                   drift on scroll (speed factor; use small values)
 *   data-magnetic="0.3"                   element eases toward the cursor
 *   video[data-cine]                      background video plays only while on screen
 */

:root {
  --saa-rise: 24px;
  --saa-dur: 0.7s;
  --saa-ease: cubic-bezier(0.22, 1, 0.36, 1);
  --saa-stagger: 90ms;
  --saa-curtain: #0f1a2e;
}

/* Reveal + curtain hidden states apply ONLY under html.saa-on AND when motion
   is allowed, so the no-JS / reduced-motion baseline is "everything visible". */
@media (prefers-reduced-motion: no-preference) {
  html.saa-on [data-reveal] {
    opacity: 0;
    transform: translateY(var(--saa-rise));
    transition:
      opacity var(--saa-dur) var(--saa-ease),
      transform var(--saa-dur) var(--saa-ease);
    transition-delay: calc(var(--saa-i, 0) * var(--saa-stagger));
    will-change: opacity, transform;
  }
  html.saa-on [data-reveal="left"]  { transform: translateX(calc(-1 * var(--saa-rise))); }
  html.saa-on [data-reveal="right"] { transform: translateX(var(--saa-rise)); }
  html.saa-on [data-reveal="scale"] { transform: scale(0.94); }
  html.saa-on [data-reveal].saa-in  { opacity: 1; transform: none; }

  html.saa-on .saa-curtain { transition: transform 0.6s var(--saa-ease); }
  /* Cover ONLY while armed and not yet revealed. Gating the covered state on
     saa-on means a runtime failure (which removes saa-on) can never leave a
     section trapped behind the panel — it defaults to lifted (scaleY 0). */
  html.saa-on [data-curtain]:not(.saa-in) > .saa-curtain { transform: scaleY(1); }
}

/* The curtain panel the runtime injects as the section's first child.
   Default lifted (scaleY 0) so no-JS / reduced-motion / error never covers. */
.saa-curtain {
  position: absolute;
  inset: 0;
  z-index: 5;
  background: var(--saa-curtain);
  transform-origin: top;
  transform: scaleY(0);
  pointer-events: none;
}

[data-parallax] { will-change: transform; }
[data-magnetic] { transition: transform 0.25s var(--saa-ease); }
