@media (prefers-reduced-motion: no-preference) {
  @view-transition { navigation: auto; }
}

:root {
  --works-banner-ink: #1c211c;
  --works-banner-radius: clamp(20px, 2.4vw, 28px);
  --works-button-radius: 24px;
  --works-fold-delay: calc(var(--works-open) + var(--works-gap));
  --works-lift: 545ms;
  --works-open: 710ms;
  --works-gap: 45ms;
  --works-list-travel: 104px;
  --works-list-fade: 360ms;
  --works-lift-ease: cubic-bezier(.8, 0, .2, 1);
  --works-open-ease: cubic-bezier(.82, 0, .18, 1);
}

@media (max-width: 670px) {
  :root {
    --works-lift: 480ms;
    --works-open: 625ms;
    --works-gap: 35ms;
    --works-list-travel: 78px;
    --works-list-fade: 315ms;
  }
}

/* The page snapshots stay fixed. Only the banner and cards travel. */
[data-works-transition]::view-transition-group(root) {
  animation: none;
}
[data-works-transition]::view-transition {
  background: #fff;
}
[data-works-transition]::view-transition-old(root),
[data-works-transition]::view-transition-new(root) {
  animation: none;
  mix-blend-mode: normal;
}

[data-works-transition="forward"]::view-transition-new(root) {
  animation: works-page-in var(--works-lift) var(--works-lift-ease) both;
}

[data-works-transition="back"]::view-transition-old(root) {
  z-index: 1;
  animation: works-page-in var(--works-lift) var(--works-lift-ease)
    calc(var(--works-open) + var(--works-gap)) reverse both;
}

[data-works-transition]::view-transition-group(works-banner) {
  z-index: 2;
  animation-duration: var(--works-lift);
  animation-timing-function: var(--works-lift-ease);
  animation-fill-mode: both;
}

[data-works-transition="back"]::view-transition-group(works-banner) {
  animation-delay: calc(var(--works-open) + var(--works-gap));
}

[data-works-transition]::view-transition-image-pair(works-banner) {
  overflow: clip;
  border-radius: var(--works-banner-radius);
  background: var(--works-banner-ink);
}

/* The frame owns the outline and fill. The snapshots carry only the labels. */
body [data-works-entry] {
  border-radius: var(--works-button-radius);
  transition-property: color;
}
body [data-works-entry]:active { transform: none; }
body #panel-works [data-works-entry]:hover { background: var(--works-banner-ink); }
body #work [data-works-entry]:hover { background: var(--lime); }

/* The top navigation expands from the white header surface. */
body .header-inner nav [data-works-entry="nav"] { border-radius: 22px; }
body .header-inner nav [data-works-entry="nav"]:hover { background: transparent; }
[data-works-origin="nav"] { --works-button-radius: 22px; }

[data-works-transition]::view-transition-image-pair(works-banner) {
  --works-button-fill: var(--works-banner-ink);
}
[data-works-transition][data-works-color="section"]::view-transition-image-pair(works-banner) {
  --works-button-fill: var(--lime);
}

/* The resume entry keeps its original white surface and square text-link bounds. */
body [data-works-entry="resume"] { border-radius: 0; }
[data-works-origin="resume"] { --works-button-radius: 0px; }
[data-works-transition]:is([data-works-color="resume"], [data-works-color="nav"])::view-transition-image-pair(works-banner) {
  --works-button-fill: var(--paper);
}

/* Never change the live frame's fill to prepare a snapshot. The two text
   labels have their own capture, so the frame can be painted once throughout. */
.works-entry-label { display: inline-flex; align-items: center; gap: inherit; }
[data-works-transition]::view-transition-old(works-banner),
[data-works-transition]::view-transition-new(works-banner) {
  animation: none;
  opacity: 0;
}
[data-works-transition]::view-transition-group(works-label) {
  z-index: 3;
  animation-duration: var(--works-lift);
  animation-timing-function: var(--works-lift-ease);
  animation-fill-mode: both;
}
[data-works-transition="back"]::view-transition-group(works-label) {
  animation-delay: var(--works-fold-delay);
}

[data-works-transition="forward"][data-works-button]::view-transition-image-pair(works-banner) {
  animation: works-frame var(--works-lift) var(--works-lift-ease) both;
}

