/* Transitions between pages.

   The site is a set of real pages rather than one page pretending to be several, and this keeps it
   that way: the browser does the transition itself across a normal navigation, so the back button,
   the address bar and a middle click all still mean what they mean. There is no router here and no
   click handler intercepting a link.

   What moves is only what changes. The grid, the navigation and the panel are named, so the
   browser carries each from where it was to where it is going instead of fading it out and the
   next copy in — which is what makes the site read as one surface being rearranged rather than as
   a series of pages.

   The homepage's card does NOT share the panel's name, though they are the same idea in two
   shapes. Sharing it made the browser morph one into the other, and a morph scales a snapshot:
   a 236px panel grown out of a 502px card arrived as enormous blurred type across half the
   screen. Two things morph well when their contents correspond, and these two only correspond in
   argument. Named apart, each simply leaves and arrives where it belongs. */
@view-transition { navigation: auto }

/* Unique within a document, and only one of these two exists on any page. */
.card { view-transition-name: hero }
.side-panel { view-transition-name: panel }
/* The band is the loudest thing on the homepage, so it leaves on its own and quickly rather than
   ghosting across whatever page comes next. */
.field { view-transition-name: band }
.topbar { view-transition-name: nav }
/* The name is the one thing the homepage card and every other page's chip share exactly — same
   words, same size — so it alone travels between them: the card and the chip fade, and the name
   glides from one corner position to the other. Because both are set at the same size it is a
   move, not a scale, which is what made the old card-to-panel morph blur. */
.brand-name { view-transition-name: name }
.grid { view-transition-name: rules }

/* The rules are the same on every page, so holding them still is the point: a cross-fade between
   two identical grids is a flicker and nothing else. */
::view-transition-group(rules) { animation-duration: 0s }
::view-transition-old(rules),
::view-transition-new(rules) { animation: none; mix-blend-mode: normal }

/* One duration for everything a transition makes.

   A transition builds four pseudo-elements per named thing — a group, an image pair, and the old
   and new images — and each defaults to 250ms. Timing some of them and not others leaves the rest
   running at the default, so the whole thing lasts as long as the slowest piece nobody named. The
   first pass here set old and new and left groups and pairs at 250ms, which is why halving the
   numbers changed nothing measurable.

   Short, too, because the animation is not the part you wait through: a cross-document transition
   holds the page you are leaving on screen until the next is ready to render, and that wait is
   130ms or more before anything here begins. Every millisecond here is spent on top of it. */
::view-transition-group(*),
::view-transition-image-pair(*),
::view-transition-old(*),
::view-transition-new(*) {
  animation-duration: .16s;
  animation-timing-function: cubic-bezier(.2, .7, .3, 1);
}

/* The page leaves faster than it arrives, so the two overlap as briefly as possible. Two dense
   pages cross-fading is double vision for as long as it lasts, and the fix is less of it. */
::view-transition-old(root),
::view-transition-old(hero),
::view-transition-old(band) { animation-name: page-out; animation-duration: .08s; animation-timing-function: ease }
::view-transition-new(root),
::view-transition-new(hero) { animation-name: page-in }
::view-transition-group(name) { animation-duration: .32s; animation-timing-function: cubic-bezier(.3, .7, .2, 1) }
::view-transition-old(name),
::view-transition-new(name) { animation: none; mix-blend-mode: normal }
::view-transition-old(name) { display: none }
@keyframes page-out { to { opacity: 0 } }
@keyframes page-in { from { opacity: 0; transform: translateY(6px) } }

/* Nothing to watch, so nothing is animated: the next page is simply there. */
@media (prefers-reduced-motion: reduce) {
  @view-transition { navigation: none }
}
