/* ============================================================================
   ГУСІ — секции (десктоп 1920)
   Все координаты и размеры — из Figma, выражены в юнитах макета (--u).
   ========================================================================= */

/* ══════════════════════════════════════════════════════════════════════
   1 · HERO
   ═══════════════════════════════════════════════════════════════════ */
.section--hero {
  background: var(--c-paper);
  height: max(100vh, calc(1080 * var(--u)));
  display: flex;
  align-items: center;
}

.section--hero .stage {
  flex: none;
}

/* Гусь — изображение из макета, кадрируется своей коробкой */
.hero__goose {
  overflow: hidden;
}

.hero__photo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Живые слои гуся — вырезанные из фото шалик и глаз плюс «заплатки» под
   ними (см. tools/hero-layers.py). Заплатки неподвижны, двигаются только
   вырезки; кликов на себя не берут — под ними лежит сам первый экран. */
.hero__part,
.hero__scarf,
.hero__eye {
  pointer-events: none;
}

/* Шалик — не вырезанная лента, а прямоугольник кадров из видео поверх
   фото (см. tools/hero-layers.py). Внутри него всё нарисовано правильно
   в каждом кадре, включая то, как ткань изгибается; края растушёваны
   маской, а под ними то же самое изображение — шва не видно.

   Кадров два слоя, а не один: между соседними позами идёт кроссфейд.
   Тридцати трёх кадров на весь размах хватает по форме, но не по
   плавности — переключение читалось бы ступеньками; смешивание двух
   соседних поз даёт непрерывный ход, а расходятся они на 0.6°. */
.hero__scarf {
  -webkit-mask-image: url("../assets/hero/scarf-mask.png");
          mask-image: url("../assets/hero/scarf-mask.png");
  -webkit-mask-size: 100% 100%;
          mask-size: 100% 100%;
}

.hero__scarf-frame {
  position: absolute;
  inset: 0;
  background-image: url("../assets/hero/scarf-sheet.webp");
  background-repeat: no-repeat;
  /* Кадры лежат сеткой: лист во столько раз больше коробки, сколько в нём
     столбцов и строк, а положение фона выбирает клетку. Полосой их не
     разложить — 33 кадра дали бы 8844 px ширины, а у части мобильных GPU
     предел текстуры 4096. */
  background-size: calc(var(--cols) * 100%) calc(var(--rows) * 100%);
}

/* Коробка шалика — цель наведения: «соприкосновение с шарфиком».
   Указатель ей нужен только за этим, поэтому включается отдельно и
   только там, где наведение вообще есть. */
@media (hover: hover) and (pointer: fine) {
  .hero__scarf { pointer-events: auto; }
}

/* Белая дымка под заголовком (Figma Rectangle 15: white .8, blur 50).
   Гауссов blur(50) большого прямоугольника — самая дорогая отрисовка на
   первом экране, поэтому он заменён точным градиентным эквивалентом:
   коробка расширена на 150 юнитов в каждую сторону (туда уходил бы блюр),
   а стопы — значения erf-профиля того же σ=50. Разница с фильтром меньше
   1/255 по альфе, но паинт становится обычной заливкой. */
.hero__haze {
  background: linear-gradient(180deg,
    rgba(255, 255, 255, 0.001) 0%,
    rgba(255, 255, 255, 0.018) 7.1%,
    rgba(255, 255, 255, 0.127) 14.2%,
    rgba(255, 255, 255, 0.247) 17.8%,
    rgba(255, 255, 255, 0.400) 21.3%,
    rgba(255, 255, 255, 0.553) 24.9%,
    rgba(255, 255, 255, 0.673) 28.4%,
    rgba(255, 255, 255, 0.782) 35.6%,
    rgba(255, 255, 255, 0.799) 42.7%,
    rgba(255, 255, 255, 0.800) 49.8%,
    rgba(255, 255, 255, 0.799) 57.3%,
    rgba(255, 255, 255, 0.782) 64.4%,
    rgba(255, 255, 255, 0.673) 71.6%,
    rgba(255, 255, 255, 0.553) 75.1%,
    rgba(255, 255, 255, 0.400) 78.7%,
    rgba(255, 255, 255, 0.247) 82.2%,
    rgba(255, 255, 255, 0.127) 85.8%,
    rgba(255, 255, 255, 0.018) 92.9%,
    rgba(255, 255, 255, 0.001) 100%);
}

/* Заголовок и подзаголовок центрируются в своей коробке из макета */
.hero__title,
.hero__sub {
  text-align: center;
}

