/* ==========================================================================
   Rediza — Motion primitives
   Declarative reveal states. JS (reveal.js) only ever toggles `.is-in`
   and writes scroll progress into `--p`; all timing lives here.
   ========================================================================== */

/* --- Entrance reveals ---------------------------------------------------- */
/* Every reveal shares one easing + one duration family so the page reads as
   a single coordinated system rather than a pile of effects. */

[data-reveal] {
  --delay: calc(var(--i, 0) * var(--stagger, 70ms));
  transition:
    opacity var(--d-slow) var(--e-out) var(--delay),
    transform var(--d-slow) var(--e-out) var(--delay),
    filter var(--d-slow) var(--e-out) var(--delay),
    clip-path var(--d-epic) var(--e-out) var(--delay);
  will-change: opacity, transform;
}

[data-reveal="fade"]  { opacity: 0; }
[data-reveal="rise"]  { opacity: 0; transform: translate3d(0, 34px, 0); }
[data-reveal="rise-s"]{ opacity: 0; transform: translate3d(0, 16px, 0); }
[data-reveal="fall"]  { opacity: 0; transform: translate3d(0, -24px, 0); }
[data-reveal="left"]  { opacity: 0; transform: translate3d(-40px, 0, 0); }
[data-reveal="right"] { opacity: 0; transform: translate3d(40px, 0, 0); }
[data-reveal="scale"] { opacity: 0; transform: scale(0.94); }
[data-reveal="blur"]  { opacity: 0; filter: blur(14px); transform: scale(1.03); }
[data-reveal="wipe"]  { clip-path: inset(0 100% 0 0); }
[data-reveal="rule"]  { transform: scaleX(0); transform-origin: left center; }

[data-reveal].is-in {
  opacity: 1;
  filter: blur(0);
  transform: none;
  clip-path: inset(0 0 0 0);
}
[data-reveal="rule"].is-in { transform: scaleX(1); }

/* Once played, stop reserving a compositor layer. */
[data-reveal].is-done { will-change: auto; }

/* --- Split-text mask reveal (the Apple signature) ------------------------ */
/* split.js wraps each line/word/char in .sp-mask > .sp-part */

.sp-mask {
  display: block;
  overflow: hidden;
  padding-bottom: 0.06em;   /* room for descenders inside the mask */
  margin-bottom: -0.06em;
}
.sp-mask--inline { display: inline-block; vertical-align: top; }

.sp-part {
  display: inline-block;
  transform: translate3d(0, 110%, 0) rotate(2.5deg);
  transform-origin: left top;
  opacity: 0;
  transition:
    transform 1s var(--e-out) calc(var(--i, 0) * var(--stagger, 55ms)),
    opacity 0.7s var(--e-out) calc(var(--i, 0) * var(--stagger, 55ms));
  will-change: transform, opacity;
}
.is-in .sp-part,
.sp-part.is-in {
  transform: translate3d(0, 0, 0) rotate(0deg);
  opacity: 1;
}
.is-done .sp-part { will-change: auto; }

/* --- Scrub-driven word illumination -------------------------------------- */
/* Used by the pinned statement. reveal.js writes 0→1 into --p on the
   container; each word derives its own threshold from --i / --n. */

.lightup { display: inline; }
.lightup .lw {
  --t: calc(var(--i) / var(--n));
  --lit: clamp(0, calc((var(--p, 0) - var(--t)) * var(--n, 12) * 0.85), 1);
  color: color-mix(in oklab, var(--fg-lo), var(--fg) calc(var(--lit) * 100%));
  transition: color 0.18s linear;
}

/* --- Parallax / scrub transforms ----------------------------------------- */
/* Elements with data-scrub get --p written every frame. These classes turn
   that scalar into a transform. No JS style-writing beyond the one variable. */

[data-scrub] { will-change: transform; }

.par-up   { transform: translate3d(0, calc(var(--p, 0) * -14vh), 0); }
.par-down { transform: translate3d(0, calc(var(--p, 0) * 14vh), 0); }
.par-slow { transform: translate3d(0, calc(var(--p, 0) * -6vh), 0); }

.hero-dissolve {
  transform: scale(calc(1 - var(--p, 0) * 0.12)) translate3d(0, calc(var(--p, 0) * -6vh), 0);
  filter: blur(calc(var(--p, 0) * 16px));
  opacity: calc(1 - var(--p, 0) * 1.25);
}

.rail-track { transform: translate3d(calc(var(--p, 0) * var(--rail-shift, 0px)), 0, 0); }

.draw-line { stroke-dasharray: 1; stroke-dashoffset: calc(1 - var(--p, 0)); }

/* --- Ambient loops ------------------------------------------------------- */

@keyframes drift {
  0%,100% { transform: translate3d(0, 0, 0) scale(1); }
  50%     { transform: translate3d(2%, -3%, 0) scale(1.06); }
}

@keyframes pulse-ring {
  0%   { transform: scale(0.7); opacity: 0.55; }
  70%  { opacity: 0; }
  100% { transform: scale(2.1); opacity: 0; }
}

@keyframes marquee-x {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-50%, 0, 0); }
}

@keyframes scroll-hint {
  0%       { transform: translateY(-90%); opacity: 0; }
  30%, 60% { opacity: 1; }
  100%     { transform: translateY(90%); opacity: 0; }
}

@keyframes shimmer {
  from { background-position: 200% 0; }
  to   { background-position: -200% 0; }
}

/* --- Reduced motion ------------------------------------------------------ */
/* Not a degraded page — a calm one. Everything is present and legible;
   only the movement is removed. */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }

  [data-reveal],
  [data-reveal].is-in {
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
    clip-path: none !important;
  }

  .sp-part { opacity: 1 !important; transform: none !important; }
  .sp-mask { overflow: visible; }

  .lightup .lw { color: var(--fg) !important; }

  .par-up, .par-down, .par-slow,
  .hero-dissolve, .rail-track {
    transform: none !important;
    filter: none !important;
    opacity: 1 !important;
  }

  .draw-line { stroke-dashoffset: 0 !important; }

  .cursor { display: none !important; }
}
