/* ── DBM Global · motion layer (alt version) ──────────────────────
   Loaded only by alt.html. The base build stays untouched so the two
   can be compared side by side.

   Vocabulary borrowed from the GISI reference:
   · smooth inertial scrolling
   · headlines split into words that rise out of a mask
   · blocks fade and rise ~40px over roughly 1.1s, children staggered
   ------------------------------------------------------------------ */

:root {
  --m-dur: 1150ms;
  --m-ease: cubic-bezier(.16, .84, .24, 1);
  --m-rise: 42px;
}

/* Elements are hidden only once the motion layer has claimed them, so the
   page is never blank if the script fails to run. */
.m-ready [data-m-rise] {
  opacity: 0;
  transform: translate3d(0, var(--m-rise), 0);
  transition:
    opacity var(--m-dur) var(--m-ease) var(--m-delay, 0ms),
    transform var(--m-dur) var(--m-ease) var(--m-delay, 0ms);
  will-change: opacity, transform;
}
.m-ready [data-m-rise].is-in {
  opacity: 1;
  transform: none;
}

/* Word masks: the mask clips, the inner span does the moving. The extra
   bottom padding and matching negative margin keep descenders off the
   clip edge, which is the usual giveaway that text is masked. */
.m-word {
  display: inline-block;
  overflow: hidden;
  vertical-align: bottom;
  padding-bottom: .14em;
  margin-bottom: -.14em;
}
.m-word > span {
  display: inline-block;
  transform: translate3d(0, 110%, 0);
  transition: transform var(--m-dur) var(--m-ease) var(--m-delay, 0ms);
  will-change: transform;
}
.m-split.is-in .m-word > span { transform: none; }

/* Leaving is the other half of the transition. The outgoing words lift up out of
   their masks and the incoming ones rise in from below, so one line hands over to
   the next instead of the old copy simply vanishing. The exit staggers far tighter
   than the entrance — it has to clear before the new text arrives. */
.m-split.is-out .m-word > span {
  transform: translate3d(0, -115%, 0);
  transition: transform 300ms cubic-bezier(.6, 0, .78, .5) var(--m-out, 0ms);
}

/* Lines, not words, for running copy: at this length a per-word stagger reads as
   fussy. Each visual line gets its own mask and moves as one block. */
.m-line { display: block; overflow: hidden; padding-bottom: .06em; margin-bottom: -.06em; }
.m-line > span {
  display: block;
  transform: translate3d(0, 110%, 0);
  /* its own curve rather than --m-ease: that one decelerates hard and front-loads
     the travel, which reads as fast however long the duration is */
  transition: transform 1250ms cubic-bezier(.32, .06, .16, 1) var(--m-delay, 0ms);
  will-change: transform;
}
.m-split.is-in .m-line > span { transform: none; }
.m-split.is-out .m-line > span {
  transform: translate3d(0, -115%, 0);
  transition: transform 520ms cubic-bezier(.5, 0, .7, .4) var(--m-out, 0ms);
}
@media (prefers-reduced-motion: reduce) {
  .m-line > span { transform: none; transition: none; }
}

/* Scroll-linked fade for the standing section labels, so they lift in and
   settle back out as they cross the viewport rather than snapping. */
[data-m-fade] { opacity: var(--m-op, 1); }

@media (prefers-reduced-motion: reduce) {
  .m-ready [data-m-rise] { opacity: 1; transform: none; transition: none; }
  .m-word > span { transform: none; transition: none; }
  [data-m-fade] { opacity: 1 !important; }
}
