/* ============================================================================
   ГУСІ — компоненты
   Кнопка, ссылка, шапка, стрелки каруселей, карточки, оверлей меню.
   Все размеры — из Figma, в юнитах макета.
   ========================================================================= */

/* ----------------------------------------------------------------------
   РУКОПИСНАЯ ГАРНИТУРА ShaltaiW10

   Ею в макете набраны «кисточные» надписи и пункты меню. Сами надписи на
   странице стоят SVG-контурами из Figma (там они отданы кривыми), а меню
   картинкой не подменить: по нему ходят с клавиатуры и его читает
   скринридер, — поэтому меню набирается текстом и файл шрифта ему нужен.

   Файл лежит в `assets/fonts/Shaltai W10/Shaltai W10.ttf` — ровно так,
   как его выгрузили: папкой и с пробелом в имени. Пробел в url() обязан
   быть закодирован (%20), иначе адрес разбирается как два токена и
   источник молча отбрасывается. Прежние адреса вида
   `assets/fonts/ShaltaiW10.woff2` оставлены следом: если файл однажды
   переложат в woff2 (вдвое легче ttf), он подхватится без правки.

   local() идёт первым не для красоты: без него @font-face перекрыл бы
   собой одноимённый шрифт, установленный в системе, и на машине, где
   ShaltaiW10 стоит, меню всё равно набиралось бы запасной гарнитурой.

   font-display: swap — меню не должно ждать шрифт: оверлей открывается
   по клику, и невидимый текст в этот момент читался бы поломкой.
   -------------------------------------------------------------------- */
@font-face {
  font-family: "ShaltaiW10";
  src: local("ShaltaiW10"), local("Shaltai W10"), local("Shaltai"),
       url("../assets/fonts/ShaltaiW10.woff2") format("woff2"),
       url("../assets/fonts/ShaltaiW10.woff") format("woff"),
       url("../assets/fonts/Shaltai%20W10/Shaltai%20W10.ttf") format("truetype"),
       url("../assets/fonts/ShaltaiW10.otf") format("opentype"),
       url("../assets/fonts/ShaltaiW10.ttf") format("truetype");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}

/* ----------------------------------------------------------------------
   КНОПКА  (Figma: btn даведацца / btn купіць)
   border 2 · radius 25 · bg rgba(255,255,255,.5) · backdrop-blur 2
   Высота фиксирована макетом, горизонтальные поля — 55.
   -------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: calc(40 * var(--u));
  padding: 0 var(--btn-pad-x);
  font-size: var(--fs-body);
  font-weight: var(--fw-regular);
  line-height: var(--lh-flat);
  color: var(--c-brand);
  white-space: nowrap;
  background: var(--c-paper-50);
  border: var(--btn-border) solid var(--c-brand);
  border-radius: var(--btn-radius);
  backdrop-filter: blur(calc(2 * var(--u)));
  -webkit-backdrop-filter: blur(calc(2 * var(--u)));
  transition: color var(--dur-fast) var(--ease-out),
              background-color var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-out);
}

/* Слой компоновки поднимается только на время наведения — держать его
   на всех кнопках страницы постоянно дороже, чем создать по требованию. */
.btn:hover,
.btn:focus-visible {
  will-change: transform;
}

.btn:hover {
  color: var(--c-paper);
  background: var(--c-brand);
}

.btn:active {
  transform: scale(0.97);
}

/* Кнопка «КУПІЦЬ» в карусели — подпись под товаром, а не призыв во весь
   экран: самый мелкий уровень шкалы и своя, более низкая коробка. Рядом
   с ней на экране стоят ещё две такие же, и в кегле «ДАВЕДАЦЦА» три
   одинаковые кнопки в ряд перевешивали бы сами товары. */
.btn--buy {
  height: calc(34 * var(--u));
  padding: 0 calc(26 * var(--u));
  min-width: calc(150 * var(--u));
  font-size: var(--fs-small);
}

/* В макете центральная «КУПІЦЬ» залита сиреневым на 50% с белым текстом
   (фон rgb(211,181,229)) — так дизайнер показал наведение, а не постоянное
   состояние слайда. Поэтому заливка живёт на :hover, а не на классе. */
