/* Живая версия презентации ЖК HAYAT.
   Те же 20 страниц 1080×1920, что и в PDF, но вписаны в экран и оживают при пролистывании.
   Анимации — CSS scroll-driven, без библиотек.

   Ключевой приём: сцена (экран целиком) объявляет именованный таймлайн своей видимости
   view-timeline-name: --slide, и ВСЕ элементы страницы анимируются по нему.
   Иначе каждый элемент считал бы прогресс по своей раскладке, а страница внутри сцены
   уменьшена трансформом — раскладочные координаты не совпадают с видимыми, и порядок ломался. */

html { scroll-behavior: smooth; }
html, body { height: 100%; }
body {
  margin: 0;
  background: #DED6C8;
  background-image: radial-gradient(120% 80% at 50% 0%, #EFE7D8 0%, #D6CDBE 60%, #C7BDAC 100%);
  background-attachment: fixed;
  overflow-x: hidden;
  scroll-snap-type: y mandatory;
  overflow-y: auto;
}
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

/* ---------- сцена: страница вписывается в экран целиком ---------- */
.stage {
  position: relative;
  z-index: 2;
  height: 100svh;
  scroll-snap-align: center;
  scroll-snap-stop: always;
  overflow: hidden;
}
/* Страница крупнее сцены, а сцена — скролл-контейнер (overflow:hidden), поэтому grid-центрирование
   браузер делает «безопасным» и прижимает страницу к началу. Центрируем сами, абсолютно. */
.stage .page {
  position: absolute;
  left: 50%; top: 50%;
  margin: 0;
  flex: none;
  transform: translate(-50%, -50%) scale(var(--k));
  transform-origin: center center;
  box-shadow: 0 60px 120px -60px rgba(40, 30, 12, .85), 0 2px 0 rgba(255,255,255,.5);
  will-change: transform, opacity;
}
/* Коэффициент вписывания считает скрипт: CSS-деление вьюпорта даёт длину,
   а scale() требует безразмерное число. --k задаётся на :root при загрузке и ресайзе. */
:root { --k: 1; }

/* ---------- шкала прогресса сверху ---------- */
.rail { position: fixed; inset: 0 0 auto 0; height: 3px; z-index: 50; background: rgba(27,23,18,.10); }
.rail i {
  display: block; height: 100%; transform-origin: 0 50%;
  background: linear-gradient(90deg, #A87C2B, #E0BB6C);
  animation: railGrow linear both;
  animation-timeline: scroll(root block);
}
@keyframes railGrow { from { transform: scaleX(0); } to { transform: scaleX(1); } }

/* ---------- счётчик страниц ---------- */
.pager {
  position: fixed; right: 20px; top: 50%; transform: translateY(-50%); z-index: 50;
  display: flex; flex-direction: column; align-items: center; gap: 7px;
}
.pager b {
  font: 700 12px/1 -apple-system, "Segoe UI", Roboto, sans-serif;
  letter-spacing: .1em; color: #6E4F16; opacity: .75;
}
.pager u { display: block; width: 1px; height: 46px; background: rgba(27,23,18,.18); position: relative; }
.pager u::after {
  content: ''; position: absolute; left: -1px; width: 3px; border-radius: 2px;
  background: linear-gradient(180deg, #A87C2B, #E0BB6C);
  top: 0; height: 100%; transform-origin: 50% 0;
  animation: railGrowY linear both; animation-timeline: scroll(root block);
}
@keyframes railGrowY { from { transform: scaleY(0); } to { transform: scaleY(1); } }
/* на телефоне страница занимает всю ширину, а свой номер у неё есть в шапке */
@media (max-width: 900px) { .pager { display: none; } }


/* ---------- паспарту на широком экране ---------- */
.deco { position: fixed; inset: 20px; z-index: 40; pointer-events: none;
        box-shadow: inset 0 0 0 1px rgba(27,23,18,.10); border-radius: 4px; }
.deco::before, .deco::after {
  content: ''; position: absolute; width: 14px; height: 14px; border: 1px solid rgba(168,124,43,.55);
}
.deco::before { left: -1px; top: -1px; border-right: 0; border-bottom: 0; }
.deco::after  { right: -1px; bottom: -1px; border-left: 0; border-top: 0; }

/* название текущего раздела вертикально слева */
.side {
  position: fixed; left: 30px; top: 50%; transform: translateY(-50%) rotate(180deg); z-index: 45;
  writing-mode: vertical-rl; pointer-events: none;
  font: 700 11.5px/1 -apple-system, "Segoe UI", Roboto, sans-serif;
  letter-spacing: .28em; text-transform: uppercase; color: #8B8173;
  transition: opacity .5s ease;
}
.side b { color: #A87C2B; font-weight: 700; }

/* лёгкое зерно поверх фона — убирает «пластиковость» заливки */
body::after {
  content: ''; position: fixed; inset: 0; z-index: 0; pointer-events: none; opacity: .05;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='140'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/></filter><rect width='140' height='140' filter='url(%23n)'/></svg>");
}
@media (max-width: 900px) { .deco, .side { display: none; } body::after { opacity: .035; } }

/* подсказка «листайте» */
.hint {
  position: fixed; left: 50%; bottom: 18px; transform: translateX(-50%); z-index: 50;
  display: flex; align-items: center; gap: 10px;
  padding: 9px 16px; border-radius: 999px;
  background: rgba(255,252,246,.86); backdrop-filter: blur(10px);
  box-shadow: 0 8px 26px -14px rgba(40,30,12,.5), inset 0 0 0 1px rgba(27,23,18,.08);
  font: 600 12.5px/1 -apple-system, "Segoe UI", Roboto, sans-serif;
  letter-spacing: .12em; text-transform: uppercase; color: #574E42; white-space: nowrap;
  animation: hintOut linear both; animation-timeline: scroll(root block); animation-range: 0 6%;
}
.hint b { color: #A87C2B; }
.hint i { width: 7px; height: 7px; border-bottom: 1.5px solid #A87C2B; border-right: 1.5px solid #A87C2B;
          transform: rotate(45deg); margin-top: -3px; animation: nudge 1.6s ease-in-out infinite; }
@keyframes hintOut { to { opacity: 0; transform: translate(-50%, 14px); } }
@keyframes nudge { 0%,100% { transform: rotate(45deg) translate(0,0); } 50% { transform: rotate(45deg) translate(2px,2px); } }

/* ============================================================
   ПЕРЕХОД МЕЖДУ СТРАНИЦАМИ — привязан к пальцу (scroll-driven).
   Сцена объявляет именованный таймлайн своей видимости, страница едет по нему.
   ============================================================ */
@supports (animation-timeline: view()) {

  .stage { view-timeline-name: --slide; view-timeline-axis: block; }

  .stage .page {
    animation: pageThrough linear both;
    animation-timeline: --slide;
    animation-range: entry 0% exit 100%;
  }
  @keyframes pageThrough {
    0%   { opacity: 0; transform: translate(-50%, -50%) scale(calc(var(--k) * .88)) translateY(9%); }
    24%  { opacity: 1; }
    36%  { opacity: 1; transform: translate(-50%, -50%) scale(var(--k)) translateY(0); }
    68%  { opacity: 1; transform: translate(-50%, -50%) scale(var(--k)) translateY(0); }
    100% { opacity: 0; transform: translate(-50%, -50%) scale(calc(var(--k) * .92)) translateY(-7%); }
  }

  /* фон-кадр: наезд камеры на всём проходе сцены */
  .stage .bg img {
    animation: kenBurns linear both;
    animation-timeline: --slide;
    animation-range: entry 0% exit 100%;
  }
  @keyframes kenBurns {
    0%   { transform: scale(1.16) translateY(2%); }
    50%  { transform: scale(1.05) translateY(0); }
    100% { transform: scale(1.00) translateY(-2%); }
  }

  /* светлая плашка обложки чуть отстаёт от фона — глубина */
  .stage .cover__slab {
    animation: slabPar linear both;
    animation-timeline: --slide;
    animation-range: entry 0% exit 100%;
  }
  @keyframes slabPar { from { transform: translateY(3.2%); } to { transform: translateY(-3.2%); } }
}

/* ============================================================
   ВНУТРЕННИЙ СЦЕНАРИЙ СЛАЙДА — по времени, стартует когда слайд встал в экран.
   Так каскад доигрывается целиком даже на быстром свайпе телефона,
   тогда как привязка к скроллу проглатывала бы его за долю секунды.
   Начальные состояния включаются только при готовом скрипте (body.anim),
   поэтому без JS страница просто статична и полностью видна.
   ============================================================ */
body.anim .stage {
  --t: 1;            /* общий множитель длительности */
  --e: cubic-bezier(.16, 1, .3, 1);
}

/* ---------- заголовки: слова выезжают из-под маски ---------- */
body.anim .w { display: inline-block; overflow: hidden; vertical-align: top;
               padding: .12em 0 .18em; margin: -.12em 0 -.18em; }
/* сдвиг с запасом больше, чем поля маски, иначе из-под неё торчат верхушки букв */
body.anim .ww { display: inline-block; transform: translateY(140%); opacity: 0; filter: blur(4px); }
body.anim .stage.on .ww {
  animation: wordUp calc(1s * var(--t)) var(--e) both;
  animation-delay: calc(.14s + var(--i, 0) * .052s);
}
@keyframes wordUp {
  from { transform: translateY(140%); opacity: 0; filter: blur(4px); }
  60%  { filter: blur(0); }
  to   { transform: translateY(0);    opacity: 1; filter: none; }
}

/* ---------- общий подъём ---------- */
body.anim .stage .head, body.anim .stage .foot, body.anim .stage .kicker,
body.anim .stage .lead, body.anim .stage .capt, body.anim .stage .cover__slogan,
body.anim .stage .badge, body.anim .stage .pnum, body.anim .stage .cover__no,
body.anim .stage .feat, body.anim .stage .cont__i, body.anim .stage .steps li,
body.anim .stage .tbl tr, body.anim .stage .way, body.anim .stage .nums div,
body.anim .stage .poi li, body.anim .stage .cover__facts div,
body.anim .stage .cover__contacts span, body.anim .stage .plan figcaption,
body.anim .stage .gmap__cap {
  opacity: 0; transform: translateY(26px);
}
body.anim .stage.on .head, body.anim .stage.on .foot, body.anim .stage.on .kicker,
body.anim .stage.on .lead, body.anim .stage.on .capt, body.anim .stage.on .cover__slogan,
body.anim .stage.on .badge, body.anim .stage.on .pnum, body.anim .stage.on .cover__no,
body.anim .stage.on .feat, body.anim .stage.on .cont__i, body.anim .stage.on .steps li,
body.anim .stage.on .tbl tr, body.anim .stage.on .way, body.anim .stage.on .nums div,
body.anim .stage.on .poi li, body.anim .stage.on .cover__facts div,
body.anim .stage.on .cover__contacts span, body.anim .stage.on .plan figcaption,
body.anim .stage.on .gmap__cap {
  animation: riseUp calc(.9s * var(--t)) var(--e) both;
  animation-delay: var(--d, .3s);
}
@keyframes riseUp { from { opacity: 0; transform: translateY(26px); } to { opacity: 1; transform: none; } }

/* при склеенных границах линии принадлежат таблице, а не строке, и прозрачность строки
   их не прячет — разлиновка проступала до самих строк */
body.anim .stage .tbl { border-collapse: separate; border-spacing: 0; }

/* когда что выходит */
body.anim .stage .head            { --d: 0s; }
body.anim .stage .head { transform: translateY(-18px); }
body.anim .stage.on .head { animation-name: dropIn; }
@keyframes dropIn { from { opacity: 0; transform: translateY(-18px); } to { opacity: 1; transform: none; } }
body.anim .stage .pnum            { --d: .12s; }
body.anim .stage .badge           { --d: .5s; }
body.anim .stage .kicker          { --d: .1s; }
body.anim .stage .lead            { --d: .42s; }
body.anim .stage .capt            { --d: .5s; }
body.anim .stage .cover__slogan   { --d: .62s; }
body.anim .stage .cover__no       { --d: .9s; }
body.anim .stage .foot            { --d: .78s; }
body.anim .stage .gmap__cap       { --d: 1.1s; }
body.anim .stage .plan figcaption { --d: .78s; }

/* золотая линия у надстрочной метки прочерчивается */
body.anim .stage .kicker::after { transform: scaleX(0); transform-origin: 0 50%; }
body.anim .stage.on .kicker::after {
  animation: lineGrow calc(.85s * var(--t)) var(--e) both; animation-delay: .34s;
}
@keyframes lineGrow { from { transform: scaleX(0); } to { transform: scaleX(1); } }

/* ---------- кадры: раскрываются шторкой, картинка внутри доезжает ---------- */
body.anim .stage .ph, body.anim .stage .gmap, body.anim .stage .plan, body.anim .stage .aero {
  clip-path: inset(0 0 100% 0);
}
body.anim .stage.on .ph, body.anim .stage.on .gmap, body.anim .stage.on .plan, body.anim .stage.on .aero {
  animation: frameOpen calc(1.15s * var(--t)) cubic-bezier(.62, 0, .17, 1) both;
  animation-delay: var(--d, .3s);
}
@keyframes frameOpen { from { clip-path: inset(0 0 100% 0); } to { clip-path: inset(0 0 0 0); } }

body.anim .stage .ph img, body.anim .stage .aero img { transform: scale(1.22) translateY(3%); }
body.anim .stage.on .ph img, body.anim .stage.on .aero img {
  animation: imgSettle calc(1.9s * var(--t)) cubic-bezier(.18, .8, .24, 1) both;
  animation-delay: var(--d, .3s);
}
@keyframes imgSettle { from { transform: scale(1.22) translateY(3%); } to { transform: none; } }

/* блик проходит по кадру сразу после раскрытия */
body.anim .stage .ph::before, body.anim .stage .gmap::before, body.anim .stage .plan::before,
body.anim .stage .aero::before {
  content: ''; position: absolute; inset: -10%; z-index: 4; pointer-events: none; opacity: 0;
  background: linear-gradient(104deg, transparent 42%, rgba(255,255,255,.42) 50%, transparent 58%);
}
body.anim .stage.on .ph::before, body.anim .stage.on .gmap::before, body.anim .stage.on .plan::before,
body.anim .stage.on .aero::before {
  animation: sweep calc(1.25s * var(--t)) cubic-bezier(.3, .1, .2, 1) both;
  animation-delay: calc(var(--d, .3s) + .34s);
}
@keyframes sweep {
  0%   { opacity: 0; transform: translateX(-95%); }
  22%  { opacity: 1; }
  78%  { opacity: 1; }
  100% { opacity: 0; transform: translateX(95%); }
}
body.anim .stage .plan { overflow: hidden; }

/* ---------- иконки в карточках выщёлкивают ---------- */
body.anim .stage .feat i, body.anim .stage .cont__i i, body.anim .stage .poi li i {
  transform: scale(.55) rotate(-10deg); opacity: 0;
}
body.anim .stage.on .feat i, body.anim .stage.on .cont__i i, body.anim .stage.on .poi li i {
  animation: iconPop calc(.75s * var(--t)) cubic-bezier(.2, 1.5, .35, 1) both;
  animation-delay: calc(var(--d, .3s) + .1s);
}
@keyframes iconPop { from { transform: scale(.55) rotate(-10deg); opacity: 0; }
                     to   { transform: none; opacity: 1; } }

/* ---------- лесенки ---------- */
body.anim .stage .feats .feat:nth-child(1)  { --d: .62s; }
body.anim .stage .feats .feat:nth-child(2)  { --d: .70s; }
body.anim .stage .feats .feat:nth-child(3)  { --d: .78s; }
body.anim .stage .feats .feat:nth-child(4)  { --d: .86s; }
body.anim .stage .feats .feat:nth-child(5)  { --d: .94s; }
body.anim .stage .feats .feat:nth-child(6)  { --d: 1.02s; }

body.anim .stage .poi li:nth-child(1) { --d: .96s; }
body.anim .stage .poi li:nth-child(2) { --d: 1.02s; }
body.anim .stage .poi li:nth-child(3) { --d: 1.08s; }
body.anim .stage .poi li:nth-child(4) { --d: 1.14s; }
body.anim .stage .poi li:nth-child(5) { --d: 1.20s; }
body.anim .stage .poi li:nth-child(6) { --d: 1.26s; }
body.anim .stage .poi li:nth-child(7) { --d: 1.32s; }
body.anim .stage .poi li:nth-child(8) { --d: 1.38s; }

body.anim .stage .cont .cont__i:nth-child(1) { --d: .58s; }
body.anim .stage .cont .cont__i:nth-child(2) { --d: .66s; }
body.anim .stage .cont .cont__i:nth-child(3) { --d: .74s; }
body.anim .stage .cont .cont__i:nth-child(4) { --d: .82s; }
body.anim .stage .cont .cont__i:nth-child(5) { --d: .90s; }
body.anim .stage .cont .cont__i:nth-child(6) { --d: .98s; }

body.anim .stage .steps li:nth-child(1) { --d: .56s; }
body.anim .stage .steps li:nth-child(2) { --d: .68s; }
body.anim .stage .steps li:nth-child(3) { --d: .80s; }
body.anim .stage .steps li:nth-child(4) { --d: .92s; }
body.anim .stage .steps li:nth-child(5) { --d: 1.04s; }

body.anim .stage .ways .way:nth-child(1) { --d: .58s; }
body.anim .stage .ways .way:nth-child(2) { --d: .72s; }
body.anim .stage .ways .way:nth-child(3) { --d: .86s; }

body.anim .stage .nums div:nth-child(1) { --d: .5s; }
body.anim .stage .nums div:nth-child(2) { --d: .58s; }
body.anim .stage .nums div:nth-child(3) { --d: .66s; }
body.anim .stage .nums div:nth-child(4) { --d: .74s; }

body.anim .stage .tbl tr:nth-child(1) { --d: .82s; }
body.anim .stage .tbl tr:nth-child(2) { --d: .90s; }
body.anim .stage .tbl tr:nth-child(3) { --d: .98s; }
body.anim .stage .tbl tr:nth-child(4) { --d: 1.06s; }
body.anim .stage .tbl tr:nth-child(5) { --d: 1.14s; }

body.anim .stage .cover__facts div:nth-child(1) { --d: .74s; }
body.anim .stage .cover__facts div:nth-child(2) { --d: .82s; }
body.anim .stage .cover__facts div:nth-child(3) { --d: .90s; }
body.anim .stage .cover__facts div:nth-child(4) { --d: .98s; }
body.anim .stage .cover__contacts span:nth-child(1) { --d: 1.06s; }
body.anim .stage .cover__contacts span:nth-child(2) { --d: 1.14s; }

body.anim .stage .plans .plan:nth-child(1) { --d: .5s; }
body.anim .stage .plans .plan:nth-child(2) { --d: .64s; }
body.anim .stage .plans .plan:nth-child(3) { --d: .78s; }
body.anim .stage .duo .ph:nth-child(1) { --d: .44s; }
body.anim .stage .duo .ph:nth-child(2) { --d: .58s; }

/* крупные цифры и номера шагов набирают вес отдельно */
body.anim .stage .nums div b, body.anim .stage .way__n, body.anim .stage .steps li span,
body.anim .stage .cover__facts div b {
  display: inline-block; transform: translateY(14px) scale(.9); opacity: 0;
}
body.anim .stage.on .nums div b, body.anim .stage.on .way__n, body.anim .stage.on .steps li span,
body.anim .stage.on .cover__facts div b {
  animation: numIn calc(.9s * var(--t)) cubic-bezier(.2, 1.35, .35, 1) both;
  animation-delay: calc(var(--d, .3s) + .12s);
}
@keyframes numIn { from { transform: translateY(14px) scale(.9); opacity: 0; }
                   to   { transform: none; opacity: 1; } }


/* крупные цифры отсчитывают от нуля — значение подставляет скрипт,
   поэтому цифры не прыгают в ширине */
body.anim .stage .cnt { font-variant-numeric: tabular-nums; }


/* ---------- подписи на аэроснимке проступают после того, как кадр открылся ---------- */
body.anim .stage .apin, body.anim .stage .astreet, body.anim .stage .aero__cap,
body.anim .stage .aero__spot { opacity: 0; }
body.anim .stage .apin { transform: translate(-50%, -100%) scale(.86); }
body.anim .stage.on .aero__spot {
  animation: mapFade calc(1.2s * var(--t)) ease-out both; animation-delay: .95s;
}
body.anim .stage.on .apin {
  animation: pinPop calc(.8s * var(--t)) cubic-bezier(.2, 1.5, .4, 1) both;
  animation-delay: var(--pd, 1.1s);
}
@keyframes pinPop {
  from { opacity: 0; transform: translate(-50%, -100%) scale(.86); }
  to   { opacity: 1; transform: translate(-50%, -100%) scale(1); }
}
body.anim .stage .apin--home { transform: translate(-50%, -100%) scale(.8); --pd: .95s; }
body.anim .stage.on .apin--home {
  animation: homePinPop calc(.95s * var(--t)) cubic-bezier(.2, 1.5, .4, 1) both;
}
@keyframes homePinPop {
  from { opacity: 0; transform: translate(-50%, -100%) scale(.8); filter: blur(5px); }
  to   { opacity: 1; transform: translate(-50%, -100%) scale(1); filter: none; }
}
/* задержки меток заданы в разметке: nth-of-type здесь считает и другие div внутри кадра */
body.anim .stage.on .astreet {
  animation: streetIn calc(1s * var(--t)) var(--e) both; animation-delay: var(--sd, 1.5s);
}
@keyframes streetIn {
  from { opacity: 0; letter-spacing: .22em; }
  to   { opacity: 1; letter-spacing: .06em; }
}
body.anim .stage.on .aero__cap {
  animation: mapFade calc(.9s * var(--t)) ease-out both; animation-delay: 1.75s;
}

/* ---------- карта района ---------- */
body.anim .stage .gm-green, body.anim .stage .gm-build { opacity: 0; }
body.anim .stage.on .gm-green {
  animation: mapFade calc(1s * var(--t)) ease-out both; animation-delay: .62s;
}
body.anim .stage.on .gm-build {
  animation: mapFade calc(1.1s * var(--t)) ease-out both; animation-delay: .7s;
}
@keyframes mapFade { from { opacity: 0; } to { opacity: 1; } }

/* улицы прочерчиваются: длину каждой линии считает скрипт */
body.anim .stage .gm-rb path, body.anim .stage .gm-rm path { stroke-dashoffset: var(--L, 0); }
body.anim .stage.on .gm-rb path {
  animation: drawRoad calc(1.5s * var(--t)) cubic-bezier(.4, 0, .2, 1) both;
  animation-delay: calc(.72s + var(--i, 0) * .06s);
}
body.anim .stage.on .gm-rm path {
  animation: drawRoad calc(1.2s * var(--t)) cubic-bezier(.4, 0, .2, 1) both;
  animation-delay: calc(.86s + var(--i, 0) * .012s);
}
@keyframes drawRoad { to { stroke-dashoffset: 0; } }

/* метки на карте выскакивают по очереди, дом — первым и с пульсацией */
body.anim .stage .gdot, body.anim .stage .ghome { opacity: 0; transform: scale(.2); }
body.anim .stage.on .gdot {
  animation: dotPop calc(.7s * var(--t)) cubic-bezier(.2, 1.6, .4, 1) both;
  animation-delay: calc(1.24s + var(--i, 0) * .075s);
}
body.anim .stage.on .ghome {
  animation: dotPop calc(.85s * var(--t)) cubic-bezier(.2, 1.6, .4, 1) both;
  animation-delay: 1.1s;
}
@keyframes dotPop { from { opacity: 0; transform: scale(.2); } to { opacity: 1; transform: scale(1); } }

body.anim .stage.on .ghome::before {
  content: ''; position: absolute; inset: -14px; border-radius: 50%;
  box-shadow: 0 0 0 2px rgba(168,124,43,.45);
  animation: ping 2.6s cubic-bezier(.2,.7,.3,1) 1.9s infinite;
}
@keyframes ping { 0% { transform: scale(.6); opacity: .9; } 70%,100% { transform: scale(1.9); opacity: 0; } }

/* ---------- чертежи планировок проявляются как калька ---------- */
body.anim .stage .plan img { opacity: 0; filter: blur(6px); transform: scale(1.03); }
body.anim .stage.on .plan img {
  animation: blueprint calc(1.3s * var(--t)) ease-out both;
  animation-delay: calc(var(--d, .5s) + .22s);
}
@keyframes blueprint { from { opacity: 0; filter: blur(6px); transform: scale(1.03); }
                       to   { opacity: 1; filter: none; transform: none; } }

/* ---------- обложка ---------- */
body.anim .stage .cover__edge { clip-path: inset(0 100% 0 0); }
body.anim .stage.on .cover__edge {
  animation: edgeDraw calc(1.1s * var(--t)) cubic-bezier(.5, 0, .2, 1) both; animation-delay: .18s;
}
@keyframes edgeDraw { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }

body.anim .stage .frame { opacity: 0; }
body.anim .stage.on .frame { animation: mapFade calc(1.4s * var(--t)) ease-out both; animation-delay: .5s; }

body.anim .stage .badge i { transform: scale(0); }
body.anim .stage.on .badge i {
  animation: dotPop calc(.7s * var(--t)) cubic-bezier(.2, 1.6, .4, 1) both; animation-delay: .78s;
}

/* ============================================================
   ТЕЛЕФОН: страница мельче, поэтому шаги каскада крупнее и чуть быстрее,
   иначе движение читается как вялое.
   ============================================================ */
@media (max-width: 900px) {
  body.anim .stage { --t: .88; }
  body.anim .stage .head, body.anim .stage .foot, body.anim .stage .kicker,
  body.anim .stage .lead, body.anim .stage .capt, body.anim .stage .cover__slogan,
  body.anim .stage .feat, body.anim .stage .cont__i, body.anim .stage .steps li,
  body.anim .stage .tbl tr, body.anim .stage .way, body.anim .stage .nums div,
  body.anim .stage .poi li, body.anim .stage .cover__facts div,
  body.anim .stage .cover__contacts span { transform: translateY(34px); }
  @keyframes riseUp { from { opacity: 0; transform: translateY(34px); } to { opacity: 1; transform: none; } }
  body.anim .stage .ph::before, body.anim .stage .gmap::before, body.anim .stage .plan::before,
body.anim .stage .aero::before {
    background: linear-gradient(104deg, transparent 38%, rgba(255,255,255,.5) 50%, transparent 62%);
  }
}

/* ---------- уважение к системной настройке ---------- */
@media (prefers-reduced-motion: reduce) {
  body.anim .stage *, body.anim .stage *::before, body.anim .stage *::after { animation: none !important; }
  body.anim .stage .ww { transform: none; opacity: 1; }
  body.anim .stage .ph, body.anim .stage .gmap, body.anim .stage .plan,
  body.anim .stage .cover__edge { clip-path: none; }
  body.anim .stage .head, body.anim .stage .foot, body.anim .stage .kicker,
  body.anim .stage .lead, body.anim .stage .capt, body.anim .stage .cover__slogan,
  body.anim .stage .badge, body.anim .stage .pnum, body.anim .stage .cover__no,
  body.anim .stage .feat, body.anim .stage .cont__i, body.anim .stage .steps li,
  body.anim .stage .tbl tr, body.anim .stage .way, body.anim .stage .nums div,
  body.anim .stage .poi li, body.anim .stage .cover__facts div,
  body.anim .stage .cover__contacts span, body.anim .stage .plan figcaption,
  body.anim .stage .gmap__cap, body.anim .stage .plan img, body.anim .stage .frame,
  body.anim .stage .gm-green, body.anim .stage .gm-build, body.anim .stage .gdot,
  body.anim .stage .ghome, body.anim .stage .feat i, body.anim .stage .cont__i i {
    opacity: 1 !important; transform: none !important; filter: none !important;
  }
}

/* без поддержки scroll-driven страница остаётся статичной и целой */
@supports not (animation-timeline: view()) {
  .stage .page { opacity: 1; }
}
