/* Praxus motion system v1 (2026-09-10). One drop-in for every page except the home hero.
   Load AFTER focus.css / e.css / page-e.css:   <link rel="stylesheet" href="/assets/css/motion.css">
   Pair with /assets/js/motion.js (defer). The script adds html.motion-v2; nothing here applies without it,
   so a page without JavaScript shows everything at rest.

   Rules of the system
   1. Text reveals once. A block rises 14px and settles in .55s the moment it enters the bottom of the screen, then never fades again.
      Photos, rules and clip reveals keep the scroll-drawn feel from focus.css (that is imagery, not reading).
   2. One easing pair, three durations. --m-ease for anything entering or lifting, --m-ease-io for state changes.
   3. One link language: a label and a long thin arrow. The line extends on hover. Headlines stay ink; sky is for labels only.
   4. Photos lift 1.03 and warm by one grade step on hover, over --m-slow. The navy button wipe (approved) stays on the tokens.
   5. Focus-visible is the hover state plus a 2px ring in the current colour.
   6. Page to page: cross-document view transitions. The header holds still; the body crossfades.
   7. Reduced motion: finished states, no transitions, posters instead of video (v2.js), native scroll (focus.js). */

:root{--m-ease:cubic-bezier(.22,1,.36,1);--m-ease-io:cubic-bezier(.65,0,.35,1);--m-fast:.25s;--m-base:.55s;--m-slow:.9s;--m-rise:14px;--m-stagger:60ms;--m-delay:0ms}

/* 1. Reveals ------------------------------------------------------------- */
html.motion-v2 body [data-scrub]>*,html.motion-v2 body [data-reveal]>*,html.motion-v2 body .rv{opacity:1;transform:none;transition:opacity var(--m-base) var(--m-ease),transform var(--m-base) var(--m-ease);transition-delay:var(--m-delay)}
html.motion-v2 body [data-scrub]:not(.is-in)>*,html.motion-v2 body [data-reveal]:not(.is-in)>*,html.motion-v2 body .rv:not(.is-in){opacity:0;transform:translateY(var(--m-rise))}
html.motion-v2 body [data-scrub].is-in>*,html.motion-v2 body [data-reveal].is-in>*,html.motion-v2 body .rv.is-in{opacity:1;transform:none}
html.motion-v2 body [data-scrub]>*:nth-child(2),html.motion-v2 body [data-reveal]>*:nth-child(2){transition-delay:calc(var(--m-delay) + var(--m-stagger))}
html.motion-v2 body [data-scrub]>*:nth-child(3),html.motion-v2 body [data-reveal]>*:nth-child(3){transition-delay:calc(var(--m-delay) + var(--m-stagger) * 2)}
html.motion-v2 body [data-scrub]>*:nth-child(4),html.motion-v2 body [data-reveal]>*:nth-child(4){transition-delay:calc(var(--m-delay) + var(--m-stagger) * 3)}
html.motion-v2 body [data-scrub]>*:nth-child(5),html.motion-v2 body [data-reveal]>*:nth-child(5){transition-delay:calc(var(--m-delay) + var(--m-stagger) * 4)}
html.motion-v2 body [data-scrub]>*:nth-child(n+6),html.motion-v2 body [data-reveal]>*:nth-child(n+6){transition-delay:calc(var(--m-delay) + var(--m-stagger) * 5)}
/* imagery inside a reveal group keeps its own scroll-drawn reveal */
html.motion-v2 body [data-scrub]>.fx-frame,html.motion-v2 body [data-reveal]>.fx-frame{opacity:1;transform:none;transition:none}
/* the bracket label opens once with its block instead of tracking the scroll position */
html.motion-v2 body .v3-e .eyebrow--ticks{--o:0;--t:0;opacity:1;transform:none;transition:gap var(--m-slow) var(--m-ease) var(--m-delay)}
html.motion-v2 body .v3-e .eyebrow--ticks .eyebrow__t{transition:max-width var(--m-slow) var(--m-ease) var(--m-delay),opacity var(--m-base) var(--m-ease) calc(var(--m-delay) + .18s)}
html.motion-v2 body .v3-e .is-in .eyebrow--ticks,html.motion-v2 body .v3-e .eyebrow--ticks.is-in{--o:1;--t:1}
@media (hover:none) and (pointer:coarse){html.motion-v2 body .v3-e .eyebrow--ticks .eyebrow__t{max-width:none;opacity:1}}