.btn--buy:hover,
.btn--buy:focus-visible {
  background: var(--c-brand-50);
  color: var(--c-paper);
}

/* ----------------------------------------------------------------------
   ТЕКСТОВАЯ ССЫЛКА «ДАВЕДАЦЦА» — подчёркнутая, уровень L4
   -------------------------------------------------------------------- */
.link {
  position: relative;
  display: inline-block;
  font-size: var(--fs-body);
  line-height: var(--lh-flat);
  color: var(--c-brand);
}

.link::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(-2 * var(--u));
  height: calc(1 * var(--u));
  background: currentColor;
  /* Появление и наведение разведены по разным свойствам нарочно.
     Длина при появлении живёт в clip-path и ведётся из js (--underline),
     наведение — в transform, у которого свой transition. Будь оба на
     transform, переход наведения сглаживал бы каждый кадр рисования, и
     линия выезжала бы с чужой инерцией. */
  clip-path: inset(0 calc((1 - var(--underline, 1)) * 100%) 0 0);
  transform-origin: right;
  transition: transform var(--dur-base) var(--ease-out);
}

.link:hover::after {
  transform: scaleX(0);
  transform-origin: left;
}

.link--on-dark {
  color: var(--c-brand);
}

/* ----------------------------------------------------------------------
   ШАПКА
   МЕНЮ (60,36) · ЛОГО (864.5,0) · МАГАЗІН (1722,36)
   -------------------------------------------------------------------- */
/* Шапка живёт в системе координат СЦЕНЫ, а не секции.

   Раньше она растягивалась во всю секцию (inset: 0 0 auto 0), и логотип
   центрировался по её середине, а заголовок, подводка и кнопка — по
   середине сцены. Пока юнит считался от 100vw, это были две разные
   середины: сцена шириной 100vw (с полосой прокрутки), секция — 100%
   документа (без неё). Юнит теперь считается по видимой ширине и обе
   середины сошлись, но зависеть выравнивание от арифметики юнита не
   должно: «ГУСІ» с утками обязано стоять на той же оси, что и кнопка,
   по построению. Коробка шапки — ровно коробка сцены, и ось у них одна.

   Поля 60 юнитов у «МЕНЮ» и «МАГАЗІН» тоже отмеряются теперь от краёв
   кадра макета, а не от краёв окна: в Figma они именно кадровые. */
.hdr {
  position: absolute;
  top: 0;
  left: 50%;
  translate: -50% 0;
  width: calc(var(--design-w) * var(--u));
  z-index: 40;
  height: calc(96 * var(--u));
  pointer-events: none;
}

.hdr > * {
  pointer-events: auto;
}

/* Подложка шапки. На десктопе её нет вовсе — шапка там стоит на первом
   экране и никуда не едет. Показывается в mobile.css, ход ей задаёт
   js (stickyHeader): opacity и scaleY, то есть ровно те два свойства,
   которые браузер считает без пересчёта раскладки. */
.hdr__veil {
  display: none;
  position: absolute;
  inset: 0;
  transform-origin: 50% 0;
  pointer-events: none;
}

.hdr__menu,
.hdr__store {
  position: absolute;
  top: calc(36 * var(--u));
  display: inline-flex;
  align-items: center;
  height: calc(48 * var(--u));
  font-size: var(--fs-nav);
  line-height: var(--lh-flat);
  color: var(--c-brand);
}

.hdr__menu {
  left: var(--gutter);
  gap: calc(12 * var(--u));
}

.hdr__store {
  right: var(--gutter);
  gap: calc(9 * var(--u));
}

.hdr__burger {
  position: relative;
  width: calc(22 * var(--u));
  height: calc(16 * var(--u));
  flex: none;
}

.hdr__burger span {
  position: absolute;
  left: 0;
  width: 100%;
  height: calc(2 * var(--u));
  background: currentColor;
  transition: transform var(--dur-fast) var(--ease-out),
              opacity var(--dur-fast) var(--ease-out);
}

