/* Shared scroll motion for the home, Vision, Current Steps and Updates pages.
   Same feel as the recruitment page (Colton, 2026-09-29/30): things arrive as
   you scroll, ONCE, on scroll into view, never looping or replaying (the brand
   rule in canon/brand-visual.md §6). Same distances, durations and curve as the
   recruitment page. Used with /assets/motion.js.

   The hidden starting state exists only while JavaScript runs (html.js), so a
   page without JavaScript shows everything. Reduced motion gets the finished
   page with nothing moving.

   Arrivals are one-time CSS animations rather than transitions, so an element's
   own hover transition (the cards lift on hover) keeps working once it has
   arrived. */

:root { --ease: cubic-bezier(.2,.7,.2,1); }

@keyframes rv-up    { from { opacity: 0; transform: translateY(34px); } to { opacity: 1; transform: none; } }
@keyframes rv-up-sm { from { opacity: 0; transform: translateY(26px); } to { opacity: 1; transform: none; } }

/* .rv: arrives on its own. --d on the element delays it.
   Nothing with live text in it ever zooms. The diagrams used to grow from 96.5%
   as they rose, and the Vision diagram's "MEDIA" jumped sideways and flickered
   (Colton, 2026-09-30): a zoom slides text sideways and makes the browser redraw
   it at new sizes mid-motion. A straight rise moves nothing sideways. */
.js .rv:not(.in) { opacity: 0; }
.js .rv.in { animation: rv-up .9s var(--ease) backwards; animation-delay: var(--d, 0s); }

/* .rv-group: its children arrive one after another. */
.js .rv-group:not(.in) > * { opacity: 0; }
.js .rv-group.in > * { animation: rv-up-sm .75s var(--ease) backwards; animation-delay: calc(var(--i, 0) * 90ms + var(--d, 0s)); }

/* .rv-settle: images inside settle from a slight zoom as they arrive, like the
   film stills on the recruitment page. */
.js .rv-settle img { transition: transform 1.6s var(--ease); }
.js .rv-settle:not(.in) img { transform: scale(1.12); }

/* .rv-track: an accent line draws along the top edge while the items arrive,
   so a numbered row reads as a sequence. */
.rv-track { position: relative; }
.rv-track::before { content: ""; position: absolute; left: 0; right: 0; top: -1px; height: 2px; background: var(--accent, #5D7A99);
                    transform-origin: left center; pointer-events: none; }
.js .rv-track:not(.in)::before { transform: scaleX(0); }
.js .rv-track.in::before { transition: transform 1.4s var(--ease) .15s; }

/* The mascot. Two copies of his unchanged artwork: one clipped to the lantern,
   one with the lantern clipped out (the same cut as the recruitment countdown).
   When he comes into view the lantern swings once, like a pendulum coming to
   rest, and its light comes on. */
.mascot { display: block; }
.mascot svg { display: block; width: 100%; height: auto; overflow: visible; }
.mascot .lantern { transform-box: view-box; transform-origin: 132px 228px; }
.mascot .core { mix-blend-mode: screen; opacity: .75; }
.js .mascot:not(.in) .core { opacity: 0; }
.js .mascot.in .core { transition: opacity 1.2s ease .5s; }
.js .mascot.in .lantern { animation: sway-once 3.2s ease-in-out .35s both; }
@keyframes sway-once {
  0% { transform: rotate(0); }
  16% { transform: rotate(7deg); }
  38% { transform: rotate(-5deg); }
  58% { transform: rotate(3deg); }
  78% { transform: rotate(-1.2deg); }
  100% { transform: rotate(0); }
}

@media (prefers-reduced-motion: reduce) {
  .js .rv, .js .rv-group > *, .js .rv-settle img, .js .rv-track::before, .js .mascot .lantern {
    opacity: 1 !important; transform: none !important; animation: none !important; transition: none !important;
  }
  .js .mascot .core { opacity: .75 !important; transition: none !important; }
}