/* 2. One easing pair on what already moves --------------------------------- */
html.motion-v2 .btn-e{transition:color var(--m-base) var(--m-ease),border-color var(--m-base) var(--m-ease)}
html.motion-v2 .btn-e::after{transition:transform var(--m-base) var(--m-ease)}
html.motion-v2 .btn-br::before,html.motion-v2 .btn-br::after{transition:transform var(--m-fast) var(--m-ease)}
html.motion-v2 .story__m{transition:opacity var(--m-slow) var(--m-ease)}
html.motion-v2 .hero-focus .nav__links>a::after,html.motion-v2 .hero-focus .nav__dd-btn::after,html.motion-v2 .hero-focus .nav__mobile>a::after,html.motion-v2 .hero-focus .nav__row-name::after{transition:transform var(--m-base) var(--m-ease)}
html.motion-v2 .hero-focus .nav__panel{transition:opacity var(--m-fast) var(--m-ease-io),transform var(--m-base) var(--m-ease),visibility 0s var(--m-fast)}
html.motion-v2 .hero-focus .nav--dd-open .nav__panel{transition:opacity var(--m-fast) var(--m-ease),transform var(--m-base) var(--m-ease),visibility 0s}
html.motion-v2 .nav__panel-inner>*{transition:opacity var(--m-base) var(--m-ease),transform var(--m-base) var(--m-ease)}
html.motion-v2 .hero-focus .nav__dd-btn::before{transition:transform var(--m-base) var(--m-ease)}
html.motion-v2 .why-e__card{transition:background var(--m-base) var(--m-ease),border-color var(--m-base) var(--m-ease)}