.hdr__burger span:nth-child(1) { top: 0; }
.hdr__burger span:nth-child(2) { top: calc(7 * var(--u)); }
.hdr__burger span:nth-child(3) { top: calc(14 * var(--u)); }

.hdr__menu[aria-expanded="true"] .hdr__burger span:nth-child(1) {
  transform: translateY(calc(7 * var(--u))) rotate(45deg);
}

.hdr__menu[aria-expanded="true"] .hdr__burger span:nth-child(2) {
  opacity: 0;
}

.hdr__menu[aria-expanded="true"] .hdr__burger span:nth-child(3) {
  transform: translateY(calc(-7 * var(--u))) rotate(-45deg);
}

.hdr__store-icon {
  width: calc(26 * var(--u));
  height: calc(24 * var(--u));
  flex: none;
}

/* Логотип: гусь · ГУСІ · гусь (второй развёрнут на 180°) */
.hdr__logo {
  position: absolute;
  left: 50%;
  top: 0;
  translate: -50% 0;
  display: flex;
  align-items: center;
  gap: calc(10 * var(--u));
  height: calc(96 * var(--u));
}

.hdr__logo-duck {
  width: calc(34 * var(--u));
  height: calc(42 * var(--u));
  flex: none;
}

.hdr__logo-duck--flip {
  transform: rotate(180deg) scaleY(-1);
}

.hdr__logo-text {
  font-size: var(--fs-logo);
  font-weight: var(--fw-bold);
  line-height: var(--lh-flat);
  color: var(--c-brand);
}

/* ----------------------------------------------------------------------
   СТРЕЛКИ КАРУСЕЛЕЙ  (Figma vector 14.5×26.5)
   -------------------------------------------------------------------- */
.arrow {
  position: absolute;
  z-index: 20;
  display: grid;
  place-items: center;
  width: calc(56 * var(--u));
  height: calc(56 * var(--u));
  color: var(--c-brand);
  transition: transform var(--dur-fast) var(--ease-out),
              opacity var(--dur-fast) var(--ease-out);
}

.arrow svg {
  width: calc(21 * var(--u));
  height: calc(32 * var(--u));
}

.arrow:hover {
  transform: scale(1.25);
}

.arrow:disabled {
  opacity: 0.25;
  cursor: default;
  transform: none;
}

/* ----------------------------------------------------------------------
   РУКОПИСНАЯ НАДПИСЬ (SVG вместо шрифта ShaltaiW10)
   -------------------------------------------------------------------- */
.brush {
  display: block;
  width: calc(var(--w) * var(--u));
  height: auto;
}

.brush img {
  display: block;
  width: 100%;
  height: auto;
}

/* ----------------------------------------------------------------------
   ОВЕРЛЕЙ МЕНЮ
   -------------------------------------------------------------------- */
/* Шторка едет сверху вниз и обратно. visibility снимается не сразу, а
   ровно после того, как шторка уехала: без этой отсрочки оверлей исчезал
   мгновенно и обратного движения не было видно вовсе. */
.menu {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;
  place-items: center;
  background: var(--c-paper);
  clip-path: inset(0 0 100% 0);
  transition: clip-path 0.85s var(--ease-in-out), visibility 0s linear 0.85s;
  visibility: hidden;
}

.menu.is-open {
  clip-path: inset(0 0 0 0);
  visibility: visible;
  transition: clip-path 0.85s var(--ease-in-out), visibility 0s linear 0s;
}

.menu__list {
  display: grid;
  gap: calc(20 * var(--u));
  text-align: center;
}

.menu__item {
  overflow: hidden;
}

/* Пункты меню — рукописной гарнитурой макета, уровнем H2: названия
   секций на странице набраны H1, и меню, ведущее к ним, не должно быть
   крупнее того, к чему ведёт. */
.menu__link {
  display: inline-block;
  font-family: var(--font-hand);
  font-size: var(--fs-h2);
  font-weight: var(--fw-bold);
  line-height: var(--lh-flat);
  color: var(--c-brand);
  transform: translateY(110%);
  transition: transform 0.7s var(--ease-out), opacity var(--dur-fast) linear;
}

