/*
 * Движение на сайте организации. Подключается `<link media="screen and
 * (prefers-reduced-motion: no-preference)">` (page.blade.php): тому, кто попросил систему
 * уменьшить движение, этот файл не грузится вовсе, и страница остаётся неподвижной -
 * без проверок в каждом правиле. Поэтому всё движение страницы живёт ТОЛЬКО здесь,
 * а site.css не содержит ни `animation`, ни `transition` (сторожит SiteThemeTest).
 *
 * Что включено, решает тема (SiteTheme::MOTION): имена анимаций приходят переменными,
 * у «без движения» это `none`. Плавность наведения (кнопки, карточки) от темы не зависит:
 * это отклик на действие, а не украшение.
 *
 * Правила, на которых держится «контент виден всегда»:
 * - появление при прокрутке - CSS-шкала прокрутки (`animation-timeline: view()`) под
 *   @supports: без неё (Firefox, iOS до 26) анимации нет, статичная страница целиком видна;
 * - заливка `backwards`, не `both`: после анимации действует обычный стиль, а не
 *   последний кадр, и неактивная шкала (страница короче окна) ничего не прячет;
 * - `animation` пишется ДО `animation-timeline`: сокращённая запись сбрасывает шкалу;
 * - первый экран, первый блок после него и последний блок не «появляются» по прокрутке:
 *   первые видно сразу, а последний не успел бы доиграть до конца страницы; первый экран
 *   играет своё вступление по времени;
 * - каскад - сдвигом зоны у `:nth-child`, не `animation-delay` (у шкалы прокрутки это не задержка);
 * - въезд сбоку не даёт прокрутки вбок: `main` обрезает выступ (`overflow-x: clip`,
 *   не `hidden` - тот сделал бы `main` контейнером прокрутки и сломал бы шкалы `view()`);
 * - дрейф узора - только `transform` слоя: перерисовка фона на телефоне шла бы каждый кадр.
 */

@keyframes site-rise {
    from {
        opacity: 0;
        transform: translateY(32px);
    }
}

@keyframes site-fade {
    from {
        opacity: 0;
        transform: translateY(12px);
    }
}

/* Въезд сбоку: сторону задаёт `--side` блока (нечётные слева, чётные справа). */
@keyframes site-slide {
    from {
        opacity: 0;
        transform: translateX(calc(var(--side, -1) * 96px));
    }
}

/* Карточка выскакивает с наклоном; наклон соседей чередуется (`--tilt`). */
@keyframes site-pop {
    from {
        opacity: 0;
        transform: translateY(72px) rotate(var(--tilt, -4deg)) scale(0.88);
    }

    65% {
        transform: translateY(-6px) rotate(0deg) scale(1.02);
    }
}

/* Карточка переворачивается, как табличка на шарнире сверху. */
@keyframes site-flip {
    from {
        opacity: 0;
        transform: perspective(900px) rotateX(-80deg) translateY(24px);
    }

    70% {
        opacity: 1;
        transform: perspective(900px) rotateX(8deg);
    }
}

/* Заголовок блока поднимается из-под маски: нижняя кромка - как прорезь в странице. */
@keyframes site-mask {
    from {
        clip-path: inset(-0.2em -0.2em 100% -0.2em);
        transform: translateY(0.7em);
    }

    to {
        clip-path: inset(-0.2em -0.2em -0.8em -0.2em);
        transform: none;
    }
}

/* Буква взлетает с поворотом и сжатием - заголовок «собирается». */
@keyframes site-letter {
    from {
        opacity: 0;
        transform: translateY(0.6em) rotate(14deg) scale(0.5);
    }

    70% {
        opacity: 1;
        transform: translateY(-0.08em) rotate(-3deg) scale(1.06);
    }
}

/* Печать: буква просто появляется в свой момент (длительность одна на все виды букв,
   поэтому появление в первом проценте). */
@keyframes site-type {
    0% {
        opacity: 0;
    }

    1% {
        opacity: 1;
    }
}

/* Курсор печати: за каждой буквой мелькает её шаг, у последней мигает. */
@keyframes site-caret {
    0%,
    55% {
        opacity: 1;
    }

    56%,
    100% {
        opacity: 0;
    }
}

