/* Greybox — growing-background page transition.
 *
 * The capsule click is the origin of a circular wash that expands over the
 * old page. The new route renders underneath while the wash is fully
 * covering, then the wash fades away as <main> eases in. The reveal is a
 * single clip-path animation on one fixed layer (no layout, no giant
 * transformed bitmap), and it is skipped entirely for reduced-motion users.
 *
 * js/page-transition.js owns the timing; the 380ms cover here must stay in
 * sync with its COVER_MS. z-index 45 sits above the fixed header (40) but
 * below the detail modal / player (50+). */

.gx-page-transition {
  position: fixed;
  inset: 0;
  z-index: 45;
  display: none;
  overflow: hidden;
  pointer-events: none;
  touch-action: none;
  background:
    radial-gradient(circle at var(--gx-pt-x, 50%) var(--gx-pt-y, 50%),
      rgba(208, 162, 79, 0.14) 0%,
      rgba(208, 162, 79, 0.04) 18%,
      transparent 44%),
    radial-gradient(circle at var(--gx-pt-x, 50%) var(--gx-pt-y, 50%),
      #2a323e 0%,
      #1a2029 46%,
      #0d1117 100%);
  clip-path: circle(0px at var(--gx-pt-x, 50%) var(--gx-pt-y, 50%));
  transition:
    clip-path 380ms cubic-bezier(0.22, 1, 0.36, 1),
    opacity 440ms cubic-bezier(0.22, 1, 0.36, 1);
  contain: layout paint style;
}

.gx-page-transition.is-active {
  display: block;
  pointer-events: auto;
  will-change: clip-path, opacity;
}

.gx-page-transition.is-cover {
  clip-path: circle(var(--gx-pt-r, 150vmax) at var(--gx-pt-x, 50%) var(--gx-pt-y, 50%));
}

.gx-page-transition.is-reveal { opacity: 0; }

/* The header is the trigger surface: once a transition owns the screen,
 * ignore a second tab click instead of racing the in-flight route. */
html.gx-transitioning #site-header { pointer-events: none; }

/* Under the fully-covering wash, make the outgoing hero/ambient disappear on
 * the route's loading state instead of easing out over 900ms. Without this
 * the reveal exposed the previous poster halfway through its fade. The class
 * is removed at reveal time, so the incoming hero still gets its normal fade. */
html.gx-transitioning .gx-hero-img,
html.gx-transitioning .gx-hero-ambient,
html.gx-transitioning .gx-page-ambient,
html.gx-transitioning .gx-hero-actions { transition: none !important; }

/* The new page emerges as the wash leaves. Opacity only — no transform on
 * <main>, so fixed children keep their containing block. */
main.gx-page-enter {
  animation: gx-page-enter 560ms cubic-bezier(0.22, 1, 0.36, 1) both;
}

@keyframes gx-page-enter {
  from { opacity: 0.25; }
  to { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .gx-page-transition { display: none !important; }
  main.gx-page-enter { animation: none !important; }
}

html[data-motion="reduced"] .gx-page-transition { display: none !important; }
html[data-motion="reduced"] main.gx-page-enter { animation: none !important; }
