/* ==========================================================================
   Анимации текста и микровзаимодействия — стили слоя 2 из 2.

   Заполняется тем же агентом, что и js/anim-text.js. Правила те же:
   transform и opacity, уважение к prefers-reduced-motion, никаких скрытых
   без JavaScript элементов.

   Поэтому здесь нет ни одного правила, которое что-то прячет по умолчанию:
   каждое скрытое состояние требует класса, который ставит скрипт
   (.anim-title--armed, .anim-hero--live, .tabs-indicator, .burst).
   Без JavaScript страница выглядит ровно так, как выглядела до этого слоя.

   Что обслуживает файл:
   1. слова заголовков (каскад);
   2. продвижение слоёв первого экрана по прокрутке (will-change);
   3. полоса под активной вкладкой программы;
   4. залп частиц на успешную заявку.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Заголовки: слова поднимаются по одному

   Слова — настоящий текст заголовка (не aria-hidden копия), поэтому доступное
   имя складывается из них как из одной фразы. inline-block нужен, чтобы
   transform вообще применялся к слову; пробелы между словами остаются
   текстовыми узлами, поэтому перенос строк не меняется.
   -------------------------------------------------------------------------- */

.anim-title__word {
    display: inline-block;
    /* У inline-block своя ширина по содержимому, и очень длинное слово
       распирало бы контейнер. max-width возвращает перенос внутри слова. */
    max-width: 100%;
    transition:
        opacity 0.6s var(--ease-out),
        transform 0.6s var(--ease-out);
    transition-delay: calc(var(--w, 0) * 80ms);
}

/* Скрытое состояние включает скрипт. Задержка живёт в базовом правиле, а не в
   состоянии --shown: так каскад одинаково работает и на появление, и на
   случайный сброс состояния. */
.anim-title--armed .anim-title__word {
    opacity: 0;
    transform: translate3d(0, 0.45em, 0);
}

.anim-title--armed.anim-title--shown .anim-title__word {
    opacity: 1;
    transform: none;
}

/* --------------------------------------------------------------------------
   2. Первый экран, привязанный к прокрутке

   Значения transform и opacity пишет скрипт, здесь только продвижение слоёв.
   Класс anim-hero--live висит ровно столько, сколько герой на экране: держать
   продвинутыми текстовые слои первого экрана всю сессию незачем, а
   постоянный will-change — это постоянная занятая память.
   -------------------------------------------------------------------------- */

.hero.anim-hero--live .anim-drift {
    will-change: transform, opacity;
}

/* --------------------------------------------------------------------------
   3. Полоса под активной вкладкой программы

   Элемент создаёт скрипт, поэтому без JavaScript его нет вовсе. Позицию
   задаёт transform (translate3d + scaleX), ширина меняется только при
   «пересадке» и в transition не входит — то есть ширина не анимируется
   никогда. Клики полоса не перехватывает: она лежит на нижней кромке вкладки.
   -------------------------------------------------------------------------- */

.anim-tabs {
    position: relative;
}

.tabs-indicator {
    position: absolute;
    top: 0;
    left: 0;
    /* Полоса ложится на нижнюю кромку вкладки, внутри её рамки. Именно из-за
       этого её нельзя вынести под вкладки: на узком экране вкладки переносятся
       в три ряда, и полоса под первым рядом легла бы поверх второго. */
    height: 3px;
    background: linear-gradient(90deg, var(--accent-soft), var(--accent));
    /* Точка отсчёта одна и задана в базовом правиле: scaleX растёт вправо от
       левого края, поэтому смещение и ширина считаются независимо. */
    transform-origin: 0 50%;
    pointer-events: none;
    transition: transform 0.42s var(--ease-out), opacity 0.3s linear;
}

/* Пересадка на новое место (сменилась ширина окна или загрузился шрифт):
   переход выключен, полоса встаёт мгновенно. */
.tabs-indicator.is-static {
    transition: none;
}

/* --------------------------------------------------------------------------
   4. Залп на успешную заявку

   Контейнер фиксирован к экрану и не перехватывает клики; точки и кольцо —
   обычные span'ы, у которых в кадре меняются только transform и opacity.
   Частицы собираются вокруг центра контейнера отрицательными отступами,
   чтобы transform был чистым сдвигом без примеси процентов.
   -------------------------------------------------------------------------- */

.burst {
    position: fixed;
    inset: 0;
    z-index: 5;
    overflow: hidden;
    pointer-events: none;
}

.burst__dot,
.burst__ring {
    position: absolute;
    left: 50%;
    top: 50%;
    border-radius: 50%;
    opacity: 0;
    pointer-events: none;
}

.burst__dot {
    width: 6px;
    height: 6px;
    margin: -3px 0 0 -3px;
    background: var(--accent-soft);
}

.burst__ring {
    width: 46px;
    height: 46px;
    margin: -23px 0 0 -23px;
    border: 2px solid var(--accent-soft);
}

/* --------------------------------------------------------------------------
   Подстраховка на случай «меньше движения»

   Скрипт при этой настройке не запускается вовсе, поэтому правила ниже не
   должны срабатывать никогда. Они здесь как второй контур: если классы
   откуда-то возьмутся (кэш, сторонний код, отладка), содержимое всё равно
   останется видимым и неподвижным.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
    .anim-title--armed .anim-title__word {
        opacity: 1;
        transform: none;
    }

    .anim-title__word {
        transition: none;
    }

    .tabs-indicator,
    .burst {
        display: none;
    }
}
