/* ============================================================
   Появление контента при скролле (scroll reveal) — сквозная анимация сайта.
   Работает в паре с assets/js/reveal.js: скрипт размечает «строительные блоки»
   страницы атрибутом data-reveal, наблюдает за ними через IntersectionObserver
   и при входе в экран ставит .is-in — элемент проявляется и доезжает на место.

   Почему так:
   • Появление сделано через @keyframes, а НЕ через transition. У компонентов
     сайта есть свои transition (.service-card — box-shadow/transform,
     .acc__item — фон и рамка): объявив transition здесь, мы бы их затирали,
     и блоки появлялись бы мгновенно, без анимации. animation — отдельное
     свойство, оно ничего не перебивает.
   • Двигаем отдельными CSS-свойствами translate/scale, а не transform —
     hover-эффекты компонентов используют transform, конфликта нет.
   • Скрытие висит ТОЛЬКО на [data-reveal], а атрибут ставит JS. Нет JS или он
     упал — ничего не скрыто, контент виден сразу (progressive enhancement).
   • После проигрыша JS снимает data-reveal/.is-in — элемент возвращается к
     чистым стилям, никаких «залипших» opacity/scale поверх hover-эффектов.
   • Старые браузеры без свойства translate деградируют до простого fade.

   Подключается ПОСЛЕДНИМ в <head> — после components.css и стилей страницы,
   чтобы правило [data-reveal] не перебивалось равными по весу селекторами.
   В HostCMS — то же место в корневом макете, после всех остальных стилей. */

:root {
    --reveal-dur:       .72s;                            /* текст и блоки */
    --reveal-dur-media: .9s;                             /* фото — чуть медленнее, «дороже» */
    --reveal-ease:      cubic-bezier(.22, .68, .28, 1);  /* быстрый старт, мягкое торможение */
    --reveal-shift:     28px;                            /* сдвиг снизу */
}

/* Исходное (скрытое) состояние. Ставится JS до первой отрисовки контента —
   пока держится заставка #page-loader, поэтому «прыжка» пользователь не видит. */
[data-reveal] { opacity: 0; }

/* Проигрыш — ставит JS при входе элемента в экран. Задержка «волны» приходит
   переменной --reveal-delay, both держит первый кадр до старта и последний после. */
[data-reveal].is-in {
    animation: reveal-up var(--reveal-dur) var(--reveal-ease) var(--reveal-delay, 0ms) both;
}

/* Фото и медиа-блоки: короткий подъём + едва заметный «наезд» масштаба. */
[data-reveal="media"].is-in {
    animation-name: reveal-media;
    animation-duration: var(--reveal-dur-media);
}

/* Остальные пресеты — для точечной ручной разметки (data-reveal="left" и т.п.). */
[data-reveal="down"].is-in  { animation-name: reveal-down; }
[data-reveal="left"].is-in  { animation-name: reveal-left; }
[data-reveal="right"].is-in { animation-name: reveal-right; }
[data-reveal="zoom"].is-in  { animation-name: reveal-zoom; }
[data-reveal="fade"].is-in  { animation-name: reveal-fade; }

@keyframes reveal-up {
    from { opacity: 0; translate: 0 var(--reveal-shift); }
    to   { opacity: 1; translate: 0 0; }
}
@keyframes reveal-media {
    from { opacity: 0; translate: 0 calc(var(--reveal-shift) * .6); scale: .97; }
    to   { opacity: 1; translate: 0 0; scale: 1; }
}
@keyframes reveal-down {
    from { opacity: 0; translate: 0 calc(var(--reveal-shift) * -.7); }
    to   { opacity: 1; translate: 0 0; }
}
@keyframes reveal-left {
    from { opacity: 0; translate: calc(var(--reveal-shift) * -1.2) 0; }
    to   { opacity: 1; translate: 0 0; }
}
@keyframes reveal-right {
    from { opacity: 0; translate: calc(var(--reveal-shift) * 1.2) 0; }
    to   { opacity: 1; translate: 0 0; }
}
@keyframes reveal-zoom {
    from { opacity: 0; scale: .94; }
    to   { opacity: 1; scale: 1; }
}
@keyframes reveal-fade {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* Мобильные: движение короче — на маленьком экране длинный сдвиг мешает читать. */
@media (max-width: 640px) {
    :root { --reveal-shift: 18px; --reveal-dur: .6s; --reveal-dur-media: .72s; }
}

/* Уважаем системную настройку «уменьшить движение»: JS в этом режиме вообще
   не размечает страницу, правило ниже — страховка на случай смены настройки
   уже после загрузки (медиазапрос переоценивается на лету). */
@media (prefers-reduced-motion: reduce) {
    [data-reveal] { opacity: 1; animation: none; }
}

/* Печать: документ должен выйти целиком, без учёта того, докрутили ли до блока. */
@media print {
    [data-reveal] { opacity: 1 !important; animation: none !important; }
}
