/* ============================================================
   Годовой отчёт 2025 — моушн.
   Правило: без JS и при prefers-reduced-motion страница полностью
   читается, просто ничего не двигается. Анимируем только
   transform и opacity.
   ============================================================ */

/* прогресс чтения */
.progress { position: fixed; top: 0; left: 0; right: 0; height: 3px; z-index: 60; pointer-events: none; }
.progress span {
	display: block; height: 100%; background: var(--sc-accent);
	transform: scaleX(0); transform-origin: 0 50%;
}

/* ---------- появления ---------- */
.js .reveal { opacity: 0; transform: translateY(26px); }
.js .reveal.is-in {
	opacity: 1; transform: none;
	transition: opacity .75s cubic-bezier(.16,1,.3,1), transform .75s cubic-bezier(.16,1,.3,1);
	transition-delay: var(--d, 0s);
}
.js .reveal--left  { transform: translateX(-34px); }
.js .reveal--right { transform: translateX(34px); }
.js .reveal--scale { transform: scale(.94); }

/* ---------- сцены ---------- */
/* по умолчанию (нет класса .scenes) сцена — обычный блок */
.scene__stage { padding-top: var(--sc-space-16); padding-bottom: var(--sc-space-16); }

.scenes .scene { position: relative; padding: 0; }
.scenes .scene__stage {
	position: sticky; top: var(--chrome, 0px); height: calc(100vh - var(--chrome, 0px));
	height: calc(100svh - var(--chrome, 0px));
	display: flex; flex-direction: column; align-items: center; justify-content: center;
	padding-top: 0; padding-bottom: 0; overflow: hidden;
}
.scenes .scene [data-in],
.scenes .scene [data-seq] {
	opacity: var(--q, 0);
	transform: translateY(calc((1 - var(--q, 0)) * 34px));
	will-change: opacity, transform;
}

/* сцена «ключевые цифры»: числа сменяют друг друга на одном месте */
.keys-stack { position: relative; width: 100%; }
.scenes .keys-stack { min-height: 340px; }
.scenes .keys-stack > .giant { position: absolute; inset: 0; margin: 0; display: flex; flex-direction: column; justify-content: center; }

/* обложка: работает и на телефоне, поэтому вынесена в отдельный режим .heroscene.
   Проезд длинный — на него нужно потратить несколько экранов прокрутки. */
.heroscene .scene--hero { position: relative; padding: 0; height: 340vh; }
.heroscene .scene--hero .scene__stage {
	position: sticky; top: var(--chrome, 0px); height: calc(100vh - var(--chrome, 0px));
	height: calc(100svh - var(--chrome, 0px));
	display: flex; flex-direction: column; align-items: center; justify-content: center;
	padding-top: 0; padding-bottom: 0; overflow: hidden;
}
.heroscene .scene--hero .scene__stage > .wrap { max-height: 100%; }
.heroscene .scene--hero .lead { font-size: var(--sc-text-minor); line-height: var(--sc-lh-minor); }

/* высоты прокрутки сцен */
.scenes .scene--keys   { height: 320vh; }
.scenes .scene--test   { height: 240vh; }
.scenes .scene--events { height: 300vh; }

/* обложка: длинная лента-конь едет вбок по мере прокрутки */
/* лента — прямой ребёнок сцены, поэтому сама занимает всю ширину экрана.
   Внутри .wrap её резал overflow колонки. */
.hero-band { width: 100%; overflow: hidden; margin: var(--sc-space-9) 0; }
/* конь развёрнут мордой вправо — он въезжает слева и уходит вправо */
.hero-band img { display: block; height: clamp(90px, 16vh, 170px); width: auto; max-width: none; transform: scaleX(-1); }
/* содержимое сцены не должно вылезать за экран */
.scenes .scene__stage > .wrap { max-height: 100%; overflow: hidden; }
.scenes .scene--hero .lead { font-size: var(--sc-text-minor); line-height: var(--sc-lh-minor); }
/* Конь проходит через весь экран: при загрузке его не видно совсем (он левее
   левого края), к концу сцены он целиком уходит за правый край. Отсчёт идёт
   от ширины экрана, поэтому на телефоне и на мониторе проезд выглядит одинаково. */
.heroscene .hero-band img {
	transform: translateX(calc(-100% + var(--p, 0) * (100% + 100vw))) scaleX(-1);
}
.heroscene .hero-year { transform: translateY(calc(var(--p, 0) * -22px)); }

/* тестирование: конь-змейка выезжает снизу вверх */
.snake { width: 100%; display: flex; justify-content: center; }
.snake__horse { width: min(620px, 78vw); height: auto; display: block; }
.scenes .snake__horse {
	/* открываем снизу вверх: сначала виден хвост, последней приходит голова */
	clip-path: inset(calc((1 - var(--p, 0)) * 100%) 0 0 0);
	transform: translateX(calc(var(--wob, 0) * 1px));
}

/* лента событий */
.strip-viewport { width: 100%; overflow: hidden; }
.scene__strip { display: flex; gap: var(--sc-space-6); padding: var(--sc-space-4) var(--sc-page-pad); }
/* без сцен лента листается пальцем/трекпадом */
:not(.scenes) .strip-viewport { overflow-x: auto; scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch; }
:not(.scenes) .scene__strip > * { scroll-snap-align: center; }

