/* ═══════════════════════════════════════════════════════════════════════
   THE EMBER PASSAGE — cross-document page transitions
   ═══════════════════════════════════════════════════════════════════════

   Every page in this site used to be its own island: each had a private
   entrance animation, and leaving one was a hard cut to the next. This is the
   site's first shared layer, and it does something a static multi-page site
   normally cannot — it animates BETWEEN documents.

   How: the View Transitions API (`@view-transition { navigation: auto }`).
   The browser snapshots the outgoing page, snapshots the incoming one, and
   lets us animate between them. Because both documents opt in and we're
   same-origin, this works on plain <a href> navigation — no SPA, no router,
   no framework.

   The motion is deliberately NOT a crossfade. The old page catches light,
   blooms, and burns away upward into ash; the new one cools in from darkness,
   as if the fire carried you there. A phoenix site should navigate by burning.

   SHARED ELEMENTS: anything tagged `view-transition-name` is tracked across
   the navigation and MORPHS — position, size and all. The phoenix sigil uses
   this, so it physically travels from one page to the next instead of
   disappearing and being redrawn.

   SAFETY: browsers without support ignore every rule here and navigate
   exactly as they do today — this is purely additive. Reduced-motion users
   get a short, calm dissolve instead.
   ═══════════════════════════════════════════════════════════════════════ */

@view-transition { navigation: auto; }

/* ── Tempo ─────────────────────────────────────────────────────────────
   The old page leaves a touch faster than the new one arrives, so the two
   overlap in the middle. That overlap is what sells it as one continuous
   motion rather than two animations played back to back. */
::view-transition-group(root) {
    animation-duration: 900ms;
    animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
}

/* Both snapshots share the stage; the outgoing one sits on top as it burns. */
::view-transition-old(root) {
    animation: phxBurnAway 780ms cubic-bezier(0.55, 0, 0.35, 1) both;
    mix-blend-mode: screen;      /* embers add light to what's underneath */
    z-index: 2;
}
::view-transition-new(root) {
    animation: phxEmberIn 900ms cubic-bezier(0.16, 1, 0.3, 1) both;
    z-index: 1;
}

/* ── The burn ──────────────────────────────────────────────────────────
   Three things happen at once, and the overlap is the whole trick:
     1. brightness+saturate bloom — the page catches light before it goes
     2. a mask sweeping bottom→top — it burns away like paper, not a fade
     3. a slight rise + blur — the ash lifts rather than sitting still     */
@keyframes phxBurnAway {
    0% {
        opacity: 1;
        filter: none;
        transform: scale(1) translateY(0);
        -webkit-mask-image: linear-gradient(to top, #000 0%, #000 100%);
                mask-image: linear-gradient(to top, #000 0%, #000 100%);
    }
    35% {
        opacity: 1;
        filter: brightness(1.32) saturate(1.28) contrast(1.04);
        transform: scale(1.012) translateY(-4px);
    }
    100% {
        opacity: 0;
        filter: brightness(1.9) saturate(1.5) blur(13px);
        transform: scale(1.055) translateY(-26px);
        /* The mask edge has travelled off the top — the page has burned. */
        -webkit-mask-image: linear-gradient(to top, transparent 88%, #000 140%);
                mask-image: linear-gradient(to top, transparent 88%, #000 140%);
    }
}

/* ── The arrival ───────────────────────────────────────────────────────
   The new page does NOT fade in. It cools in: from dark and out of focus
   to full colour, easing down into place as the embers settle. */
@keyframes phxEmberIn {
    0% {
        opacity: 0;
        filter: brightness(0.28) saturate(0.6) blur(18px);
        transform: scale(1.035) translateY(14px);
    }
    38% { opacity: 1; }
    100% {
        opacity: 1;
        filter: none;
        transform: scale(1) translateY(0);
    }
}

/* ── The travelling sigil ──────────────────────────────────────────────
   Tagged elements are matched by name across documents and interpolated
   between their two positions. The phoenix doesn't blink out and redraw —
   it flies from where it was to where it's going. */
::view-transition-group(phx-sigil) {
    animation-duration: 1000ms;
    animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
    z-index: 10;                 /* rides above the burn */
}
::view-transition-old(phx-sigil),
::view-transition-new(phx-sigil) {
    /* Hold both at full opacity so the shape morphs cleanly instead of
       cross-dissolving into a muddy double-image. */
    animation-duration: 1000ms;
    mix-blend-mode: normal;
}
::view-transition-old(phx-sigil) { animation-name: phxSigilOut; }
::view-transition-new(phx-sigil) { animation-name: phxSigilIn; }

@keyframes phxSigilOut {
    0%   { opacity: 1; filter: drop-shadow(0 0 0 rgba(255,150,60,0)); }
    100% { opacity: 0; filter: drop-shadow(0 0 26px rgba(255,150,60,0.85)); }
}
@keyframes phxSigilIn {
    0%   { opacity: 0; filter: drop-shadow(0 0 26px rgba(255,150,60,0.85)); }
    100% { opacity: 1; filter: drop-shadow(0 0 0 rgba(255,150,60,0)); }
}

/* Opt an element in from any page:  <div class="phx-sigil"> … </div>       */
.phx-sigil { view-transition-name: phx-sigil; contain: layout; }

/* ── Accessibility ─────────────────────────────────────────────────────
   Vestibular-safe: no bloom, no scale, no drift. Just a short dissolve so
   the navigation still feels connected without any motion. */
@media (prefers-reduced-motion: reduce) {
    ::view-transition-group(root),
    ::view-transition-old(root),
    ::view-transition-new(root),
    ::view-transition-group(phx-sigil),
    ::view-transition-old(phx-sigil),
    ::view-transition-new(phx-sigil) {
        animation-duration: 200ms !important;
        animation-timing-function: ease !important;
    }
    ::view-transition-old(root) {
        animation-name: phxCalmOut !important;
        mix-blend-mode: normal;
    }
    ::view-transition-new(root) { animation-name: phxCalmIn !important; }
    @keyframes phxCalmOut { to { opacity: 0; } }
    @keyframes phxCalmIn  { from { opacity: 0; } }
}
