/* Page-to-page motion (page-transitions.js names the parts and picks the
   type). Loaded on every page: the pseudo-elements below are styled by
   whichever page is arriving, so both ends need these rules. */
@view-transition {
  navigation: auto;
}

/* The frame stands in for "the whole page" while a card grows into it or
   shrinks out of it. It only exists for the length of one transition. */
.vt-frame {
  position: fixed;
  inset: 0;
  z-index: 100;
  pointer-events: none;
}

/* Karyll's curves: an emphasized move (a quick start, a long settle) and a
   standard fade. */
:root {
  --vt-emph: cubic-bezier(0.2, 0, 0, 1);
  --vt-fade: cubic-bezier(0.4, 0, 0.2, 1);
}

/* ---- Zoom in: card -> case study ----
   The card grows along the emphasized curve into the hero's place. It fades
   through rather than double-exposing: the card leaves early, showing the
   live hero underneath, and the rest of the page rises a few pixels once
   the move is mostly done. Home fades from under the card in its first
   fifth. */
html:active-view-transition-type(zoom-in) {
  &::view-transition-group(case-frame) {
    animation-duration: 0.64s;
    animation-timing-function: var(--vt-emph);
  }
  &::view-transition-old(case-frame),
  &::view-transition-new(case-frame) {
    height: 100%;
    object-fit: cover;
    object-position: top;
  }
  &::view-transition-old(root) { animation: vt-out 0.22s var(--vt-fade) both; }
  &::view-transition-new(root) { animation: vt-rise 0.46s 0.3s var(--vt-emph) both; }
  /* No hero on screen: the card grows to fill the screen instead and
     dissolves into the page colour (a stand-in frame) as it lands. */
  &::view-transition-old(case-frame) { animation: vt-out 0.25s 0.15s ease both; }
  &::view-transition-new(case-frame) { animation: vt-frame-in 0.6s ease both; }
}
html:active-view-transition-type(to-hero) {
  &::view-transition-old(case-frame) { animation: vt-out 0.3s 0.06s var(--vt-fade) both; }
  &::view-transition-new(case-frame) { animation: none; }
}

/* ---- Zoom out: case study -> home ----
   The same move backwards: the page lifts away first, the hero (or, scrolled
   past it, the page itself) shrinks back into its card, and home fades in
   around it. The card's snapshot only takes over once the box is nearly
   card-sized - otherwise it shows up stretched (a portrait photo card most
   of all). */
html:active-view-transition-type(zoom-out) {
  &::view-transition-group(case-frame) {
    animation-duration: 0.6s;
    animation-timing-function: var(--vt-emph);
  }
  &::view-transition-old(case-frame),
  &::view-transition-new(case-frame) {
    height: 100%;
    object-fit: cover;
    object-position: top;
  }
  &::view-transition-old(case-frame) { animation: vt-out 0.22s 0.2s ease both; }
  &::view-transition-new(case-frame) { animation: vt-in 0.22s 0.16s ease both; }
  &::view-transition-old(root) { animation: vt-lift 0.18s cubic-bezier(0.3, 0, 0.8, 0.15) both; }
  &::view-transition-new(root) { animation: vt-in 0.32s 0.06s var(--vt-emph) both; }
}

/* Behind the snapshots: the arriving page's own colour (set by
   page-transitions.js), so a gap between the two pages never shows the
   browser's bare white canvas. */
::view-transition { background: var(--vt-bg, transparent); }

/* ---- Next / previous: a camera pan ----
   The two pages are artboards side by side on a dotted canvas. The camera
   eases back as it travels and settles in as it arrives - the pair scales
   down and up again while each page slides across - so it's always two
   whole pages with a gap between them, never one fading through the
   other. The top bar (close, Contents) and the nav stay put, like the
   chrome of the canvas. */