/* Граница первого экрана и второго блока (Figma Rectangle 23, 111:18).
   Это не просто полоса, а лента беларускага арнаменту: тот же мотив
   рушніка, что сыплется по бокам первого экрана, только положенный
   поперёк. Градиент из макета остался под ним подложкой — он и задаёт
   ленте ход от сиреневого слева к белому справа.

   Мотив кладётся своей пропорцией: звено 66×80, значит при высоте
   полосы 25 юнитов шаг повтора — 25 × 66/80 = 20.625. Выводить ширину
   из `auto 100%` нельзя: браузер округляет её до целого пикселя, и на
   1800 юнитах лента разъезжается на целый мотив к правому краю.

   Лента живёт в ::after, а не в самом фоне: под ней должен просвечивать
   градиент, а две картинки в одном background-image легли бы друг на
   друга без возможности задать общую непрозрачность только верхней. */
.hero__bar {
  background: var(--grad-h);
}

.hero__bar::after {
  content: "";
  position: absolute;
  inset: 0;
  background: url("../assets/ornament/ornament-tile-h.png") repeat-x
    center / calc(20.625 * var(--u)) 100%;
  opacity: 0.75;
}

/* ══════════════════════════════════════════════════════════════════════
   2 · БІРУЛЬКА
   ═══════════════════════════════════════════════════════════════════ */
.section--birulka {
  background: var(--c-paper);
}

/* Коробка гуся кадрирует композицию: плита выше коробки на 32 юнита с
   каждой стороны — ровно та подрезка, которую раньше делал object-fit:
   cover у фото и видео. */
.birulka__goose {
  overflow: hidden;
}

.birulka__plate {
  object-fit: fill;
}

/* Черты головы — клюв и глаза. Их возит js по формуле шара, а клики они
   на себя не берут: под ними лежит сама секция. */
.birulka__part {
  pointer-events: none;
  will-change: transform;
}

/* Хвост шалика: два слоя кадров с кроссфейдом между соседними позами —
   та же механика, что у шалика на первом экране. Края окна растушёваны
   маской, под ним та же самая картинка, поэтому шва не видно. */
.birulka__scarf {
  -webkit-mask-image: url("../assets/birulka/scarf-mask.png");
          mask-image: url("../assets/birulka/scarf-mask.png");
  -webkit-mask-size: 100% 100%;
          mask-size: 100% 100%;
  pointer-events: none;
}

.birulka__scarf-frame {
  position: absolute;
  inset: 0;
  background-image: url("../assets/birulka/scarf-sheet.webp");
  background-repeat: no-repeat;
  /* Кадры лежат сеткой: лист во столько раз больше коробки, сколько в нём
     столбцов и строк, а положение фона выбирает клетку. */
  background-size: calc(var(--cols) * 100%) calc(var(--rows) * 100%);
}

.birulka__sub {
  text-align: center;
}

/* ══════════════════════════════════════════════════════════════════════
   3 · НАШЫ БІРУЛЬКІ
   ═══════════════════════════════════════════════════════════════════ */
.section--keychains {
  background: var(--c-paper);
}

/* Кадр карусели. Обрезка нужна именно здесь: карточки уезжают за края
   сцены и приходят из-за краёв, и убирать их обязана сама карусель.
   Секция для этого не годится — она шире сцены на экранах от 1920, и
   заэкранная карточка выезжала бы в поле рядом с макетом.

   Режем только ПО ГОРИЗОНТАЛИ: в мобильном фрейме карточка мерча
   нарочно свисает за низ секции (носок выходит на 70 юнитов ниже), и
   обрезка по вертикали срезала бы его. Пара clip/visible — единственная,
   которая это даёт: у overflow значение visible превращается в auto,
   если по другой оси стоит hidden, и вместо обрезки получилась бы
   прокрутка. Рядом с clip такой подмены нет, обе оси остаются как
   написаны. */
.carousel {
  position: absolute;
  inset: 0;
  z-index: 3;
  overflow-x: clip;
  overflow-y: visible;

  /* Горизонталь карусель разбирает сама (js/carousel.js, свайп), вертикаль
     остаётся странице. Без этого браузер забирает горизонтальное движение
     себе — как заготовку под собственную прокрутку — и обрывает жест
     событием pointercancel на первых же пикселях. */
  touch-action: pan-y;
}

.carousel__track {
  position: absolute;
  inset: 0;
}

.key {
  z-index: 1;
}

/* Экспорты слайдов непрозрачно белые по полям, а в макете хвост шалика
   центрального гуся заходит на область соседа справа. Поэтому центральный
   слайд лежит выше — иначе сосед закрывает ему хвост белым.

   Класс, а не :nth-child(2): на время листания в трек добавляется двойник
   входящей карточки, и порядковый номер перестал бы значить «средний». */
