/* Page transition — the project cards fly into the nav while the page rises.

   Modelled on the recording Flora sent. Two things happen at once there:

   1. The whole row of cards shrinks and travels up into the bar. Every card
      goes, not only the one clicked — which is why the project you opened is
      briefly visible twice, once as a thumbnail in the bar and once as the
      cover rising underneath it.
   2. The incoming page rises and settles underneath them.

   The timing was traced off that recording frame by frame: about 640ms on
   cubic-bezier(0.25, 0.1, 0.25, 1). The site's usual expo-out is much snappier
   and does not describe this motion at all — fitted against the traced travel
   it is off by 0.23 where this curve is off by 0.03 — so the transition keeps
   its own curve rather than the house one.

   The distance is theirs too: a whole screen, with everything that belongs to
   both pages held still while it travels. Nothing moves except what genuinely
   changes place.

   This is a cross-document view transition. Chrome, Edge and Safari run it;
   Firefox navigates the way it does today. Nothing on either page depends on
   it, so where it does not run, nothing is missing. */

@view-transition { navigation: auto; }

/* Anyone who has asked for less motion gets the plain navigation back. */
@media (prefers-reduced-motion: reduce) {
  @view-transition { navigation: none; }
}

:root {
  --transition-travel: 640ms;
  --transition-ease: cubic-bezier(0.25, 0.1, 0.25, 1);
}

/* ── What travels ────────────────────────────────────────────────────────── */

/* The buttons are named, the bar is not — and that distinction is the whole
   thing.

   A named element becomes a backdrop root, and a backdrop root cuts every
   `backdrop-filter` INSIDE it off from the page behind. Naming the bar
   therefore flattened the glass on everything it contained, permanently, not
   only while a transition ran. Naming each button does not: an element is a
   backdrop root for its descendants, never for itself, and the blur lives on
   the buttons themselves. So they hold still and keep their glass.

   These five are the same five buttons on every page, so they should not move
   between pages at all. Naming them says exactly that. */
[data-nav="name"]     { view-transition-name: nav-name; }
[data-nav="about"]    { view-transition-name: nav-about; }
[data-nav="approach"] { view-transition-name: nav-approach; }
[data-nav="contact"]  { view-transition-name: nav-contact; }
[data-nav="menu"]     { view-transition-name: nav-menu; }

/* The rule between the two card groups exists only on a project page. Named, it
   arrives on its own rather than sliding a whole screen up with the page. */
.nav-sep { view-transition-name: nav-sep; }

/* Each card is paired with its thumbnail in the project nav by sharing a name.
   The browser then has one object in two places and moves it between them.

   This is what Flora's 4:3 change was for: the two boxes are now the same
   shape, so the card only ever changes size on the way, never proportion.

   On the home the name sits on the clipping frame rather than the image, since
   the frame is what carries the rounded corners and the box that morphs. */
.project-card[data-project="iterationx"] .project-thumb-wrap,
.nav-project[data-project="iterationx"] { view-transition-name: card-iterationx; }

.project-card[data-project="propertygrid"] .project-thumb-wrap,
.nav-project[data-project="propertygrid"] { view-transition-name: card-propertygrid; }

.project-card[data-project="axa-live"] .project-thumb-wrap,
.nav-project[data-project="axa-live"] { view-transition-name: card-axa-live; }

.project-card[data-project="whitebird"] .project-thumb-wrap,
.nav-project[data-project="whitebird"] { view-transition-name: card-whitebird; }

.project-card[data-project="lizee"] .project-thumb-wrap,
.nav-project[data-project="lizee"] { view-transition-name: card-lizee; }

/* Every travelling object shares the traced timing, so the row arrives as one
   movement rather than six that happen to overlap.

   Named one by one rather than with `*`: the universal form is newer than the
   transition itself and not everywhere yet, and a group that misses this rule
   silently falls back to the browser's default 250ms, which would break the
   row apart.

   And only when a project is involved. Between the main pages nothing travels
   anywhere, so none of this applies and the browser's own cross-fade is left
   to do its job. */
