/* =============================================================================
   hi-vt.css — cross-document View Transitions.

   WHY A STYLESHEET AND NOT hi-motion.js
   `@view-transition { navigation: auto; }` opts the DOCUMENT in, and the
   browser has to know that BEFORE the outbound navigation starts. A deferred
   script that injects the rule at DOMContentLoaded loses the race on a fast
   click, and loses entirely for a reader with JS off. It is also a CSS
   feature end to end — there is no JS to write. So it ships as a tiny static
   sheet in <head>.

   WHY NOT hi-tokens.css
   hi-tokens.css is values-only by charter: custom properties, nothing that
   paints or behaves. An at-rule that changes navigation behaviour does not
   belong there. This sheet CONSUMES those tokens (--mo-base / --mo-slow /
   --mo-ease) and carries literal fallbacks so it is correct on its own.

   PROGRESSIVE BY CONSTRUCTION
   Browsers without support ignore the at-rule and simply navigate. Same-origin
   only — that is the spec's own limit, not something we enforce. No polyfill.
   ============================================================================= */

@view-transition { navigation: auto; }

/* ---------------------------------------------------------------- the base
   The whole page cross-fades at --mo-base. Anything carrying an explicit
   view-transition-name is lifted out of this group and animated on its own. */
::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: var(--mo-base, 240ms);
  animation-timing-function: var(--mo-ease, cubic-bezier(.22, .61, .36, 1));
}

/* ------------------------------------------------------------ the masthead
   The single move that makes this read as an app rather than a page load:
   the chrome holds still while the content underneath changes. Every page
   type gets the SAME name so the old and new mastheads pair up — the
   research-desk routes on nav.mnav, the generated routes on header.site-nav.
   No page carries both (verified across every hand-built route). */
header.site-nav,
nav.mnav {
  view-transition-name: masthead;
}

/* A held-still element still gets an old/new pair; make it a hard cut so the
   chrome does not ghost or double up during the fade. */
::view-transition-old(masthead),
::view-transition-new(masthead) {
  animation: none;
  mix-blend-mode: normal;
}

/* ----------------------------------------------------------- the morphs
   Individual `view-transition-name: mug-<nhlId>` / `crest-<TRI>` values are
   set inline by scripts/generate-seo-pages.js on the paired elements (a
   directory face and the dossier hero mug; a standings/team-directory crest
   and the team-hub hero crest). A name must be unique per page — a duplicate
   silently kills the ENTIRE transition — so writePage() runs a dedupe pass
   over every emitted document and scripts/check-vt-names.js audits the
   built output.

   Wildcards are not available in `::view-transition-group()`, so the shared
   timing rides on the group's default and is set here via the whole
   pseudo-tree instead: `*` matches every named group including root, and the
   root override above wins for the cross-fade because it comes first only in
   specificity terms — so re-state root after. */
::view-transition-group(*) {
  animation-duration: var(--mo-slow, 400ms);
  animation-timing-function: var(--mo-ease, cubic-bezier(.22, .61, .36, 1));
}
::view-transition-group(root) {
  animation-duration: var(--mo-base, 240ms);
}

/* Morphing images should scale rather than squash while the box changes. */
::view-transition-old(*),
::view-transition-new(*) {
  object-fit: cover;
}

/* ------------------------------------------------------------ the off switch
   Reduced motion turns the navigation transition off entirely; the reader
   gets an ordinary, instant page load. */
@media (prefers-reduced-motion: reduce) {
  @view-transition { navigation: none; }
}
