/*
 * Mobile page open/close transitions.
 *
 * Uses cross-document View Transitions, so the browser animates the outgoing
 * page out and the incoming page in by itself. No JavaScript, and crucially no
 * click interception — navigation is never held back waiting for an animation.
 *
 * The @view-transition rule is declared at top level, where every engine that
 * supports it will parse it; the visuals are then scoped by media query.
 * Browsers without support navigate exactly as before and keep the existing
 * .motion-page enter animation from app.css. Nothing degrades.
 */

@view-transition {
    navigation: auto;
}

/* Desktop keeps the instant swap it has today. */
@media (min-width: 768px) {
    ::view-transition-old(root),
    ::view-transition-new(root) {
        animation: none;
    }
}

@media (max-width: 767px) {
    /* The outgoing page — the "closing" half. Kept short so the next page is
       never waiting on it. */
    ::view-transition-old(root) {
        animation: bbaPageOut 160ms cubic-bezier(0.4, 0, 1, 1) both;
    }

    /* The incoming page — a plain fade. The upward slide still comes from
       .motion-page on <main>, so the two compose instead of fighting. */
    ::view-transition-new(root) {
        animation: bbaPageIn 220ms cubic-bezier(0.22, 1, 0.36, 1) both;
    }

    /* Hold the chrome still so only the content moves. This is what makes it
       read as a page change rather than a whole-screen cross-fade. */
    .mobile-top-bar {
        view-transition-name: bba-top-bar;
    }

    #mobile-bottom-nav {
        view-transition-name: bba-bottom-nav;
    }

    ::view-transition-old(bba-top-bar),
    ::view-transition-new(bba-top-bar),
    ::view-transition-old(bba-bottom-nav),
    ::view-transition-new(bba-bottom-nav) {
        animation: none;
        mix-blend-mode: normal;
    }
}

@keyframes bbaPageOut {
    from {
        opacity: 1;
        transform: none;
    }

    to {
        opacity: 0;
        transform: translateY(-8px);
    }
}

@keyframes bbaPageIn {
    from {
        opacity: 0;
    }

    to {
        opacity: 1;
    }
}

/* Honour the OS setting: no motion, no transition. */
@media (prefers-reduced-motion: reduce) {
    ::view-transition-group(*),
    ::view-transition-old(*),
    ::view-transition-new(*) {
        animation: none !important;
    }
}

/*
 * In-page push/pop — used when the routine screens swap (choose batch → the
 * routine itself, and back). Driven by document.startViewTransition, so the
 * browser overlaps the two states for us and the panels do not need to be
 * absolutely positioned.
 *
 * The curve is the iOS navigation push: a fast start that settles rather than
 * decelerating evenly. The outgoing screen recedes a little instead of leaving
 * completely, which is what makes it feel layered rather than like a slideshow.
 */

html.rt-push::view-transition-old(root) {
    animation: rtPushOutOld 420ms cubic-bezier(0.32, 0.72, 0, 1) both;
}

html.rt-push::view-transition-new(root) {
    animation: rtPushInNew 420ms cubic-bezier(0.32, 0.72, 0, 1) both;
}

html.rt-pop::view-transition-old(root) {
    animation: rtPopOutOld 380ms cubic-bezier(0.32, 0.72, 0, 1) both;
}

html.rt-pop::view-transition-new(root) {
    animation: rtPopInNew 380ms cubic-bezier(0.32, 0.72, 0, 1) both;
}

/* Forward: the new screen comes in from the right, the old one slips back. */
@keyframes rtPushInNew {
    from {
        opacity: 0.6;
        transform: translateX(28%);
    }

    to {
        opacity: 1;
        transform: none;
    }
}

@keyframes rtPushOutOld {
    from {
        opacity: 1;
        transform: none;
    }

    to {
        opacity: 0;
        transform: translateX(-14%) scale(0.98);
    }
}

/* Back: exactly mirrored, slightly quicker — the way iOS pops. */
@keyframes rtPopInNew {
    from {
        opacity: 0.6;
        transform: translateX(-14%) scale(0.98);
    }

    to {
        opacity: 1;
        transform: none;
    }
}

@keyframes rtPopOutOld {
    from {
        opacity: 1;
        transform: none;
    }

    to {
        opacity: 0;
        transform: translateX(28%);
    }
}
