/* ============================================================================
   ISELLPOWER · hero-scroll.css  (v309, база — v306)
   Одно-единственное: Hero-видео во весь экран, при прокрутке кадр собирается
   в карточку на своё обычное место. Больше ничего на сайте не меняется.

   Подключается ПОСЛЕДНИМ в <head> у index.html. Пара к assets/hero-scroll.js.
   Все правила живут внутри html.hs-on — если скрипт не загрузился,
   первый экран выглядит ровно как в v296.

   --hp: 0 — полноэкранный кадр, 1 — карточка на своём месте.
   Кадр НЕ привязан к колесу: первый же скролл переводит --hp из 0 в 1, а
   уменьшение играет само по времени, ровно одну секунду.

   Плавность держится на @property: обычная переменная не умеет перетекать
   между значениями, зарегистрированная — умеет, и один переход на --hp
   тянет за собой всё, что из него посчитано.

   Ширину и высоту экрана скрипт кладёт в --hs-vw/--hs-vh в пикселях:
   100vw врёт на ширину полосы прокрутки, 100vh — на адресную строку телефона.

   ── ЧТО ПОЧИНЕНО В v309 ────────────────────────────────────────────────────
   Дрожание под самый конец сборки кадра.

   Причина. Размер и положение кадра считаются в РАСКЛАДКЕ: ширина и высота
   окна, flex-basis слайда, отступ обёртки. Кривая cubic-bezier(.22,.61,.24,1)
   заканчивается почти горизонтально — последние ~200 мс кадр проходит меньше
   одного пикселя, то есть каждый кадр размер меняется на доли пикселя.
   Рисует браузер только по целым пикселям и вынужден округлять, а на долях
   округление скачет туда-сюда. Отсюда и ощущение «то ли рамка дрожит, то ли
   видео»: дрожит и то и другое сразу, потому что высота окна задаёт и рамку,
   и коробку видео внутри неё.

   Лечение — КВАНТОВАНИЕ: все величины, участвующие в раскладке, проходят
   через round() и ложатся на целые пиксели (шаг --hs-q). Кадр уменьшается
   ровными шажками, округлять больше нечего, дрожь пропадает. Шаг 2px на
   обычном экране — тогда и половина от него (кадр центрируется, то есть
   делится пополам) остаётся целой; на retina 1px, там половина пикселя и так
   ложится на целый пиксель матрицы.

   Второе: у окна стоял will-change:width,height. Ширина и высота — свойства
   раскладки, композитор их не умеет, толку от подсказки нет; зато окно
   уезжает в отдельный слой, а слой при каждом новом размере перевыделяется
   и перерисовывается целиком вместе с кадром видео. Убрано.

   Третье: точки и цифры под кадром двигались через bottom и top, то есть
   опять через раскладку. Переведены на сдвиг — на глаз то же самое.

   Внешне ничего не меняется: конечный кадр совпадает с v306 с точностью до
   пикселя округления.
   ============================================================================ */

@property --hp{
  syntax:"<number>";
  inherits:true;
  initial-value:0;
}

html.hs-on .hero{
  --hp:0;
  /* шаг квантования — см. шапку файла */
  --hs-q:1px;
  /* сколько кадр держится приклеенным к верху: за это время играет
     уменьшение, после — Hero отлипает и страница идёт дальше */
  --hs-run:30vh;
  --hs-r:26px;
  transition:--hp 1s cubic-bezier(.22,.61,.24,1);
  /* Конечный размер кадра. Проценты от экрана, с ограничением сверху —
     иначе на сверхшироком мониторе кадр уехал бы далеко за сетку сайта. */
  --hs-w:min(1700px, calc(var(--hs-vw) * .82));
  --hs-h:min(860px, calc(var(--hs-vh) * .78));
  /* место под цифрами: кадр смещается вверх ровно на столько, чтобы они влезли */
  --hs-sb:calc(96px * var(--hp));
  --hs-cw:calc(var(--hs-vw) - (var(--hs-vw) - var(--hs-w)) * var(--hp));
  --hs-ch:calc(var(--hs-vh) - (var(--hs-vh) - var(--hs-h)) * var(--hp));
  --hs-peek:calc(clamp(22px,3vw,44px) * var(--hp));
  --hs-hgap:calc(14px * var(--hp));
  --hs-rad:calc(var(--hs-r) * var(--hp));
  --hs-pad:clamp(28px,6vw,74px);
  padding:0 !important;
  margin:0 !important;
  min-height:0 !important;
  /* ВАЖНО: у .hero в базовом CSS стоит overflow:hidden — он ломает sticky */
  overflow:visible !important;
  height:calc(var(--hs-vh) + var(--hs-run));
}

/* На плотных экранах половина пикселя и так ложится на целый пиксель
   матрицы — можно шагать вдвое мельче */