/* Фото первого экрана открывается шторкой сбоку и чуть оседает. */
@keyframes site-wipe {
    from {
        clip-path: inset(0 0 0 100% round var(--radius));
        transform: scale(1.14);
    }

    to {
        clip-path: inset(0 0 0 0 round var(--radius));
        transform: none;
    }
}

/* Фото первого экрана раскрывается кругом из середины. */
@keyframes site-iris {
    from {
        clip-path: circle(0% at 50% 50%);
    }

    to {
        clip-path: circle(75% at 50% 50%);
    }
}

@keyframes site-drift {
    from {
        transform: translate3d(0, 0, 0) scale(1.06);
    }

    to {
        transform: translate3d(-3%, 2%, 0) scale(1.14);
    }
}

@keyframes site-underline {
    from {
        transform: scaleX(0);
    }

    to {
        transform: scaleX(1);
    }
}

main {
    overflow-x: clip;
}

/* Первый экран - вступление по времени загрузки. Заголовок целиком (`--intro`) или
   по буквам (`--letter`, разметку по буквам сервер даёт только этим ступеням). */
.hero .hero-title {
    animation: var(--intro, none) 0.8s cubic-bezier(0.2, 0.7, 0.2, 1) backwards;
}

.hero-word {
    display: inline-block;
    white-space: nowrap;
}

/* Задержка буквы - её номер на шаг ступени, но не дольше 2.8 с: длинный заголовок
   иначе собирался бы до десяти секунд. */
.hero-letter {
    display: inline-block;
    position: relative;
    transform-origin: 0 100%;
    animation: var(--letter, none) 0.7s cubic-bezier(0.2, 0.7, 0.2, 1) backwards;
    animation-delay: min(calc(var(--i) * var(--letter-step, 0ms)), 2.8s);
}

/* Курсор печати - тонкая черта за буквой, видна только в её шаг (`site-caret`). */
.hero-letter::after {
    content: '';
    position: absolute;
    left: 100%;
    top: 0.12em;
    bottom: 0.1em;
    width: 0.07em;
    margin-left: 0.04em;
    background: currentColor;
    opacity: 0;
    animation: var(--caret, none) var(--letter-step, 0ms) linear;
    animation-delay: min(calc(var(--i) * var(--letter-step, 0ms)), 2.8s);
}

.hero-word:last-child > .hero-letter:last-child::after {
    animation-duration: 0.9s;
    animation-iteration-count: 3;
}

/* Подзаголовок и кнопки - когда заголовок собран, кнопки по очереди. */
.hero :is(.hero-sub, .hero-actions > *) {
    animation: var(--follow, none) 0.7s cubic-bezier(0.2, 0.7, 0.2, 1) backwards;
    animation-delay: calc(min(var(--letters, 0) * var(--letter-step, 0ms), 2.8s) + 0.3s);
}

.hero .hero-actions > :nth-child(2) {
    animation-delay: calc(min(var(--letters, 0) * var(--letter-step, 0ms), 2.8s) + 0.45s);
}

.hero-split .hero-image {
    animation: var(--picture, none) 1.1s cubic-bezier(0.65, 0, 0.25, 1) 0.15s backwards;
}

/* В редакторе предпросмотр обновляется на каждой паузе ввода, и узлы заголовка
   заменяются: вступление проигрывалось бы заново на каждой букве. preview.js ставит
   `data-settled` после первого обновления и снимает его ненадолго, когда меняют само
   движение - чтобы выбор было видно (докблок preview.js). */
[data-settled] .hero :is(.hero-title, .hero-letter, .hero-sub, .hero-actions > *, .hero-image),
[data-settled] .hero-letter::after {
    animation: none;
}

/* Дрейф узора первого экрана: медленно, туда и обратно. */
.hero:not(.hero-cover)::after {
    animation: var(--drift, none) 26s ease-in-out infinite alternate;
}

/* Сторона въезда: нечётные блоки слева, чётные справа. */
.block:nth-of-type(even) {
    --side: 1;
}

.block :is(.points, .directions, .plans) > :nth-child(even) {
    --tilt: 4deg;
}

