/* =====================================================================
   Scroll reveal — shared by every page.

   A section gets .is-in when it scrolls into view; everything tagged
   inside it then transitions from its resting offset on its own delay.
   Tagging is done in JS (reveal.js) so the markup does not have to
   carry a class on every element.

   Five variants, because one direction for an entire section reads as a
   single sheet sliding up:

     .r-up    rise         copy, headings, cards, labels
     .r-z     scale        media, icon plates, 3D objects
     .r-l     from left    rails, rules, arrows
     .r-r     from right   fields, side panels
     .r-fade  opacity only anything that already owns a keyframe
                           transform — a transition transform loses to a
                           running animation, so a rise on those would
                           silently do nothing

   --d is the element's delay. --o carries a resting opacity for things
   that are deliberately not fully opaque, so the reveal lands on that
   value rather than snapping to 1.
   ===================================================================== */

.r-up, .r-z, .r-l, .r-r, .r-fade { transition-delay: var(--d, 0ms); }

.r-up {
  opacity: 0; transform: translateY(26px);
  transition-property: opacity, transform;
  transition-duration: 800ms, 900ms;
  transition-timing-function: ease-out, cubic-bezier(.22, 1, .28, 1);
}
.r-z {
  opacity: 0; transform: scale(0.86);
  transition-property: opacity, transform;
  transition-duration: 760ms, 860ms;
  transition-timing-function: ease-out, cubic-bezier(.22, 1, .28, 1);
}
.r-l {
  opacity: 0; transform: translateX(-34px);
  transition-property: opacity, transform;
  transition-duration: 760ms, 860ms;
  transition-timing-function: ease-out, cubic-bezier(.22, 1, .28, 1);
}
.r-r {
  opacity: 0; transform: translateX(34px);
  transition-property: opacity, transform;
  transition-duration: 760ms, 860ms;
  transition-timing-function: ease-out, cubic-bezier(.22, 1, .28, 1);
}
.r-fade {
  opacity: 0;
  transition-property: opacity;
  transition-duration: 820ms;
  transition-timing-function: ease-out;
}

.is-in .r-up,
.is-in .r-z,
.is-in .r-l,
.is-in .r-r,
.is-in .r-fade { opacity: var(--o, 1); }

.is-in .r-up,
.is-in .r-z,
.is-in .r-l,
.is-in .r-r { transform: none; }


/* ---------------------------------------------------------------------
   Word-level reveal for headings. Each word sits in its own mask and
   rises out of it on a stagger.
   --------------------------------------------------------------------- */
.r-wm {
  display: inline-block; overflow: hidden;
  vertical-align: bottom; padding-bottom: 0.08em;
}
.r-w {
  display: inline-block;
  transform: translateY(115%);
  transition: transform 820ms cubic-bezier(.22, 1, .28, 1);
  transition-delay: var(--d, 0ms);
}
.is-in .r-w { transform: translateY(0); }


/* ---------------------------------------------------------------------
   Off-screen sections stop animating.

   Pages here run a lot of looping decoration — drifting grids, marquees,
   floating objects, orbits, glyph fields — and all of it used to tick at
   once whether or not anything was on screen. .r-idle parks a section
   that is not near the viewport. Animations only; transitions are left
   alone so hover still behaves normally.
   --------------------------------------------------------------------- */
.r-idle,
.r-idle::before,
.r-idle::after,
.r-idle *,
.r-idle *::before,
.r-idle *::after { animation-play-state: paused !important; }


@media (prefers-reduced-motion: reduce) {
  .r-up, .r-z, .r-l, .r-r, .r-fade {
    opacity: 1; transform: none; transition: none;
  }
  .r-w { transform: none; transition: none; }
}
