/* ============================================================
   ABM Partner — СЛОЙ АНИМАЦИЙ
   Примитивы, которые используют блоки секций: появление при
   скролле, масковое появление текста, по-буквенный glow.
   ============================================================ */

/* ============================================================
   ПОЯВЛЕНИЕ ПРИ СКРОЛЛЕ
   Мягкий подъём + проявление. Без blur — он мылил текст и тормозил
   скролл. Задержку каскада задаём через --d в разметке.
   ============================================================ */
.reveal {
    --_rx: 0px;
    --_ry: 2rem;
    --_rs: 1;

    opacity: 0;
    transform: translate3d(var(--_rx), var(--_ry), 0) scale(var(--_rs));
    transition:
        opacity var(--dur-reveal) var(--ease-out) var(--d, 0s),
        transform var(--dur-reveal) var(--ease-out) var(--d, 0s);
    will-change: opacity, transform;
}

.reveal--visible {
    opacity: 1;
    transform: translate3d(0, 0, 0) scale(1);
    will-change: auto;
}

/* Направления/эффекты. Тайминг одинаковый — меняется только вектор. */
.reveal[data-reveal="left"]  { --_rx: -2.5rem; --_ry: 0; }
.reveal[data-reveal="right"] { --_rx: 2.5rem;  --_ry: 0; }
.reveal[data-reveal="up"]    { --_rx: 0;      --_ry: 2rem; }
.reveal[data-reveal="fade"]  { --_rx: 0;      --_ry: 0; }
.reveal[data-reveal="zoom"]  { --_rx: 0;      --_ry: 1rem; --_rs: 1.04; }

/* ============================================================
   МАСКОВОЕ ПОЯВЛЕНИЕ ТЕКСТА
   Слова заголовка поднимаются по одному из-под «шторки»
   (overflow:hidden), каскадно с маленькой задержкой.
   Размечается через data-reveal-text, слова раскладывает JS.
   ============================================================ */
.reveal-text__word {
    display: inline-block;
    overflow: hidden;
    vertical-align: top;
    padding-bottom: 0.14em;   /* не срезаем «р», «у», «ц» */
    margin-bottom: -0.14em;
    white-space: pre;
}

.reveal-text__word--block {
    display: block;
    white-space: normal;
}

.reveal-text__glyph {
    display: inline-block;
    will-change: transform;
    transform: translateY(128%);
    transition:
        transform var(--reveal-duration, 1.05s) cubic-bezier(0.19, 1, 0.22, 1) var(--td, 0s);
}

[data-reveal-text].reveal-text--on .reveal-text__glyph {
    transform: translateY(0);
}

/* ============================================================
   ПО-БУКВЕННЫЙ GLOW
   ============================================================ */
.glow {
    --glow-delay: 0.3s;
}

.glow__char {
    opacity: var(--glow-settle, 1);
}

.glow--play .glow__char,
.glow--play::before {
    animation: glow-in 0.15s both;
    animation-delay: calc(var(--glow-delay, 0s) + var(--i, 0) * 0.01s);
}

@keyframes glow-in {
    0%   { opacity: 0; }
    55%  { opacity: 1; text-shadow: 0 0 1.25rem rgba(255, 255, 255, 0.95); }
    75%  { opacity: 1; }
    100% { opacity: var(--glow-settle, 1); text-shadow: none; }
}

/* ============================================================
   ПАУЗА АНИМАЦИЙ ВНЕ КАДРА
   Секция, ушедшая из вьюпорта, не должна крутить бесконечные
   анимации (дыхание фото, плавающие чипы). Класс ставит motion.js.
   ============================================================ */
.is-idle,
.is-idle *,
.is-idle *::before,
.is-idle *::after {
    animation-play-state: paused !important;
}

/* ============================================================
   ДОСТУПНОСТЬ: prefers-reduced-motion
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
    .reveal {
        opacity: 1 !important;
        transform: none !important;
        transition: none !important;
    }
    .reveal-text__glyph {
        transform: none !important;
        transition: none !important;
    }
    .glow__char {
        opacity: 1 !important;
        animation: none !important;
    }
    .glow--play .glow__char {
        animation: none !important;
    }
}
