/* ============================================================
   Mikewavs — motion
   Cross-page behaviour: navigation transitions, entrance
   choreography, and scroll reveals.

   Loaded by every page. Per-component motion (the hub's row
   hover, the marquee rails) stays with its component; what
   lives here is anything that spans pages or is shared.

   Tokens come from tokens.css. Nothing in this file hardcodes
   a duration or a curve.
   ============================================================ */

/* ------------------------------------------------------------
   1. Cross-document view transitions

   The hub and the interior pages currently read as two separate
   sites, partly because navigation between them is a hard cut.
   This is the whole fix, and it degrades to nothing on engines
   that don't support it — no polyfill, no JS.
   ------------------------------------------------------------ */

@view-transition {
  navigation: auto;
}

/* The logo is present in the header of every page, so naming it makes the
   browser morph the one element between documents instead of cross-fading
   two copies of it. It is the anchor that makes the two page types feel
   like one site.

   The name must be unique per page — two elements sharing a
   view-transition-name in the same document abort the transition. There is
   exactly one logo per page here, so a plain class selector is safe. */
.mw-logo-mark {
  view-transition-name: mw-logo;
}

::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: var(--mw-dur-slow);
  animation-timing-function: var(--mw-ease-out);
}

/* Let the morphing logo run slightly longer than the page cross-fade, so the
   eye has something continuous to hold while the content swaps underneath. */
::view-transition-group(mw-logo) {
  animation-duration: var(--mw-dur-slow);
  animation-timing-function: var(--mw-ease-out);
}

/* ------------------------------------------------------------
   2. Entrance choreography

   Sequenced reveal for first paint. Elements opt in with
   .mw-rise and set --i to their position in the sequence.

   Deliberately capped: eight items at 45ms finishes in ~360ms
   after the 120ms lead-in, so the whole thing is done inside
   half a second. Past roughly that point a staggered entrance
   stops reading as choreography and starts reading as a page
   that is slow to load.
   ------------------------------------------------------------ */

@keyframes mw-rise {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: none; }
}

.mw-rise {
  animation: mw-rise var(--mw-dur-slow) var(--mw-ease-out) both;
  animation-delay: calc(var(--mw-lead, 0ms) + var(--i, 0) * var(--mw-stagger));
}

/* ------------------------------------------------------------
   3. Scroll reveals (interior pages)

   Scroll-driven animations, so there is no IntersectionObserver,
   no library, and nothing to run on the main thread. Where the
   API is missing the element is simply visible — which is why
   the `to` state is the resting state and the rule sits inside
   @supports rather than applying the hidden state unguarded.

   Without that guard, an engine that parses `animation-timeline`
   as invalid would keep the element at opacity 0 forever.
   ------------------------------------------------------------ */

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .mw-reveal {
      animation: mw-rise auto var(--mw-ease-out) both;
      animation-timeline: view();
      /* Start as the element's top edge enters the viewport, finish by the
         time it is a fifth of the way up. Tying the range to the element
         rather than the scroll position keeps long and short sections
         behaving the same. */
      animation-range: entry 0% cover 20%;
    }
  }
}

/* ------------------------------------------------------------
   4. Reduced motion

   Durations are already collapsed to 1ms in tokens.css, so
   nothing here needs to repeat that. What is left is removing
   the transforms themselves — a 12px jump completed in 1ms is
   still a jump, and scroll-linked movement is exactly what this
   setting exists to suppress.
   ------------------------------------------------------------ */

@media (prefers-reduced-motion: reduce) {
  .mw-rise,
  .mw-reveal {
    animation: none;
    opacity: 1;
    transform: none;
  }

  /* A cross-document morph is motion the user has asked not to see. Cutting
     the animation leaves the navigation itself working, just instant. */
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) {
    animation: none !important;
  }
}
