/* ---------------------------------------------------------------------------
   transition.css — cross-document page transitions.

   Not Barba.js. Barba v1 is officially deprecated and unsupported, and it
   solves a problem we do not have: it intercepts the click, fetches the
   next page, and swaps the DOM so the transition can run without a
   reload. On a self-hosted static site behind Cloudflare that buys one
   thing — an animated handover — at the cost of duplicating what the
   browser already does well, and it breaks progressive enhancement,
   scroll restoration, and every link that a crawler or a middle-click
   depends on.

   The platform does this natively now: `@view-transition { navigation:
   auto }` animates a real cross-document navigation, with the outgoing
   document still a real document. No library, no fetch, no DOM swap, and
   a browser without support simply navigates. (Chrome 126+ and Safari
   18.2+ ship it; Firefox does not yet, and degrades to an instant
   navigation there, which is correct behaviour, not a broken page.)

   The treatment is a RISO press: the old page lifts and the new sheet
   drops into register, the way a badly timed print pass shifts. It is
   the page-level expression of the same misregistration the logo already
   does on hover, so the motion stays inside one idea.
   --------------------------------------------------------------------------- */

@view-transition {
  navigation: auto;
}

/* Slow enough to read as a press, short enough never to feel like a
   wait. Both directions are distinct on purpose: the eye can tell a
   page arriving from a lift or a drop. */
::view-transition-old(root) {
  animation: zbb-press-out 0.26s cubic-bezier(0.4, 0, 0.2, 1) both;
}
::view-transition-new(root) {
  animation: zbb-press-in 0.34s cubic-bezier(0.16, 1, 0.3, 1) both;
}

@keyframes zbb-press-out {
  from {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
  to {
    opacity: 0;
    transform: translateY(-10px) scale(0.985);
  }
}

@keyframes zbb-press-in {
  from {
    opacity: 0;
    transform: translateY(14px) scale(0.99);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

/* ── the chrome is continuous, not re-cut ─────────────────────────────
   Naming the topbar and the logo makes them morph across the
   navigation instead of cross-fading with the page. The logo carries
   the name, so the emblem travels rather than blinking out and back —
   which is also the one moment the vector layer is genuinely needed. */
.topnav {
  view-transition-name: zbb-topbar;
}
.topnav .brandplate {
  view-transition-name: zbb-brand;
}
/* Both plates can exist on a page (topbar + hero figure), and a
   view-transition-name must be unique per document. The hero figure
   therefore does not claim the name; only the topbar's does, since that
   is the one present on every page. */

::view-transition-group(zbb-topbar),
::view-transition-old(zbb-topbar),
::view-transition-new(zbb-topbar) {
  animation-duration: 0.34s;
  animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
}
::view-transition-old(zbb-topbar),
::view-transition-old(zbb-brand) {
  animation: none;
  /* Keep the outgoing topbar opaque: a fade here would show the page
     sliding underneath the navigation for a few frames. */
  opacity: 1;
}
::view-transition-new(zbb-topbar),
::view-transition-new(zbb-brand) {
  animation: none;
  opacity: 1;
}

/* The mark itself is what the user is actually tracking between pages,
   so it gets the slower, softer curve and a little rotation — the
   impression turning on the press. */
::view-transition-group(zbb-brand) {
  animation-duration: 0.46s;
  animation-timing-function: cubic-bezier(0.34, 1.4, 0.4, 1);
  z-index: 10;
}
::view-transition-old(zbb-brand) {
  animation: zbb-brand-out 0.2s ease-in both;
}
::view-transition-new(zbb-brand) {
  animation: zbb-brand-in 0.34s cubic-bezier(0.16, 1, 0.3, 1) both;
}
@keyframes zbb-brand-out {
  to { opacity: 0; transform: rotate(-4deg) scale(0.92); }
}
@keyframes zbb-brand-in {
  from { opacity: 0; transform: rotate(4deg) scale(0.92); }
  to   { opacity: 1; transform: rotate(0deg) scale(1); }
}

/* ── off switches ───────────────────────────────────────────────────
   Reduced motion: no transition at all. This is a hard requirement, not
   a softening — a vestibular trigger is not a matter of degree. */
@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) {
    animation: none !important;
  }
}