:root.vt-to-project::view-transition-group(nav-name),
:root.vt-to-project::view-transition-group(nav-about),
:root.vt-to-project::view-transition-group(nav-approach),
:root.vt-to-project::view-transition-group(nav-contact),
:root.vt-to-project::view-transition-group(nav-menu),
:root.vt-to-project::view-transition-group(nav-sep),
:root.vt-to-project::view-transition-group(card-iterationx),
:root.vt-to-project::view-transition-group(card-propertygrid),
:root.vt-to-project::view-transition-group(card-axa-live),
:root.vt-to-project::view-transition-group(card-whitebird),
:root.vt-to-project::view-transition-group(card-lizee),
:root.vt-from-project::view-transition-group(nav-name),
:root.vt-from-project::view-transition-group(nav-about),
:root.vt-from-project::view-transition-group(nav-approach),
:root.vt-from-project::view-transition-group(nav-contact),
:root.vt-from-project::view-transition-group(nav-menu),
:root.vt-from-project::view-transition-group(nav-sep),
:root.vt-from-project::view-transition-group(card-iterationx),
:root.vt-from-project::view-transition-group(card-propertygrid),
:root.vt-from-project::view-transition-group(card-axa-live),
:root.vt-from-project::view-transition-group(card-whitebird),
:root.vt-from-project::view-transition-group(card-lizee) {
  animation-duration: var(--transition-travel);
  animation-timing-function: var(--transition-ease);
}

/* ── The page underneath ─────────────────────────────────────────────────── */

/* Two opaque sheets, one passing over the other — not a dissolve. The browser
   cross-fades these by default and lights the overlap with `plus-lighter` to
   keep a fade clean; over a slide that same blend brightens every pixel where
   they meet. The cards and buttons above still cross-fade, which is what a
   morph wants. */
:root.vt-to-project::view-transition-old(root),
:root.vt-to-project::view-transition-new(root),
:root.vt-from-project::view-transition-old(root),
:root.vt-from-project::view-transition-new(root) { mix-blend-mode: normal; }

/* The project comes up over the home, a full screen of travel, and the home
   goes before it gets there.

   Held at full strength, the home was still fully alive underneath while the
   project's own background — plain page grey above its white sheet — climbed
   over it. What that reads as is a grey plate being dragged across a live
   page, not a page arriving.

   So the home fades first, over 340ms, and the climb starts 80ms after it
   begins. By the time the grey has covered any real distance there is little
   left under it to cover, and the eye follows the cards flying to the bar
   rather than an edge sweeping up the screen.

   Everything that belongs to both pages is named above, so none of it rides
   this: the five buttons hold, the cards fly to their own places, and what
   climbs is only the page. */
:root.vt-to-project::view-transition-new(root) {
  animation: page-rise var(--transition-travel) var(--transition-ease) 80ms both;
}

:root.vt-to-project::view-transition-old(root) {
  animation: page-leave 340ms var(--transition-ease) both;
}

@keyframes page-rise {
  from { transform: translateY(100%); }
}

/* A short lift with the fade, so the home reads as leaving rather than simply
   being switched off. */
@keyframes page-leave {
  to { opacity: 0; transform: translateY(-24px); }
}

/* Held, not faded: still what the page being left does on the way back out of
   a project, where it is the one going and nothing is arriving over it. */
@keyframes page-hold {
  from { opacity: 1; }
  to   { opacity: 1; }
}

/* ── Coming back out ─────────────────────────────────────────────────────── */

/* Leaving a project it is the same movement run backwards: the project lowers
   away and uncovers the home, which was underneath the whole time.

   For that to read at all, the page being LEFT has to paint over the one
   arriving — new is above old by default, so the old is lifted a layer here.
   Without it the project slides away behind the home and nothing appears to
   move. */
:root.vt-from-project::view-transition-old(root) {
  animation: page-lower var(--transition-travel) var(--transition-ease) both;
  z-index: 1;
}

:root.vt-from-project::view-transition-new(root) {
  animation: page-hold var(--transition-travel) linear both;
}

@keyframes page-lower {
  to { transform: translateY(100%); }
}

/* ── Not twice ───────────────────────────────────────────────────────────── */

/* The project page brings its own sheet and nav in on load. Two arrivals are
   not arrivals at all and neither should run them:

   - `is-vt`, set from `pagereveal`, when a transition has already carried them
     there; the sheet would arrive and then start over.
   - `is-restored`, set from project-nav.js, when the browser has put the page
     back where it was. Nothing is arriving there — the visitor is returning to
     a place — and animating the sheet slides the content they were reading. */
:root.is-vt .project-body,
:root.is-vt .nav-cards-inner,
:root.is-vt .nav-project img,
:root.is-restored .project-body,
:root.is-restored .nav-cards-inner,
:root.is-restored .nav-project img { animation: none; }


