/* 06-motion.css - motion: tokens, reveal states, settle, hover, reduce, print.
   Beats 03 by order alone; APPEND. Every hidden state and entrance is gated
   on html.reveal-ready (js/reveal.js adds it after marking what is on
   screen) and on reduced-motion: no-preference, so JavaScript off, reduced
   motion and print get the plain page. Keyframes, not transitions, so a hover
   transition survives. Envelope: docs/REDESIGN-PLAN.md 1.1 to 1.4. */

:root {
    --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
    --ease-soft: cubic-bezier(0.33, 1, 0.68, 1);
    --dur-settle: 480ms;
    --dur-rise: 560ms;
    --dur-fade: 400ms;
    --dur-unmask: 700ms;
    --rise: 16px;
    --settle: 12px;
}

/* Clip, not hidden: no scroll container. */
.site-main {
    overflow-x: clip;
}

@supports not (overflow: clip) {
    .site-main {
        overflow-x: hidden;
    }
}

@media (prefers-reduced-motion: no-preference) {
    html.reveal-ready [data-reveal="rise"]:not([data-revealed]) {
        opacity: 0;
        transform: translateY(var(--rise));
    }

    html.reveal-ready [data-reveal="fade"]:not([data-revealed]) {
        opacity: 0;
    }

    /* A 1px sliver, not a bare 100%: a 0x0 box never starts a lazy image. */
    html.reveal-ready [data-reveal="unmask"]:not([data-revealed]) {
        clip-path: inset(0 0 calc(100% - 1px) 0 round var(--radius-card));
    }

    html.reveal-ready [data-reveal="unmask"][data-reveal-from="left"]:not([data-revealed]) {
        clip-path: inset(0 calc(100% - 1px) 0 0);
    }

    /* The timeline line; 05 sets its origin. */
    html.reveal-ready .steps--timeline:not([data-revealed])::before {
        transform: scaleY(0);
    }

    @media (min-width: 860px) {
        html.reveal-ready .steps--timeline:not([data-revealed])::before {
            transform: scaleX(0);
        }
    }

    html.reveal-ready .steps--timeline[data-revealed="in"]::before {
        transition: transform 700ms var(--ease-out);
    }

    /* backwards: the from state holds through the delay. */
    html.reveal-ready [data-reveal="rise"][data-revealed="in"] {
        animation: bc-rise var(--dur-rise) var(--ease-out) var(--reveal-delay, 0ms) backwards;
    }

    html.reveal-ready [data-reveal="fade"][data-revealed="in"] {
        animation: bc-fade var(--dur-fade) var(--ease-soft) var(--reveal-delay, 0ms) backwards;
    }

    html.reveal-ready [data-reveal="unmask"][data-revealed="in"] {
        animation: bc-unmask var(--dur-unmask) var(--ease-soft) var(--reveal-delay, 0ms) backwards;
    }

    html.reveal-ready [data-reveal="unmask"][data-reveal-from="left"][data-revealed="in"] {
        animation-name: bc-unmask-left;
    }

    /* SETTLE: from 0.35 so the text is painted for LCP. Once per arrival
       (the runtime keeps hero-played). Never the h1. */
    html:not(.hero-played) [data-reveal="settle"] {
        animation: bc-settle var(--dur-settle) var(--ease-out) var(--reveal-delay, 0ms) backwards;
    }

    @keyframes bc-rise {
        from {
            opacity: 0;
            transform: translateY(var(--rise));
        }

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

    @keyframes bc-fade {
        from {
            opacity: 0;
        }

        to {
            opacity: 1;
        }
    }

    /* 1.5rem past the box, so an arch's offset block (05) wipes in with it. */
    @keyframes bc-unmask {
        from {
            clip-path: inset(-1.5rem -1.5rem calc(100% - 1px) -1.5rem round var(--radius-card));
        }

        to {
            clip-path: inset(-1.5rem round var(--radius-card));
        }
    }

    @keyframes bc-unmask-left {
        from {
            clip-path: inset(0 calc(100% - 1px) 0 0);
        }

        to {
            clip-path: inset(0);
        }
    }

    @keyframes bc-settle {
        from {
            opacity: 0.35;
            transform: translateY(var(--settle));
        }

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

[data-reveal-delay="1"] {
    --reveal-delay: 80ms;
}

[data-reveal-delay="2"] {
    --reveal-delay: 160ms;
}

[data-reveal-delay="3"] {
    --reveal-delay: 240ms;
}

[data-reveal-delay="4"] {
    --reveal-delay: 320ms;
}

[data-reveal-delay="5"] {
    --reveal-delay: 400ms;
}

/* HOVER AND FOCUS, on --motion. The chevron nudge is the one sideways
   transform: a 0.4em box inside a link, it can overflow nothing. */

.btn-primary,
.btn-secondary {
    transition: background-color var(--motion) ease, color var(--motion) ease, border-color var(--motion) ease, transform 80ms ease;
}

.btn-primary:active,
.btn-secondary:active {
    transform: translateY(1px);
}

/* The call bar never moves. */
.call-bar .btn:active {
    transform: none;
}

.arch__chip {
    transition: transform var(--motion) ease, border-color var(--motion) ease;
}

.btn-quiet::after {
    transition: transform var(--motion) ease;
}

.btn-quiet:hover::after {
    transform: translateX(2px) rotate(-45deg);
}

.card__title a,
.card__icon,
.faq__question {
    transition: color var(--motion) ease;
}

.card--link:hover .card__title a,
.card--link:focus-within .card__title a,
.faq__question:hover {
    color: var(--teal-text);
}

.card--link:hover .card__icon,
.card--link:focus-within .card__icon {
    color: var(--teal-deep);
}

.site-nav__link {
    transition: color var(--motion) ease, box-shadow var(--motion) ease;
}

/* Only where a hover exists; never the therapy room. */
@media (hover: hover) {
    .photo-grid a img {
        transition: transform 400ms var(--ease-soft);
    }

    .photo-grid a:hover img:not(.photo--no-scale),
    .photo-grid a:focus-visible img:not(.photo--no-scale) {
        transform: scale(1.02);
    }
}

/* REDUCE AND PRINT: the final state wins; a lift under reduce is a jump. */

@media (prefers-reduced-motion: reduce) {
    :root {
        --dur-settle: 0ms;
        --dur-rise: 0ms;
        --dur-fade: 0ms;
        --dur-unmask: 0ms;
        --rise: 0px;
        --settle: 0px;
    }

    .card--link:hover,
    .card--link:focus-within,
    .arch__chip:hover,
    .arch__chip:focus-within,
    .btn-primary:active,
    .btn-secondary:active,
    .photo-grid a:hover img:not(.photo--no-scale),
    .photo-grid a:focus-visible img:not(.photo--no-scale) {
        transform: none;
    }
}

@media (prefers-reduced-motion: reduce), print {
    [data-reveal],
    [data-reveal-group] > *,
    .steps--timeline::before {
        opacity: 1 !important;
        transform: none !important;
        clip-path: none !important;
        animation: none !important;
        transition: none !important;
    }
}