@media(min-resolution:1.5dppx){
  html.hs-on .hero{--hs-q:.5px}
}

/* ── Квантование. Отдельным блоком: браузер, который не знает round(),
      просто возьмёт значения выше и будет вести себя как v306 ── */
@supports (width: round(3.4px, 1px)){
  html.hs-on .hero{
    --hs-sb:round(calc(96px * var(--hp)), var(--hs-q));
    --hs-cw:round(calc(var(--hs-vw) - (var(--hs-vw) - var(--hs-w)) * var(--hp)), var(--hs-q));
    --hs-ch:round(calc(var(--hs-vh) - (var(--hs-vh) - var(--hs-h)) * var(--hp)), var(--hs-q));
    /* полоска «Далее» и зазор между слайдами задают ширину слайда,
       то есть коробку видео — их тоже кладём на целые пиксели */
    --hs-peek:round(calc(clamp(22px,3vw,44px) * var(--hp)), var(--hs-q));
    --hs-hgap:round(calc(14px * var(--hp)), var(--hs-q));
    /* скругление задаёт форму обрезки: на дробном радиусе маска
       пересобирается каждый кадр и края слегка «кипят» */
    --hs-rad:round(calc(var(--hs-r) * var(--hp)), 1px);
  }
}

/* Обёртка становится «сценой»: прилипает к верху и держит кадр по центру */
html.hs-on .hero > .wrap{
  position:-webkit-sticky; position:sticky; top:0;
  height:var(--hs-vh);
  max-width:none !important;
  padding:0 !important;
  /* Прижимаем к левому верхнему углу и отводим кадр полями, а не
     центрированием. Центрирование делит свободное место ПОПОЛАМ, и половина
     нечётного числа — это половина пикселя: кадр всё время оказывался между
     пикселями, а браузер округлял то в одну, то в другую сторону. Раньше это
     обходилось шагом в 2px (чтобы половина оставалась целой), но тогда кадр
     уменьшался заметными двухпиксельными ступеньками. Теперь поля
     округляются сами, шаг можно взять в один пиксель экрана — и движение
     становится настолько плавным, насколько экран вообще позволяет. */
  display:flex; align-items:flex-start; justify-content:flex-start;
  padding-bottom:var(--hs-sb) !important;
}
html.hs-on .hero-window{
  margin-left:calc((var(--hs-vw) - var(--hs-cw)) / 2);
  margin-top:calc((var(--hs-vh) - var(--hs-sb) - var(--hs-ch)) / 2);
}
/* Округление полей — отдельным блоком ПОСЛЕ обычного правила: селекторы
   одинаковые, решает порядок (уже дважды на этом обжигался). */
@supports (width: round(3.4px, 1px)){
  html.hs-on .hero-window{
    margin-left:round(calc((var(--hs-vw) - var(--hs-cw)) / 2), var(--hs-q));
    margin-top:round(calc((var(--hs-vh) - var(--hs-sb) - var(--hs-ch)) / 2), var(--hs-q));
  }
}

html.hs-on .hero-window{
  width:var(--hs-cw);
  height:var(--hs-ch) !important;
  border-radius:var(--hs-rad);
  border-color:rgba(255,255,255,calc(.10 * var(--hp)));
  /* Тень раньше РОСЛА: и смещение, и радиус размытия считались от --hp.
     Размытие в 120px по периметру кадра 1180×700 браузер пересобирает
     заново при каждом новом радиусе, то есть шестьдесят раз в секунду.
     Теперь геометрия постоянная, меняется только прозрачность — конечный
     вид тот же, а работы на кадр почти нет. */
  box-shadow:
    0 50px 120px -46px rgba(0,0,0,calc(.92 * var(--hp))),
    0 2px 0 0 rgba(255,255,255,calc(.05 * var(--hp))) inset;
  /* полоска «Далее» справа и зазор между слайдами раскрываются вместе с рамкой */
  --peek:var(--hs-peek);
  --hgap:var(--hs-hgap);
  /* will-change:width,height убран намеренно — см. шапку файла */
  contain:layout;
  /* у окна в разметке класс .reveal с переходом transform/opacity .7s;
     появление уже отыграно (.in стоит сразу), но переход лучше снять —
     иначе он готов подхватить любое наше значение с задержкой */
  transition:none !important;
}
html.hs-on .hslide{border-radius:var(--hs-rad)}
/* Полоска «Далее» перекрывает и зазор между слайдами, и левые углы у неё
   прямые: при скруглении 26px в этих дугах выглядывал белый край второго
   слайда. Наружные углы всё равно обрезает само окно по overflow. */