/* Пункты выезжают из-под своих масок волной вслед за шторкой */
.menu.is-open .menu__link {
  transform: translateY(0);
}

.menu.is-open .menu__item:nth-child(1) .menu__link { transition-delay: 0.30s; }
.menu.is-open .menu__item:nth-child(2) .menu__link { transition-delay: 0.37s; }
.menu.is-open .menu__item:nth-child(3) .menu__link { transition-delay: 0.44s; }
.menu.is-open .menu__item:nth-child(4) .menu__link { transition-delay: 0.51s; }
.menu.is-open .menu__item:nth-child(5) .menu__link { transition-delay: 0.58s; }

.menu__link:hover {
  opacity: 0.55;
}

/* Регистр снимается только вместе с самой гарнитурой.
   ShaltaiW10 в макете живёт строчной — ею набраны все «кисточные»
   надписи, и прописных у неё там нет ни одной. Но пока файла шрифта
   нет, меню набирается запасной гарнитурой, и строчные в ней выбились
   бы из страницы, где всё остальное прописное. Класс на <html> ставит
   js, когда шрифт действительно нашёлся (см. js/main.js). */
html.has-hand .menu__link {
  text-transform: none;
}

/* Кнопка «ЗАЧЫНІЦЬ» стоит ровно на месте кнопки «МЕНЮ»: те же координаты,
   та же высота, тот же зазор до бургера. Оверлей накрывает шапку, поэтому
   для глаза это один и тот же элемент — бургер, который на месте
   складывается в крестик и подписывается заново. */
.menu__close {
  position: absolute;
  top: calc(36 * var(--u));
  left: var(--gutter);
  display: inline-flex;
  align-items: center;
  gap: calc(12 * var(--u));
  height: calc(48 * var(--u));
  font-size: var(--fs-nav);
  line-height: var(--lh-flat);
  color: var(--c-brand);
}

/* Палочки бургера складываются в крестик — тем же движением, что и в шапке,
   только по классу открытого оверлея. Задержка стоит на состоянии «открыто»:
   при открытии бургер ждёт, пока шторка доедет донизу, при закрытии
   распрямляется сразу — задержка в обратную сторону читалась бы залипанием. */
.menu.is-open .menu__close .hdr__burger span {
  transition-delay: 0.34s;
}

.menu.is-open .menu__close .hdr__burger span:nth-child(1) {
  transform: translateY(calc(7 * var(--u))) rotate(45deg);
}

.menu.is-open .menu__close .hdr__burger span:nth-child(2) {
  opacity: 0;
}

.menu.is-open .menu__close .hdr__burger span:nth-child(3) {
  transform: translateY(calc(-7 * var(--u))) rotate(-45deg);
}

.menu__close .hdr__burger span {
  transition: transform var(--dur-base) var(--ease-out),
              opacity var(--dur-fast) var(--ease-out);
}

/* Подпись выезжает из-под маски вслед за бургером */
.menu__close-label {
  display: block;
  overflow: hidden;
}

.menu__close-label-inner {
  display: block;
  transform: translateY(110%);
  transition: transform 0.6s var(--ease-out);
}

.menu.is-open .menu__close-label-inner {
  transform: translateY(0);
  transition-delay: 0.38s;
}