.evcard {
	flex: 0 0 300px; background: var(--sc-white); border: var(--sc-hairline);
	display: flex; flex-direction: column;
	color: inherit; text-decoration: none;
	transition: border-color .3s ease, transform .3s ease;
}
.evcard:hover { border-color: var(--sc-accent); transform: translateY(-3px); }
.evcard:focus-visible { outline: 2px solid var(--sc-accent); outline-offset: 3px; }
.evcard .body { flex: 1 1 auto; display: flex; flex-direction: column; }
.evcard .tglink {
	margin-top: auto; padding-top: var(--sc-space-4);
	font-weight: 500; font-size: var(--sc-text-caps); letter-spacing: var(--sc-tracking-caps);
	text-transform: uppercase; color: var(--sc-accent);
}
.evcard img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; display: block; }
.evcard .body { padding: var(--sc-space-5) var(--sc-space-6) var(--sc-space-6); }
.evcard .when {
	font-weight: 500; font-size: var(--sc-text-caps); letter-spacing: var(--sc-tracking-caps);
	text-transform: uppercase; color: var(--sc-accent);
}
.evcard .what { margin-top: var(--sc-space-2); font-size: var(--sc-text-minor); line-height: var(--sc-lh-minor); }
.evcard:hover .tglink { text-decoration: underline; }

/* ---------- полное выключение движения ---------- */
@media (prefers-reduced-motion: reduce) {
	html { scroll-behavior: auto; }
	.js .reveal { opacity: 1 !important; transform: none !important; transition: none !important; }
	.scene, .scene__stage { position: static !important; height: auto !important; }
	.scene [data-in], .scene [data-seq] { opacity: 1 !important; transform: none !important; }
	.hero-band img { transform: scaleX(-1) !important; }
	.snake__horse { transform: none !important; clip-path: none !important; }
	.scene__strip { transform: none !important; }
	.strip-viewport { overflow-x: auto !important; }
	.progress { display: none; }
}

/* ---------- адаптив 2026-09 ---------- */
/* Обложка на телефоне: проезд коня короче — три экрана пустой прокрутки
   на маленьком экране читаются как «страница зависла». */
@media (max-width: 620px) {
	.heroscene .scene--hero { height: 220vh; }
	.hero-band { margin: var(--sc-space-6) 0; }
}
/* Карточки событий не шире экрана */
@media (max-width: 620px) {
	.evcard { flex: 0 0 min(300px, 78vw); }
	.scene__strip { gap: var(--sc-space-4); }
}
/* Лента-коню ширина не ограничена намеренно: он едет внутри .hero-band
   с overflow: hidden, поэтому глобальное правило img { max-width: 100% }
   для него отключено. */
.hero-band img { max-width: none; }

/* ---------- сцены: содержимое обязано помещаться в экран ----------
   У «залипающей» сцены высота жёсткая — calc(100svh - шапка), а .wrap
   режет всё лишнее по overflow: hidden. Пока внутри стояли обычные блоки,
   сумма их высот (заголовок + иллюстрация + число) на ноутбучном экране
   получалась больше этой высоты, и нижний элемент — крупное число —
   обрезался. Лечим не отступами, а раскладкой: делаем .wrap колонкой-флексом
   и разрешаем ужиматься только картинке. Число и заголовок всегда целые. */
.scenes .scene--test .wrap,
.scenes .scene--keys .wrap {
	display: flex; flex-direction: column; align-items: center; justify-content: center;
	height: 100%; gap: var(--sc-space-6);
	padding-top: var(--sc-space-6); padding-bottom: var(--sc-space-6);
}
.scenes .scene--test h2,
.scenes .scene--keys h2 { flex: 0 0 auto; margin-bottom: 0; }
/* Единственный гибкий элемент сцены «тестирование» — лента-конь.
   flex: 1 1 0 отдаёт ей всю свободную высоту и делает эту высоту
   определённой — только поэтому max-height: 100% у картинки вообще
   срабатывает (в процентах от auto-высоты он игнорируется). Ширина
   и высота auto — пропорции картинка держит сама, без магических чисел. */
.scenes .scene--test .snake { flex: 1 1 0; min-height: 0; width: 100%; align-items: center; }
.scenes .scene--test .snake__horse {
	width: auto; height: auto;
	max-width: min(620px, 78vw);
	max-height: 100%;
}
.scenes .scene--test .giant { flex: 0 0 auto; margin: 0; }
/* в «ключевых цифрах» свободную высоту забирает стопка чисел */
.scenes .scene--keys .keys-stack { flex: 1 1 auto; min-height: 0; }

/* ---------- лента событий: карточка тоже обязана помещаться в экран ----------
   Тот же корень, что у сцены «тестирование», но цепочка длиннее.
   .strip-viewport — флекс-элемент «залипающей» сцены, и у него overflow: hidden,
   из-за чего его автоминимум равен нулю: на невысоком окне он спокойно ужимается
   до 409px. А лента внутри остаётся блоком с высотой по содержимому (527px),
   потому что высоту ей никто не передал: картинка карточки живёт по своему
   aspect-ratio: 4/3, текст с ссылкой — по своему. Разницу съедает overflow:
   у всех карточек разом срезается нижняя строка «смотреть в телеграме →».
   Чинится передачей определённой высоты вниз по цепочке: viewport → лента →
   карточка → картинка. Гибкая в карточке только картинка; блок с текстом
   и ссылкой зафиксирован и не режется никогда. */
.scenes .strip-viewport { display: flex; flex-direction: column; min-height: 0; }
.scenes .scene__strip { flex: 1 1 auto; min-height: 0; }
/* flex-basis: auto — на высоком экране картинка остаётся ровно 4:3, как раньше,
   и только на низком ужимается; object-fit: cover уже стоит, кадр не искажается */
.scenes .evcard img { flex: 0 1 auto; min-height: 0; }
.scenes .evcard .body { flex: 0 0 auto; }