html.hs-on .hero-peek{
  width:calc(var(--peek) + var(--hgap));
  border-radius:0 var(--hs-rad) var(--hs-rad) 0;
}
/* подложка окна — на случай любого шва между слайдами он будет чёрным */
html.hs-on .hero-window{background:#08080c}

/* Видео на полном экране чуть наехавшее — по мере сборки кадра отъезжает.
   Отдельным слоем: тогда наезд остаётся чистой работой видеокарты, а не
   перерисовкой кадра видео вместе со всем окном. */
html.hs-on .slide2-photo{
  transform:scale(calc(1 + .085 * (1 - var(--hp)))) translateZ(0);
  transform-origin:50% 46%;
  backface-visibility:hidden;
}

/* ── Почему видео вынуто из раскладки ──────────────────────────────────────
   Раньше видео растягивалось по слайду (inset:0 + object-fit:cover), а слайд
   ужимался вместе с рамкой. Значит коробка видео меняла размер каждый кадр, и
   браузер каждый раз заново вписывал в неё кадр ролика. Шаг у коробки целый
   пиксель, а картинка при этом должна была сдвинуться на его долю — отсюда
   мелкая тряска изображения ВНУТРИ рамки, при том что сама рамка едет ровно.

   Теперь коробка постоянная, во весь экран, а уменьшение делает transform:
   кадр ролика растрируется один раз, дальше его только двигает видеокарта.
   --hs-vk замеряет скрипт (см. measureShrink в hero-scroll.js): это доля, на
   которую слайд ужимается к концу сборки. Если скрипт почему-то не проставил
   переменную, initial-value 0 оставит видео во весь экран — не так красиво,
   но ничего не ломается. */
@property --hs-vk{syntax:'<number>';inherits:true;initial-value:0}

html.hs-on .hero-video{
  left:50%; top:50%; right:auto; bottom:auto;
  width:var(--hs-vw); height:var(--hs-vh);
  transform:
    translate(-50%,-50%)
    scale(calc((1 - var(--hs-vk) * var(--hp)) * (1 + .085 * (1 - var(--hp)))))
    translateZ(0);
  transform-origin:50% 50%;
  backface-visibility:hidden;
  will-change:transform;
}
/* у слайда 2 своя вечная анимация наезда — не перебиваем её на карточке */
html.hs-on .hslide.is-active .slide2-photo{transform:none}

/* Текст: на полном экране крупнее и отступает от края как по сетке сайта */
html.hs-on .hslide-content{
  padding-left:calc(var(--hs-pad) + (var(--hs-vw) - var(--hs-w)) / 2 * (1 - var(--hp)));
  padding-right:var(--hs-pad);
  max-width:calc(660px + 180px * (1 - var(--hp)));
}
html.hs-on .hslide-title{
  font-size:calc(clamp(2.3rem,3.6vw,3.4rem) * (1 + .30 * (1 - var(--hp))));
}
html.hs-on .hslide-sub{
  font-size:calc(clamp(1rem,1.3vw,1.1rem) * (1 + .16 * (1 - var(--hp))));
}
/* Текст тоже живёт в раскладке: на дробном кегле строка переливается, а
   дробная ширина каждый кадр заново решает, где перенести слово. Кегль
   кладём на полпикселя, отступ на пиксель, ширину на четыре — конечные
   значения (3.4rem, 660px) при этом остаются ровно теми же, что в v306.
   Блок стоит ПОСЛЕ обычных правил: селекторы одинаковые, решает порядок. */
@supports (width: round(3.4px, 1px)){
  html.hs-on .hslide-content{
    padding-left:round(calc(var(--hs-pad) + (var(--hs-vw) - var(--hs-w)) / 2 * (1 - var(--hp))), 1px);
    max-width:round(calc(660px + 180px * (1 - var(--hp))), 4px);
  }
  html.hs-on .hslide-title{
    font-size:round(calc(clamp(2.3rem,3.6vw,3.4rem) * (1 + .30 * (1 - var(--hp)))), .5px);
  }
  html.hs-on .hslide-sub{
    font-size:round(calc(clamp(1rem,1.3vw,1.1rem) * (1 + .16 * (1 - var(--hp)))), .5px);
  }
}

/* Точки приподняты, пока кадр во весь экран.
   Было bottom (раскладка) — стало сдвигом, на глаз то же самое. */
html.hs-on .hero-dots{
  bottom:22px;
  transform:translateY(calc(-34px * (1 - var(--hp))));
}

/* Цифры под кадром: прижаты влево по краю кадра, как и были.
   Выплывают из-под карточки, когда та почти собралась.
   top закреплён на конечном значении, всё движение — сдвигом. */
html.hs-on .hero-stats{
  position:absolute; left:50%;
  top:calc(50% - 48px + var(--hs-h) / 2 + 22px);
  width:var(--hs-w);
  margin:0 !important; padding:0 !important;
  justify-content:flex-start;
  transform:
    translateX(-50%)
    translateY(calc(
      26px * (1 - var(--hp))
      + (var(--hs-ch) - var(--hs-h)) / 2
      - (var(--hs-sb) - 96px) / 2
    ));
  opacity:clamp(0, calc((var(--hp) - .58) * 3.2), 1);
  transition:none;
}

/* Подсказка «Листайте» — по умолчанию выключена в скрипте (SCROLL_HINT) */
.hs-scroll{
  position:absolute; left:50%; bottom:24px; z-index:7;
  display:flex; flex-direction:column; align-items:center; gap:9px;
  transform:translateX(-50%);
  font-family:"JetBrains Mono",monospace; font-weight:300;
  font-size:.66rem; letter-spacing:.22em; text-transform:uppercase;
  color:rgba(255,255,255,.5); pointer-events:none; user-select:none;
  opacity:clamp(0, calc(1 - var(--hp) * 3.4), 1);
}
.hs-scroll i{display:block;width:1px;height:38px;overflow:hidden;background:rgba(255,255,255,.14);position:relative}
.hs-scroll i::after{content:"";position:absolute;left:0;top:-100%;width:1px;height:100%;
  background:linear-gradient(180deg,transparent,#fff);
  animation:hsDrop 2.1s cubic-bezier(.7,0,.3,1) infinite}
@keyframes hsDrop{0%{top:-100%}60%,100%{top:100%}}

/* ── Телефон: кадр собирается не по центру, а выше — под ним живут цифры ── */
@media(max-width:620px){
  html.hs-on .hero{
    --hs-run:24vh; --hs-r:20px;
    --hs-w:calc(var(--hs-vw) - 24px);
    --hs-h:calc(var(--hs-vh) * .60);
    --hs-sb:0px;
    --hs-pad:20px;
    --hs-off:calc((var(--hs-vh) - var(--hs-ch)) * .20);
  }
  html.hs-on .hero > .wrap{align-items:flex-start;padding-top:var(--hs-off) !important;padding-bottom:0 !important}
  html.hs-on .hero-window{margin-top:0}
  /* на телефоне слайды всегда во всю ширину — полоски «Далее» и зазора нет */
  html.hs-on .hero-window{--peek:0px;--hgap:0px}
  html.hs-on .hslide-content{padding-bottom:calc(112px - 56px * var(--hp))}
  html.hs-on .hslide-title{font-size:calc(1.78rem * (1 + .16 * (1 - var(--hp))))}
  html.hs-on .hslide-sub{font-size:calc(.86rem * (1 + .08 * (1 - var(--hp))))}
  /* Квантование для телефона — идёт ПОСЛЕ обычных правил, иначе они его
     перекроют: селекторы одинаковые, решает порядок */
  @supports (width: round(3.4px, 1px)){
    html.hs-on .hero{
      --hs-sb:0px;
      --hs-off:round(calc((var(--hs-vh) - var(--hs-ch)) * .20), var(--hs-q));
    }
    /* на телефоне текст во всю ширину — интерполировать нечего */
    html.hs-on .hslide-content{padding-left:20px;max-width:100%}
    html.hs-on .hslide-title{font-size:round(calc(1.78rem * (1 + .16 * (1 - var(--hp)))), .5px)}
    html.hs-on .hslide-sub{font-size:round(calc(.86rem * (1 + .08 * (1 - var(--hp)))), .5px)}
  }
  html.hs-on .hero-stats{
    left:0;
    top:calc(var(--hs-off) + var(--hs-ch) + 16px);
    transform:translateY(calc(20px * (1 - var(--hp))));
    width:var(--hs-vw); padding:0 20px !important;
  }
  html.hs-on .hero-dots{
    bottom:16px;
    transform:translateY(calc(-72px * (1 - var(--hp))));
  }
  .hs-scroll{bottom:16px;font-size:.6rem;letter-spacing:.18em}
}

/* ── Системная настройка «меньше движения»: всё как в v296 ── */
@media(prefers-reduced-motion:reduce){
  html.hs-on .hero{height:auto;padding:104px 0 64px !important;transition:none}
  html.hs-on .hero > .wrap{position:static;height:auto;display:block;max-width:1440px !important;padding:0 28px !important}
  html.hs-on .hero-window{width:auto;height:clamp(508px,69vh,712px) !important;border-radius:26px;
    margin:0;--peek:clamp(22px,3vw,44px);--hgap:14px}
  html.hs-on .hero-stats{position:static;transform:none;opacity:1;width:auto;margin-top:40px !important}
  html.hs-on .hero-dots{bottom:22px;transform:none}
  html.hs-on .hero-video,html.hs-on .slide2-photo{transform:none}
  .hs-scroll{display:none}
}