/* 3. One link language: label + long thin arrow ----------------------------- */
html.motion-v2 .lnk,html.motion-v2 .study-link,html.motion-v2 .nav__row-more,html.motion-v2 .what-w__link,html.motion-v2 .res-e__more,html.motion-v2 .res-i__more{display:inline-flex;align-items:center;gap:14px;text-decoration:none;border-bottom:0;padding-bottom:0}
html.motion-v2 .lnk::before,html.motion-v2 .study-link::before,html.motion-v2 .nav__row-more::before,html.motion-v2 .what-w__link::before,html.motion-v2 .res-e__more::before,html.motion-v2 .res-i__more::before{content:"";order:2;display:block;width:40px;height:1px;flex:none;background:currentColor;transition:width var(--m-base) var(--m-ease)}
html.motion-v2 .lnk::after,html.motion-v2 .study-link::after,html.motion-v2 .nav__row-more::after,html.motion-v2 .what-w__link::after,html.motion-v2 .res-e__more::after,html.motion-v2 .res-i__more::after{content:"";order:3;display:block;position:static;width:7px;height:7px;flex:none;margin-left:-19px;border-top:1px solid currentColor;border-right:1px solid currentColor;background:none;opacity:1;transform:rotate(45deg);transition:none}
html.motion-v2 .lnk>span[aria-hidden],html.motion-v2 .study-link>span[aria-hidden],html.motion-v2 .nav__row-more>span[aria-hidden]{display:none}
html.motion-v2 .lnk:hover::before,html.motion-v2 .lnk:focus-visible::before,html.motion-v2 .study-link:hover::before,html.motion-v2 .study-link:focus-visible::before,html.motion-v2 .nav__row:hover .nav__row-more::before,html.motion-v2 .nav__row:focus-visible .nav__row-more::before,html.motion-v2 .what-w3__item:hover .what-w__link::before,html.motion-v2 .res-e__card:hover .res-e__more::before,html.motion-v2 .research-row:hover .study-link::before,html.motion-v2 .res-i__card:hover .res-i__more::before{width:56px}
html.motion-v2 .research-index .study-link{padding-bottom:0;border-bottom:0}
/* headlines never change colour on hover; the arrow and the photo carry the hover */
html.motion-v2 .page-e .note:hover .note__name,html.motion-v2 .page-e .jr__feat:hover .note__name,html.motion-v2 .res-i__name a:hover,html.motion-v2 .res-i__card:hover h3,html.motion-v2 .res-l__row h3 a:hover,html.motion-v2 .res-g__panel:hover .res-g__meta h2 a,html.motion-v2 .v3-e .what-w3__item:hover h3,html.motion-v2 .v3-e .what-e__item:hover h3,html.motion-v2 .research-index a:hover{color:inherit}
html.motion-v2 .research-index .research-row h2 a{text-decoration:underline;text-decoration-color:transparent;text-decoration-thickness:1px;text-underline-offset:.16em;transition:text-decoration-color var(--m-base) var(--m-ease)}
html.motion-v2 .research-index .research-row:hover h2 a,html.motion-v2 .research-index .research-row h2 a:focus-visible{text-decoration-color:currentColor}
html.motion-v2 .research-index .research-filter{transition:color var(--m-fast) var(--m-ease),border-color var(--m-fast) var(--m-ease)}
html.motion-v2 .research-index .research-filter:hover{color:#0b1f3a}

/* 4. Photos and figures lift on hover; the grade warms one step ------------- */
html.motion-v2 .fx-clip img,html.motion-v2 .res-i__fig img,html.motion-v2 .res-g__fig img,html.motion-v2 .note__fig img,html.motion-v2 .tile__fig img,html.motion-v2 .prac__panel img{transition:transform var(--m-slow) var(--m-ease),filter var(--m-slow) var(--m-ease)}
html.motion-v2 .v3-e .fx-clip::after,html.motion-v2 .res-i__fig::after,html.motion-v2 .res-g__fig::after{transition:opacity var(--m-slow) var(--m-ease)}
html.motion-v2 a:hover .fx-clip img,html.motion-v2 .res-i__card:hover .res-i__fig img,html.motion-v2 .res-g__panel:hover .res-g__fig img,html.motion-v2 .what-w3__item:hover .fx-clip img,html.motion-v2 .res-e__card:hover .fx-clip img,html.motion-v2 .what-e__item:hover .fx-clip img{transform:scale(1.03)}
html.motion-v2 .v3-e a:hover .fx-clip::after,html.motion-v2 .v3-e .what-w3__item:hover .fx-clip::after,html.motion-v2 .v3-e .res-e__card:hover .fx-clip::after,html.motion-v2 .v3-e .what-e__item:hover .fx-clip::after,html.motion-v2 .res-i__card:hover .res-i__fig::after,html.motion-v2 .res-g__panel:hover .res-g__fig::after{opacity:.42}
html.motion-v2 .research-index .research-figure canvas{transition:transform var(--m-slow) var(--m-ease)}
html.motion-v2 .research-index .research-row:hover .research-figure canvas{transform:scale(1.02)}

/* 5. Focus is the hover state plus a ring --------------------------------- */
html.motion-v2 a:focus-visible,html.motion-v2 button:focus-visible,html.motion-v2 [tabindex]:focus-visible{outline:2px solid currentColor;outline-offset:4px}
html.motion-v2 .btn-e:focus-visible{outline-offset:3px}
html.motion-v2 .research-index a:focus-visible,html.motion-v2 .research-index button:focus-visible{outline-color:currentColor;outline-offset:4px}

/* 6. Page to page: the header holds still, the body crossfades ------------- */
@view-transition{navigation:auto}
::view-transition-old(root){animation:m-page-out .22s var(--m-ease-io) both}
::view-transition-new(root){animation:m-page-in .38s var(--m-ease) both}
html.motion-v2 .nav{view-transition-name:site-nav}
::view-transition-group(site-nav){animation-duration:0s}
::view-transition-old(site-nav){animation:none;opacity:0}
::view-transition-new(site-nav){animation:none;opacity:1}
@keyframes m-page-out{to{opacity:0}}
@keyframes m-page-in{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}

/* 6b. Rails draw on page open (adopted from web-r2-fable-why): the two vertical hairlines grow from the top once, then sit still */
html.motion-v2 .page-e__open--rails .page-e__in::before,html.motion-v2 .page-e__open--rails .page-e__in::after,html.motion-v2 .research-index .study-head .study-rail::before,html.motion-v2 .research-index .study-head .study-rail::after{transform-origin:top;animation:m-rail .9s var(--m-ease) .1s both}
@keyframes m-rail{from{transform:scaleY(0)}to{transform:none}}

/* 7. Reduced motion: everything at rest, no transitions ---------------------- */
@media (prefers-reduced-motion:reduce){
  html.motion-v2 body [data-scrub]>*,html.motion-v2 body [data-reveal]>*,html.motion-v2 body .rv{opacity:1;transform:none;transition:none}
  html.motion-v2 body .v3-e .eyebrow--ticks{--o:1;--t:1;transition:none}
  html.motion-v2 body .v3-e .eyebrow--ticks .eyebrow__t{transition:none}
  html.motion-v2 .lnk::before,html.motion-v2 .study-link::before,html.motion-v2 .nav__row-more::before,html.motion-v2 .what-w__link::before,html.motion-v2 .res-e__more::before,html.motion-v2 .res-i__more::before,html.motion-v2 .fx-clip img,html.motion-v2 .res-i__fig img,html.motion-v2 .res-g__fig img,html.motion-v2 .v3-e .fx-clip::after,html.motion-v2 .research-index .research-figure,html.motion-v2 .research-index .research-figure canvas,html.motion-v2 .research-index .research-row h2 a,html.motion-v2 .story__m,html.motion-v2 .btn-e,html.motion-v2 .btn-e::after{transition:none}
  html.motion-v2 a:hover .fx-clip img,html.motion-v2 .research-index .research-row:hover .research-figure canvas{transform:none}
  @view-transition{navigation:none}
}