[data-works-transition="back"][data-works-button]::view-transition-image-pair(works-banner) {
  animation: works-frame var(--works-lift) var(--works-lift-ease) var(--works-fold-delay) reverse both;
}

@keyframes works-frame {
  from {
    border-radius: var(--works-button-radius);
    background-color: color-mix(in oklab, var(--works-button-fill) 100%, var(--works-banner-ink));
  }
  to {
    border-radius: var(--works-banner-radius);
    background-color: color-mix(in oklab, var(--works-button-fill) 0%, var(--works-banner-ink));
  }
}

/* Preserve each label's proportions while the frame changes size. */
[data-works-transition]::view-transition-old(works-label),
[data-works-transition]::view-transition-new(works-label) {
  height: 100%;
  object-fit: none;
  object-position: left bottom;
  mix-blend-mode: normal;
}

[data-works-transition="forward"]::view-transition-old(works-label) {
  animation: works-button-out var(--works-lift) ease-in-out both;
}

[data-works-transition="forward"]::view-transition-new(works-label) {
  animation: works-heading-in var(--works-lift) ease-in-out both;
}

[data-works-transition="back"]::view-transition-old(works-label) {
  animation: works-heading-in var(--works-lift) ease-in-out
    calc(var(--works-open) + var(--works-gap)) reverse both;
}

[data-works-transition="back"]::view-transition-new(works-label) {
  animation: works-button-out var(--works-lift) ease-in-out
    calc(var(--works-open) + var(--works-gap)) reverse both;
}

[data-works-transition="forward"]:not([data-works-button])::view-transition-image-pair(works-banner) {
  animation: works-list-in var(--works-lift) var(--works-open-ease) both;
}

[data-works-transition="forward"]:not([data-works-button])::view-transition-new(works-label) {
  animation: none;
}

[data-works-transition="back"]:not([data-works-button])::view-transition-image-pair(works-banner) {
  animation: works-list-in var(--works-lift) var(--works-open-ease) var(--works-fold-delay) reverse both;
}

[data-works-transition="back"]:not([data-works-button])::view-transition-old(works-label) {
  animation: none;
}

/* Unpaired navigation has no button geometry: frame and label enter together. */
[data-works-transition="forward"]:not([data-works-button])::view-transition-group(works-label) {
  animation: works-list-in var(--works-lift) var(--works-open-ease) both;
}
[data-works-transition="back"]:not([data-works-button])::view-transition-group(works-label) {
  animation: works-list-in var(--works-lift) var(--works-open-ease) var(--works-fold-delay) reverse both;
}

[data-works-transition]::view-transition-group(works-list) { z-index: 1; }

[data-works-transition="forward"]::view-transition-new(works-list) {
  --works-list-start: calc(var(--works-lift) + var(--works-gap));
  animation:
    works-list-move var(--works-open) var(--works-open-ease) var(--works-list-start) both,
    works-page-in var(--works-list-fade) ease-in-out var(--works-list-start) both;
}

[data-works-transition="back"]::view-transition-old(works-list) {
  animation:
    works-list-move var(--works-open) var(--works-open-ease) reverse both,
    works-page-in var(--works-list-fade) ease-in-out
      calc(var(--works-open) - var(--works-list-fade)) reverse both;
}

@media (prefers-reduced-motion: no-preference) {
  .works-enter-fallback .works-grid {
    animation:
      works-list-move var(--works-open) var(--works-open-ease) both,
      works-page-in var(--works-list-fade) ease-in-out both;
  }
}

@keyframes works-page-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* Exchange the labels during the lift and finish before the banner settles. */
@keyframes works-button-out {
  0%, 24% { opacity: 1; }
  66%, 100% { opacity: 0; }
}

@keyframes works-heading-in {
  0%, 24% { opacity: 0; }
  66%, 100% { opacity: 1; }
}

/* Fade the card in early so its fastest movement stays visible. */
@keyframes works-list-move {
  from { transform: translateY(calc(-1 * var(--works-list-travel))); }
  to { transform: translateY(0); }
}

@keyframes works-list-in {
  from { opacity: 0; transform: translateY(-24px); }
  to { opacity: 1; transform: translateY(0); }
}
