/*
 * fss-core shared motion (with resources/js/motion.js). Port of the Next motion language:
 *  - page change (app/admin/template.tsx + `.admin-page-transition[data-animate]`): everything below the page header enters 8 px up
 *    + fade in 200 ms on a SOFT navigation; the page header is the anchor and stays put; a first load never animates;
 *    `animation-fill-mode: backwards`, so no transform lingers (it would make a containing block for position:fixed children);
 *  - rows/cards (DataTable `m.tr` + staggerDelay): 4 px up + fade, 180 ms, 25 ms apart, at most 12 steps;
 *  - KPI value (KpiTile): 4 px up + fade, 200 ms, 40 ms delay;
 *  - lazy block: the finished block fades in where its skeleton was (the height eases in motion.js);
 *  - loading: no skeleton any more. After 300 ms without a response a thin progress bar runs along the top (html[data-fss-nav="loading"]);
 *    a tab switch (x-page-tabs) never shows it: the page header and the tab bar stay, the content under the tab bar dims slightly.
 *  - ONE entry per element: a block that carries its own entry (data-enter, data-po-enter, data-fss-enter) or contains one is left out of the
 *    page entry below. The `animation` shorthand of this file would otherwise replace the element's own animation for the length of the
 *    page entry and, when html[data-fss-nav] is removed, hand it back: the browser then starts that animation again (the "plays twice").
 * Reduced motion (OS or html[data-motion="reduced"]): opacity only.
 *
 * Markup contract: the content area carries `data-fss-page`; chrome inside it that must stay still carries `data-fss-static`;
 * `html[data-fss-nav]` is set by motion.js: loading (progress bar) | pending | in.
 */

@keyframes fss-page-in {
    from {
        opacity: 0;
        transform: translateY(8px);
    }

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

@keyframes fss-rise-in {
    from {
        opacity: 0;
        transform: translateY(4px);
    }

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

@keyframes fss-fade-in {
    from {
        opacity: 0;
    }

    to {
        opacity: 1;
    }
}

/* --- Page change ------------------------------------------------------------------------------------------------------- */
/* Every block that is not (and does not contain) the page header; then one and two levels down inside a block that does. */
html[data-fss-nav="pending"] [data-fss-page] > :not(.admin-page-header):not(:has(.admin-page-header)):not([data-fss-static]):not([data-fss-static], [data-enter], [data-po-enter], [data-fss-enter], .fss-overlay-host):not(:has([data-enter], [data-po-enter])),
html[data-fss-nav="pending"] [data-fss-page] > :has(.admin-page-header):not([data-fss-static]) > :not(.admin-page-header):not(:has(.admin-page-header)):not([data-fss-static], [data-enter], [data-po-enter], [data-fss-enter], .fss-overlay-host):not(:has([data-enter], [data-po-enter])),
html[data-fss-nav="pending"] [data-fss-page] > :has(.admin-page-header):not([data-fss-static]) > :has(.admin-page-header) > :not(.admin-page-header):not(:has(.admin-page-header)):not([data-fss-static], [data-enter], [data-po-enter], [data-fss-enter], .fss-overlay-host):not(:has([data-enter], [data-po-enter])) {
    opacity: 0;
}

html[data-fss-nav="in"] [data-fss-page] > :not(.admin-page-header):not(:has(.admin-page-header)):not([data-fss-static]):not([data-fss-static], [data-enter], [data-po-enter], [data-fss-enter], .fss-overlay-host):not(:has([data-enter], [data-po-enter])),
html[data-fss-nav="in"] [data-fss-page] > :has(.admin-page-header):not([data-fss-static]) > :not(.admin-page-header):not(:has(.admin-page-header)):not([data-fss-static], [data-enter], [data-po-enter], [data-fss-enter], .fss-overlay-host):not(:has([data-enter], [data-po-enter])),
html[data-fss-nav="in"] [data-fss-page] > :has(.admin-page-header):not([data-fss-static]) > :has(.admin-page-header) > :not(.admin-page-header):not(:has(.admin-page-header)):not([data-fss-static], [data-enter], [data-po-enter], [data-fss-enter], .fss-overlay-host):not(:has([data-enter], [data-po-enter])) {
    animation: var(--fss-page-anim, fss-page-in) 200ms cubic-bezier(0.2, 0, 0, 1) backwards;
}

/* --- Rows, cards and KPI values -------------------------------------------------------------------------------------------- */
[data-fss-enter] {
    animation: var(--fss-rise-anim, fss-rise-in) 180ms cubic-bezier(0.2, 0, 0, 1) backwards;
    animation-delay: calc(var(--fss-i, 0) * 25ms);
}

html[data-fss-nav="in"] [data-fss-page] .admin-kpi-value,
[data-fss-arrived] .admin-kpi-value {
    animation: var(--fss-rise-anim, fss-rise-in) 200ms cubic-bezier(0.2, 0, 0, 1) 40ms backwards;
}

[data-fss-arrived] {
    animation: fss-fade-in 180ms cubic-bezier(0.2, 0, 0, 1) backwards;
}

/* --- Slow response: a thin progress bar, no skeleton --------------------------------------------------------------------------- */
html[data-fss-nav="loading"]::before {
    position: fixed;
    z-index: 2147483000;
    top: 0;
    left: 0;
    width: 100%;
    height: 2px;
    background: var(--accent, #c7ff4a);
    content: "";
    opacity: 0.9;
    pointer-events: none;
    transform: scaleX(0.08);
    transform-origin: left;
    animation: fss-nav-progress 6s cubic-bezier(0.1, 0.6, 0.2, 1) forwards;
}

@keyframes fss-nav-progress {
    to {
        transform: scaleX(0.92);
    }
}

/* Tab switch: everything under the clicked tab bar dims while the response is on its way (after 300 ms); header and bar stay. */
.admin-tabs2[data-fss-wait] ~ * {
    opacity: 0.55;
    transition: opacity 160ms cubic-bezier(0.2, 0, 0, 1);
    pointer-events: none;
}

/* --- Reduced motion: opacity only ---------------------------------------------------------------------------------------- */
html[data-motion="reduced"] {
    --fss-page-anim: fss-fade-in;
    --fss-rise-anim: fss-fade-in;
}

@media (prefers-reduced-motion: reduce) {
    :root {
        --fss-page-anim: fss-fade-in;
        --fss-rise-anim: fss-fade-in;
    }
}