@supports (animation-timeline: view()) {
    /* Содержимое блоков - по мере появления. Первый блок после первого экрана виден сразу.
       Зона - от входа в экран до трети пути через него, кривая ровная: у движения,
       привязанного к прокрутке, кривая «быстро в начале» (как у вступления по времени)
       отыгрывала почти всё в первых сантиметрах, пока блок едва виден, - эффект
       выглядел слабым (владелец 11.11.2026). Теперь въезд виден, пока блок идёт к середине.

       Окно шкалы срезано снизу на пятую часть экрана (`view(block 0% 20%)`): «вход» блока
       считается от линии на 20% выше нижнего края. Иначе появление начиналось, когда верх
       блока только касался края, и первая часть движения проходила за кадром (владелец
       11.11.2026: «появляются слишком рано»). Концы зон подобраны так, чтобы последний
       блок страницы успевал доиграть до конца прокрутки (проверено кадрами у дна).

       Последний блок не появляется вовсе, как и первый после первого экрана: под ним только
       подвал, прокрутка кончается раньше, чем его содержимое дойдёт до линии, и оно
       осталось бы полупрозрачным навсегда. */
    .block:not(.hero + .block, :last-of-type) > .wrap > :not(h2, .points, .directions, .plans) {
        animation: var(--reveal, none) cubic-bezier(0.35, 0, 0.25, 1) backwards;
        animation-timeline: view(block 0% 20%);
        animation-range: entry 0% cover 34%;
    }

    .block:not(.hero + .block, :last-of-type) > .wrap > h2 {
        animation: var(--heading, none) cubic-bezier(0.35, 0, 0.25, 1) backwards;
        animation-timeline: view(block 0% 20%);
        animation-range: entry 0% cover 30%;
    }

    /* Карточки - своим ходом и каскадом: соседи по ряду вслед друг за другом. */
    .block:not(.hero + .block, :last-of-type) :is(.points, .directions, .plans) > * {
        transform-origin: 50% 0;
        animation: var(--card, none) cubic-bezier(0.35, 0, 0.25, 1) backwards;
        animation-timeline: view(block 0% 20%);
        animation-range: entry 0% cover 30%;
    }

    .block :is(.points, .directions, .plans) > :nth-child(3n + 2) {
        animation-range: entry 10% cover 36%;
    }

    .block :is(.points, .directions, .plans) > :nth-child(3n) {
        animation-range: entry 20% cover 42%;
    }

    /* Черта цвета организации под заголовком блока прорисовывается при появлении.
       Видна только с движением: без анимации черта остаётся нулевой ширины. Места
       в раскладке она не занимает (абсолютная): иначе заголовки стояли бы по-разному
       с движением и без него. */
    .block h2 {
        position: relative;
    }

    .block h2::after {
        content: '';
        position: absolute;
        left: 0;
        top: calc(100% + 0.2em);
        width: 2.4em;
        height: 3px;
        border-radius: 3px;
        background: var(--s-mark);
        transform: scaleX(0);
        transform-origin: left;
        animation: var(--underline, none) linear both;
        animation-timeline: view(block 0% 20%);
        animation-range: entry 30% cover 35%;
    }

    /* Черта последнего блока - сразу целиком, по доводу выше. */
    .block:last-of-type h2::after {
        animation: none;
        transform: none;
    }

    .v-center h2::after {
        right: 0;
        margin-inline: auto;
        transform-origin: center;
    }
}

/* Отклик на наведение: плавно, независимо от темы. */
.btn {
    transition: transform 0.18s ease, box-shadow 0.18s ease, background-color 0.18s ease, color 0.18s ease;
}

.v-cards .direction,
.v-cards .plan {
    transition: transform 0.25s ease, box-shadow 0.25s ease;
}

.nav a {
    transition: color 0.15s ease;
}

/* Бегущий блик по кнопке (SiteTheme::BUTTON_FX `shine`, `--btn-shine: 1`). */
.btn::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(110deg, transparent 30%, rgb(255 255 255 / 0.42) 50%, transparent 70%);
    opacity: var(--btn-shine, 0);
    transform: translateX(-120%);
    pointer-events: none;
}

.btn:hover::after,
.btn:focus-visible::after {
    transform: translateX(120%);
    transition: transform 0.7s ease;
}

/* Кнопка «наверх» выезжает, а не вспыхивает. */
.to-top {
    transition: opacity 0.2s ease, visibility 0.2s ease, transform 0.2s ease;
}