html:active-view-transition-type(next),
html:active-view-transition-type(prev) {
  &::view-transition {
    background:
      radial-gradient(circle, rgb(0 0 0 / 0.16) 1px, transparent 1.5px) 0 0 / 22px 22px,
      color-mix(in srgb, var(--vt-bg, #fdfbf8) 93%, #000);
  }
  &::view-transition-image-pair(root) { animation: vt-camera 0.62s both; }
  &::view-transition-old(root),
  &::view-transition-new(root) { box-shadow: 0 0 0 1px rgb(0 0 0 / 0.06), 0 16px 48px rgb(0 0 0 / 0.14); }
  &::view-transition-old(root) { animation: vt-pan-out 0.62s cubic-bezier(0.65, 0, 0.35, 1) both; }
  &::view-transition-new(root) { animation: vt-pan-in 0.62s cubic-bezier(0.65, 0, 0.35, 1) both; }
  &::view-transition-group(page-topbar) { animation-duration: 0.62s; }
  /* Only one side has the bar (Showcase draws its own): pinned, it would
     hang over the other page, so it leaves early or arrives late instead. */
  &::view-transition-old(page-topbar):only-child { animation: vt-out 0.18s ease-in both; }
  &::view-transition-new(page-topbar):only-child { animation: vt-in 0.24s 0.42s ease-out both; }
  /* The pill springs to its new width; the name slides the way you're
     going, softening as it leaves. */
  &::view-transition-group(site-nav) {
    animation-duration: 0.52s;
    animation-timing-function: cubic-bezier(0.32, 1.25, 0.5, 1);
  }
  &::view-transition-old(site-nav-label) { animation: vt-label-slide-out 0.22s ease-in both; }
  &::view-transition-new(site-nav-label) { animation: vt-label-slide-in 0.36s 0.05s cubic-bezier(0.2, 0.8, 0.2, 1) both; }
}
html:active-view-transition-type(next) { --vt-dir: 1; }
html:active-view-transition-type(prev) { --vt-dir: -1; }

/* ---- Nav pill: the page name rolls up to the new one ---- */
::view-transition-old(site-nav-label) { animation: vt-label-out 0.22s ease-in both; }
::view-transition-new(site-nav-label) { animation: vt-label-in 0.4s 0.12s cubic-bezier(0.16, 1, 0.3, 1) both; }
::view-transition-old(site-nav-label),
::view-transition-new(site-nav-label) { height: 100%; width: auto; }
@keyframes vt-label-out { to { opacity: 0; translate: 0 -10px; } }
@keyframes vt-label-in { from { opacity: 0; translate: 0 10px; } }

@keyframes vt-in { from { opacity: 0; } }
@keyframes vt-out { to { opacity: 0; } }
@keyframes vt-rise { from { opacity: 0; translate: 0 14px; } }
@keyframes vt-frame-in {
  0% { opacity: 0; }
  45% { opacity: 1; }
  100% { opacity: 0; }
}
@keyframes vt-lift { to { opacity: 0; translate: 0 -8px; } }
@keyframes vt-camera {
  0% { scale: 1; animation-timing-function: cubic-bezier(0.4, 0, 0.6, 1); }
  45% { scale: 0.9; animation-timing-function: cubic-bezier(0.2, 0, 0, 1); }
  100% { scale: 1; }
}
@keyframes vt-pan-out { to { translate: calc(var(--vt-dir) * (-100% - 48px)) 0; } }
@keyframes vt-pan-in { from { translate: calc(var(--vt-dir) * (100% + 48px)) 0; } }
@keyframes vt-label-slide-out { to { opacity: 0; translate: calc(var(--vt-dir) * -14px) 0; filter: blur(3px); } }
@keyframes vt-label-slide-in { from { opacity: 0; translate: calc(var(--vt-dir) * 14px) 0; filter: blur(3px); } }

@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*),
  ::view-transition-image-pair(*),
  ::view-transition-old(*),
  ::view-transition-new(*) { animation: none !important; }
}
