/* Everything that moves is driven by one number per scene: --p, the scroll
   progress of that scene from 0 to 1, written by assets/js/site/scenes.js. Phases
   are cut out of it with clamp(), so no two rooms open the same way and no
   element needs its own timer.

   Reduced motion: scenes.js pins --p at 1 and stops the loop, so every mask is
   already open and every chapter is simply there. The rules below then remove
   the remaining travel and shorten the crossfades. */
.scene { --p: 1; }              /* no JavaScript: every mask is already open */
html.js .scene { --p: 0; }      /* scripted: assets/js/site/scenes.js drives it */

/* entrances used by the static chapters, one-shot, via core/reveal.js */
html:not(.js) [data-reveal] { opacity: 1; transform: none; }
html:not(.js) [data-reveal="wipe"] > * { clip-path: none; }
html.js [data-reveal] { opacity: 0; transition: opacity 1.1s var(--ease), transform 1.1s var(--slow); }
[data-reveal="up"]    { transform: translateY(1.6rem); }
[data-reveal="right"] { transform: translateX(-1.6rem); }
/* The wipe clips a CHILD, never the observed element itself: a clip-path that
   collapses the box collapses its intersection rectangle too, and the observer
   then never reports the element as visible — so it would stay hidden forever. */
[data-reveal="wipe"] > * { clip-path: inset(0 100% 0 0); transition: clip-path 1.3s var(--slow); }
html.js [data-reveal].is-in { opacity: 1; transform: none; }
html.js [data-reveal="wipe"].is-in > * { clip-path: inset(0 0 0 0); }
[data-reveal][style*="--d"] { transition-delay: var(--d, 0s); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .18s !important;
    scroll-behavior: auto !important;
  }
  html.js [data-reveal] { opacity: 1; transform: none; }
  html.js [data-reveal="wipe"] > * { clip-path: none; }
  html.js .scene { --p: 1; }
}
