@view-transition { navigation: auto; }

/* One persistent mark, outside every page fade, sidebar fade and Pricing slide. */
.logo,
.mobile-header-logo,
.question-logo {
  view-transition-name: site-logo;
  transition: none;
  animation: none;
}

::view-transition-group(site-logo) {
  z-index: 100;
  animation: none;
}
::view-transition-old(site-logo),
::view-transition-new(site-logo) {
  animation: none;
  mix-blend-mode: normal;
}
::view-transition-old(site-logo) { opacity: 0; }
::view-transition-new(site-logo) { opacity: 1; }

/* Use viewport coordinates for the mark alone: scrollbars and centered header
   wrappers must not shift it between the portfolio and the question page. */
@media (max-width: 1417px) {
  html .mobile-header-logo,
  html .question-logo {
    --site-logo-unit: min(1px, calc(100vw / 1080));
    position: fixed;
    top: clamp(16px, calc(36 * var(--site-logo-unit)), 36px);
    left: calc(max(0px, (100vw - 1080px) / 2) + clamp(15px, calc(32 * var(--site-logo-unit)), 32px));
    width: clamp(24px, calc(51.84 * var(--site-logo-unit)), 51.84px);
    height: clamp(37.5px, calc(81 * var(--site-logo-unit)), 81px);
  }
}

/* Names are temporary, so the existing Work / Pricing animation is untouched. */
html[data-case-transition="expand"] .visual--otherwise-loop,
html[data-case-transition="expand"] [data-case-slot="hero"] {
  view-transition-name: otherwise-film;
}

html[data-case-transition="expand"] .sidebar { view-transition-name: case-shell; }
html[data-case-transition="expand"] .sidebar-content { view-transition-name: case-copy; }
html[data-case-transition="fade"] .sidebar { view-transition-name: none; }

@keyframes case-fade-out { to { opacity: 0; } }
@keyframes case-fade-in { from { opacity: 0; } to { opacity: 1; } }

html[data-case-transition]::view-transition-group(root) { animation: none; }
/* Let the real page receive scrolling and clicks during the short entrance. */
html[data-case-transition]::view-transition { pointer-events: none; }
html[data-case-transition]::view-transition-old(root) {
  animation: case-fade-out 180ms ease both;
  mix-blend-mode: normal;
}
html[data-case-transition]::view-transition-new(root) {
  animation: case-fade-in 420ms 180ms ease both;
  mix-blend-mode: normal;
}

html[data-case-transition]::view-transition-group(otherwise-film) {
  z-index: 3;
  animation-duration: 640ms;
  animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
@keyframes case-film-bounds {
  from {
    transform: translate(var(--case-film-from-left), var(--case-film-from-top)) scale(var(--case-film-scale-x), var(--case-film-scale-y));
  }
  to {
    transform: translate(var(--case-film-to-left), var(--case-film-to-top)) scale(1, 1);
  }
}
html[data-case-transition="expand"][data-case-geometry]::view-transition-group(otherwise-film) {
  /* Keep the snapshot surface fixed; moving/scaling it avoids rerasterizing
     a large video surface on every frame of the transition. */
  width: var(--case-film-to-width);
  height: var(--case-film-to-height);
  transform-origin: top left;
  animation-name: case-film-bounds;
  animation-fill-mode: both;
  max-width: max(var(--case-film-from-width), var(--case-film-to-width));
  max-height: max(var(--case-film-from-height), var(--case-film-to-height));
}
html[data-case-transition]::view-transition-image-pair(otherwise-film) {
  isolation: isolate;
  width: 100%;
  height: 100%;
  overflow: clip;
}
html[data-case-transition]::view-transition-old(otherwise-film),
html[data-case-transition]::view-transition-new(otherwise-film) {
  width: 100%;
  height: 100%;
  max-width: 100%;
  max-height: 100%;
  object-fit: fill;
  overflow: clip;
  mix-blend-mode: normal;
  animation: none;
}
/* Keep the captured outgoing frame only until the matching incoming video
   frame is decoded. Then show the live video during the remaining movement.
   Readiness changes opacity, never the motion's duration or deadline. */
html[data-case-transition]::view-transition-old(otherwise-film) {
  opacity: 1;
}
html[data-case-transition]::view-transition-new(otherwise-film) {
  opacity: 0;
}
html[data-case-transition][data-case-film-ready]::view-transition-old(otherwise-film) {
  opacity: 0;
}
html[data-case-transition][data-case-film-ready]::view-transition-new(otherwise-film) {
  opacity: 1;
}

html[data-case-transition]::view-transition-group(case-shell) { z-index: 1; animation: none; }
/* Use the same sidebar fade as returning while the case hero is offscreen. */
html[data-case-transition]::view-transition-old(case-shell) { animation: case-fade-out 180ms ease both; }
html[data-case-transition]::view-transition-new(case-shell) { animation: case-fade-in 420ms 100ms ease both; }
html[data-case-transition]::view-transition-group(case-copy) { z-index: 2; animation: none; }
html[data-case-transition]::view-transition-image-pair(case-copy) { overflow: hidden; }
html[data-case-transition]::view-transition-old(case-copy) {
  height: auto;
  animation: case-fade-out 180ms ease both;
}
html[data-case-transition]::view-transition-new(case-copy) {
  animation: case-fade-in 420ms 100ms ease both;
}

/* Small screens retain their stacked layout rather than zooming to an offscreen hero. */
html[data-case-transition="fade"]::view-transition-new(root) {
  animation-delay: 100ms;
}

@media (prefers-reduced-motion: reduce) {
  @view-transition { navigation: none; }
}