/* ── The page's colour changes by moving, not by switching ───────────────

   A project page sits on primary/50 and the rest of the site on grey/100, so
   every crossing between them changes the colour of the whole page. Left alone that arrives
   as a hard edge sweeping up the screen with the incoming sheet — which is
   exactly the seam Flora has been chasing out of this site all along.

   So the page that arrives starts on the colour of the page being left and
   gives it up over the same 640ms everything else moves in. `vt-bg-hold` is
   set before the first paint and dropped two frames later, which is what gives
   the transition something to travel from. */

:root.vt-to-project.vt-bg-hold   { --page-bg: var(--grey-background-100); }
:root.vt-from-project.vt-bg-hold { --page-bg: var(--primary-50); }

:root.vt-to-project,
:root.vt-from-project {
  --page-bg-travel: var(--transition-travel);
}


/* ── From one project to the next ─────────────────────────────────────────

   A push, not an overlay: the arriving project pushes the one you are leaving
   off the other side, both moving together at the same rate. Measured by
   correlating consecutive frames of aparelho's recording rather than by
   tracking a shape — the page being left travels -69, -118, -137, -40 across
   the frames where the match holds, against a seam moving -71, -75, -149, -40.
   Same distance. Two pages, one movement.

   (My first reading had it holding still. I had followed the centre of mass of
   its VISIBLE part, and when a page slides off to the left its visible centre
   drifts right — which cancels most of the real travel. A centroid does not
   measure translation on something being clipped.)

   And the side depends on the order. The nav lists the projects left to right;
   going to one that sits further along, it arrives from the right and pushes
   the other left. Going back up the row, the reverse. The row is the map, so
   the movement has to agree with it.

   Durée et courbe remesurées sur les trois poussées de l'enregistrement, en
   corrélant chaque image à la suivante sur toute la largeur — dans une poussée
   rigide l'écran entier translate d'un bloc, donc la vitesse se lit
   directement. Elles totalisent -795, -797 et -807px sur un écran de 800 :
   exactement une largeur, à un pixel près.

   Le GIF tourne à 70ms par image et les poussées font 11, 11 et 10 images,
   soit 700 à 770ms — d'où 750. Et le profil de vitesse monte doucement, pointe
   fort au milieu, puis s'éteint : un ease-in-out plus marqué que le mien.
   Ajusté sur les trois, l'écart tombe de 0.054 à 0.042. Ce sont les extrémités
   plus douces qui font la fluidité, pas la lenteur. */

:root.vt-across {
  --across-travel: 750ms;
  --across-ease: cubic-bezier(0.65, 0, 0.35, 1);
}

/* Opaque sheets, not a dissolve. */
:root.vt-across::view-transition-old(root),
:root.vt-across::view-transition-new(root) { mix-blend-mode: normal; }

/* Forward along the row: the new one comes from the right. */
:root.vt-across.is-forward::view-transition-new(root) {
  animation: across-from-right var(--across-travel) var(--across-ease) both;
}
:root.vt-across.is-forward::view-transition-old(root) {
  animation: across-to-left var(--across-travel) var(--across-ease) both;
}

/* Back up the row: from the left. */
:root.vt-across.is-back::view-transition-new(root) {
  animation: across-from-left var(--across-travel) var(--across-ease) both;
}
:root.vt-across.is-back::view-transition-old(root) {
  animation: across-to-right var(--across-travel) var(--across-ease) both;
}

@keyframes across-from-right { from { transform: translateX(100%); } }
@keyframes across-to-left    { to   { transform: translateX(-100%); } }
@keyframes across-from-left  { from { transform: translateX(-100%); } }
@keyframes across-to-right   { to   { transform: translateX(100%); } }

/* Everything shared holds through it: the five nav buttons, the five card
   thumbnails, the rule between them. On their site the thumbnail row is the
   one thing that does not move during this, and here it already does not. */
:root.vt-across::view-transition-group(nav-name),
:root.vt-across::view-transition-group(nav-about),
:root.vt-across::view-transition-group(nav-approach),
:root.vt-across::view-transition-group(nav-contact),
:root.vt-across::view-transition-group(nav-menu),
:root.vt-across::view-transition-group(nav-sep),
:root.vt-across::view-transition-group(card-iterationx),
:root.vt-across::view-transition-group(card-propertygrid),
:root.vt-across::view-transition-group(card-axa-live),
:root.vt-across::view-transition-group(card-whitebird),
:root.vt-across::view-transition-group(card-lizee) {
  animation-duration: var(--across-travel);
  animation-timing-function: var(--across-ease);
}