/* ----------------------------------------------------------------------
   ОРНАМЕНТ ПЕРВОГО ЭКРАНА — «дождь»

   Полосы не стоят, а сыплются: мотив рушніка бесконечно едет вниз, у
   каждой полосы своя скорость (--fall, секунд на один мотив), поэтому
   они никогда не идут в ногу.

   Устроено это не прокруткой фона, а сдвигом вложенного слоя: у фона
   каждый кадр стоил бы перерисовки, у transform — нет. Слой начинается
   на один мотив выше полосы и уезжает ровно на один мотив вниз — на этом
   месте картинка совпадает сама с собой, и повтор бесшовен.

   Ход держит CSS-анимация, а не твин GSAP, и это не вкусовщина. Твин с
   repeat: -1 доигрывает цикл до конца и запускает следующий с нуля —
   между циклами он отдаёт кадр главному потоку, и на этом кадре ход
   спотыкался: лента доезжала, замирала на миг и трогалась заново. Плюс
   длину шага твин считал один раз, при создании, — после смены размера
   окна он уезжал не на мотив, а на старое число пикселей, и шов
   становился виден. У CSS-анимации стыка нет вовсе: она бесконечна по
   определению, идёт на композиторе и пересчитывает calc() сама.

   Голова и хвост дождя гасятся маской самой полосы. Раньше затухание
   было запечено в саму картинку (полоса целиком, одним куском), но
   бегущей ленте нужен повторяемый мотив, а гасить её приходится снаружи.
   -------------------------------------------------------------------- */
.ornament {
  position: absolute;
  left: calc(var(--x) * var(--u));
  top: calc(var(--y) * var(--u));
  width: calc(var(--w) * var(--u));
  height: calc(var(--h) * var(--u));
  overflow: hidden;
  pointer-events: none;
  -webkit-mask-image: linear-gradient(180deg,
    rgba(0, 0, 0, 0) 0%, rgb(0, 0, 0) 20%, rgb(0, 0, 0) 70%, rgba(0, 0, 0, 0) 100%);
          mask-image: linear-gradient(180deg,
    rgba(0, 0, 0, 0) 0%, rgb(0, 0, 0) 20%, rgb(0, 0, 0) 70%, rgba(0, 0, 0, 0) 100%);
}

.ornament__fall {
  position: absolute;
  left: 0;
  right: 0;
  /* На мотив выше полосы: этот запас и уезжает вниз, пока верх не пуст. */
  top: calc(-1 * var(--period) * var(--u));
  bottom: 0;
  background: url("../assets/ornament/orn-tile-v.png") repeat-y;
  background-size: 100% calc(var(--period) * var(--u));
  /* --fall — секунд на один мотив, у каждой полосы своё: в ногу они не
     идут, и рисунок дождя не повторяется. */
  animation: orn-fall calc(var(--fall, 3) * 1s) linear infinite;
  will-change: transform;
}

@keyframes orn-fall {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(0, calc(var(--period) * var(--u)), 0); }
}

/* Пока первый экран не в кадре, дождю идти незачем — класс ставит
   ScrollTrigger (js/animations.js). Вместе с ходом снимается и слой
   компоновки: держать его на невидимой секции нечем оправдать. */
html.orn-rest .ornament__fall {
  animation-play-state: paused;
  will-change: auto;
}

/* ----------------------------------------------------------------------
   БОКОВЫЕ ЛЕНТЫ АРНАМЕНТА — рамка всей страницы

   В макете это два фрейма во всю высоту кадра (Figma 289:6877 и
   289:6878): лента шириной 53 юнита с отступом 2 от края, набранная
   повторяющимся звеном. Звено готовит tools/rasterize-ornament.js —
   шаг повтора 1132 юнита, непрозрачность 0.70 запечена в саму картинку,
   как в макете.

   Лежат поверх содержимого — так они и стоят в Figma, последними в кадре.
   Шапка (z-index 40) остаётся выше: она и в макете поверх ленты.
   -------------------------------------------------------------------- */
.page-orn {
  position: absolute;
  top: 0;
  bottom: 0;
  z-index: 30;
  width: calc(53 * var(--u));
  background: url("../assets/ornament/orn-side.png") repeat-y;
  background-size: 100% calc(1132 * var(--u));
  pointer-events: none;
}

.page-orn--l { left: calc(2 * var(--u)); }
.page-orn--r { right: calc(2 * var(--u)); }

/* Шире 1920 секции остаются колонкой по центру — лента держится за её
   края, а не за края окна, иначе она уезжает в белое поле рядом с макетом.
   958 — это 960 (половина кадра) минус тот же отступ 2. */
@media (min-width: 1921px) {
  .page-orn--l { left: calc(50% - 958 * var(--u)); }
  .page-orn--r { right: calc(50% - 958 * var(--u)); }
}