.key--mid {
  z-index: 2;
}

.key__img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: center;
}

/* Экспорты в static/ обрезаны по содержимому и уже своих фреймов в Figma:
   photo.png — на 73px слева, Frame 8.png — на 102px справа. Компенсация
   этой обрезки живёт в js (js/carousel.js, FRAMES): она принадлежит файлу,
   а не слоту. Раньше она стояла здесь, на слотах, — и при листании ехала
   не с той картинкой: гусь, попав в чужой слот, уползал от центра. */

/* ══════════════════════════════════════════════════════════════════════
   4 · ДЫЗАЙН ГУСЕЙ
   ═══════════════════════════════════════════════════════════════════ */
.section--design {
  background: var(--c-paper);
}

.design__panel {
  background: var(--grad-panel);
}

.dcard {
  overflow: hidden;
  background: var(--c-paper);
  border-radius: var(--card-radius);
  z-index: 1;
  /* Тень наведения живёт в css, а не в GSAP: box-shadow — не transform,
     за него ни с чем бороться не надо (см. designHover в animations.js). */
  transition: box-shadow var(--dur-base) var(--ease-out);
}

/* Класс ставит js на pointerenter — вместе с подъёмом и наклоном. */
.dcard.is-lit {
  z-index: 3;
  box-shadow: 0 calc(22 * var(--u)) calc(52 * var(--u)) rgba(169, 109, 205, 0.32);
}

.dcard__img {
  object-fit: contain;
  object-position: center bottom;
}

.dcard__brush {
  z-index: 2;
}

/* ══════════════════════════════════════════════════════════════════════
   5 · БЕЛАРУСКІЯ ТРАДЫЦЫІ
   ═══════════════════════════════════════════════════════════════════ */
.section--traditions {
  background: var(--c-paper);
}

/* Здесь градиент горизонтальный и доходит до белого на 100% —
   проверено по пикселям макета: по вертикали цвет постоянный. */
.trad__panel {
  background: var(--grad-h);
}

/* Рамка фото: её белая заливка и закрывает левый край панели — так в
   макете. Рамка стоит намертво, ездит только картинка внутри неё. */
.trad__photo {
  overflow: hidden;
  background: var(--c-paper);
}

.trad__photo-img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: center;
}

/* ══════════════════════════════════════════════════════════════════════
   6 · БОЛЬШ АРЫГІНАЛЬНАГА МЕРЧУ
   ═══════════════════════════════════════════════════════════════════ */
.section--merch {
  background: var(--c-paper);
}

.mcard {
  overflow: visible;
  background: var(--grad-panel);
  border-radius: var(--card-radius);
  z-index: 1;
}

.mcard__img {
  object-fit: cover;
  border-radius: var(--card-radius);
}

/* Носок из макета лежит ПОД изображением футболки и на десктопе не виден
   (в Figma его перекрывает фрейм «майка»). Показывается только на мобиле,
   где он и есть содержимое карточки. */
.mcard__hang {
  display: none;
  object-fit: contain;
  object-position: center bottom;
  z-index: 2;
  pointer-events: none;
}

.mcard--hero {
  z-index: 2;
}

/* ══════════════════════════════════════════════════════════════════════
   7 · ПАДВАЛ
   Белая база + две панели одного и того же градиента: нижняя на полной
   непрозрачности (Figma Rectangle 28), верхняя на 50% (Rectangle 53),
   обе со скруглением 50.
   Сверено по пикселям экспорта всей страницы: сверху rgb(203,166,224),
   снизу rgb(251,249,252) — сходится с расчётом наложения двух слоёв.
   ═══════════════════════════════════════════════════════════════════ */
/* Раскрытие подвала: он зафиксирован под контентом, контент уезжает вверх
   и открывает его. Это та же механика, что на bugatti.com.

   Подвал занимает кадр макета целиком — 1920×1080, фрейм 2089:53, — и во
   всю ширину окна. Высоту и юнит композиции задаёт одно число, --footer-k;
   при 1 подвал живёт в тех же юнитах, что и вся страница, и координаты из
   Figma работают как есть.

   Пропорцию кадра сцена держит сама (1920×1080), поэтому композиции не
   нужно цепляться за низ окна: раньше сцена растягивалась в 100vh, и на
   окне не 16:9 гуси со словом уезжали от нижней границы — их приходилось
   привязывать к ней вручную. */
#scroll-content {
  position: relative;
  z-index: 1;
  /* Ровно столько, сколько занимает подвал: это и есть окно его раскрытия. */
  margin-bottom: var(--footer-h);
  background: var(--c-paper);
}

.section--footer {
  /* Юнит подвала — доля страничного, задаётся одним числом --footer-k.
     При 1 (кадр макета целиком) он равен страничному. */
  --u: calc(var(--u-page) * var(--footer-k));

  /* Кегль и скругление объявлены на :root и ТАМ ЖЕ посчитаны: подстановка
     var() в значение своей переменной происходит на том элементе, где
     переменная объявлена, а вниз уходит уже готовая длина. Поэтому свой
     --u подвала до них не дотягивается, и их приходится объявить заново —
     теми же формулами, но здесь. Без этого «ГУСІ» осталось бы в 800
     страничных юнитов и не влезло в укороченный подвал. */
  --fs-display: calc(800 * var(--u));
  --panel-radius: calc(50 * var(--u));

  position: fixed;
  left: 0;
  bottom: 0;
  width: 100%;
  height: var(--footer-h);
  background: var(--c-paper);
  z-index: 0;
}

/* Сцена и есть подвал: во всю ширину окна, скругление и обрез — на ней.
   «ГУСІ» в макете свисает за нижнюю границу кадра, обрез эту подрезку и
   повторяет. */
.section--footer .stage {
  width: 100%;
  height: var(--footer-h);
  overflow: hidden;
  border-radius: var(--panel-radius);
}

/* Сцена шире композиции, поэтому композиция держится за края кадра, а не
   за его координаты: левый гусь и соцсети — за левый край, правый гусь —
   за правый (1920−1581−285=54), слово — за центр. Те же числа Figma,
   просто отсчитанные от того края, к которому элемент прижат. */
.footer__duck--r {
  left: auto;
  right: calc(54 * var(--u));
}

.footer__wordmark {
  left: calc(50% - 512 * var(--u));
}

.footer__glow {
  position: absolute;
  inset: 0;
  background: var(--grad-panel);
}

/* Второй слой того же градиента — как в макете */
.footer__glow::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--grad-panel);
  opacity: 0.5;
  border-radius: inherit;
}

/* «Фонарик» подвала — ровно та механика, что на bugatti.com: гигантское
   слово там не подсвечивают сверху, а вырезают маской. Мягкий круг маски
   едет за курсором, и надпись существует только внутри круга.
   Разница со старой версией принципиальная: маска трогает одно слово,
   а не всю сцену, поэтому фон, гуси и соцсети остаются как в макете.

   Стопы — как у оригинала: непрозрачно в центре, в ноль на 60% радиуса.
   Радиус по умолчанию (farthest-corner) считается от коробки, поэтому
   пятно само масштабируется под размер подвала. */
.footer__torch {
  position: absolute;
  inset: 0;
  --torch-x: 0%;
  --torch-y: 50%;
  -webkit-mask-image: radial-gradient(circle at var(--torch-x) var(--torch-y),
    rgb(0, 0, 0) 0%, rgba(0, 0, 0, 0) 60%);
          mask-image: radial-gradient(circle at var(--torch-x) var(--torch-y),
    rgb(0, 0, 0) 0%, rgba(0, 0, 0, 0) 60%);
  pointer-events: none;
}

/* Без курсора светить нечем — слово показывается целиком, как в макете. */
@media (pointer: coarse), (prefers-reduced-motion: reduce) {
  .footer__torch {
    -webkit-mask-image: none;
            mask-image: none;
  }
}

.footer__social {
  position: absolute;
  inset: 0;
}

.footer__social-link {
  display: block;
  transition: opacity var(--dur-fast) var(--ease-out);
}

.footer__social-link img {
  width: 100%;
  height: 100%;
}

.footer__social-link:hover {
  opacity: 0.6;
}

.footer__duck {
  object-fit: contain;
}

/* Гигантское «ГУСІ» — маска по строке, буквы выезжают снизу */
.footer__wordmark {
  overflow: hidden;
  line-height: 0;
}

/* Тон букв задаёт только альфа цвета: в макете это ровно rgba(169,109,205,.5)
   поверх градиента подвала. Дополнительный opacity здесь гасил слово до
   эффективных .35 — на живой странице оно выходило заметно бледнее макета,
   а в режиме сверки этого не было видно, потому что там opacity сбрасывается
   в 1 через !important. */
.footer__wordmark-inner {
  display: block;
  color: rgba(169, 109, 205, 0.5);
  white-space: nowrap;
}

/* Буквы разбиваются в js и едут из-под маски каждая со своим сдвигом */
.footer__wordmark-inner .ch {
  will-change: transform;
}

/* Привязок композиции к низу кадра и растягивания сцены шире 1920 здесь
   больше нет: сцена подвала держит пропорцию макета на любой ширине, и
   координаты из Figma работают как есть — от верха, как они и сняты. */
