/* ============================================================================
   PROFiL landing page — styles
   Источник макета: Figma «PROFiL_landing-page», фрейм `landing page_1920` (2:10)
   Все цвета/отступы/шрифты берутся из tokens.css через var(--...).

   Подход: mobile-first, метрики резиновые на всём диапазоне: одна непрерывная
   кривая 375 → 1024 → 1920, поэтому на границах ничего не прыгает. Нижний
   участок (--fluid-s) задан в :root, верхний (--fluid) — в десктопном блоке.
   Медиа-запросы переключают только раскладку. Контрольные точки —
     до 768px      — мобильный (базовые правила)
     768…1023px    — планшет  (@media min-width: 768px), только раскладка:
                     колонки, коллаж, столбик индикаторов слайдера
     от 1024px     — десктоп  (@media min-width: 1024px), резиновый:
                     метрики плавно интерполируются от 1024 к 1920 и на 1920
                     совпадают с макетом 1:1. Выше 1920 контент замирает и
                     центрируется — max-width: var(--layout-page-width).
                     Формулы собраны в начале десктопного блока (--fluid).
     от 1340px     — шапка разворачивается в ряд (@media min-width: 1340px).
                     Единственная оставшаяся ступенька: ряд «логотип + меню +
                     телефон + кнопка» не помещается по ширине раньше.

   Раскладка построена на Flexbox/Grid. position: absolute применяется только
   там, где в макете элементы намеренно наложены друг на друга (фоны, скримы,
   декоративные круги, коллаж) — auto-layout в этих местах отсутствует.
   ========================================================================== */

/* ------------------------------- reset ----------------------------------- */

*,
*::before,
*::after { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  font-family: var(--font-family-base);
  font-size: var(--font-size-md);
  font-weight: var(--font-weight-regular);
  line-height: var(--line-height-base);
  letter-spacing: var(--letter-spacing-base);
  color: var(--color-text);
  background: var(--color-bg);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, p, figure, ol, ul { margin: 0; }
ul, ol { padding: 0; list-style: none; }
img { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font: inherit; letter-spacing: inherit; }

:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 3px;
}

/* ------------------------- служебные утилиты ----------------------------- */

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Прячем через transform, а не через top: calc(-1 * токен), — смещение
   на -100% всегда равно реальной высоте ссылки, независимо от того, как
   мелкий --font-size-3xl на узких экранах (иначе на 375…1150px ссылка
   выше своего же отступа, и снизу торчит полоска фона). */
.skip-link {
  position: absolute;
  top: 0;
  left: var(--space-2);
  z-index: 100;
  padding: var(--space-2) var(--space-3);
  font-size: var(--font-size-xs);
  color: var(--color-text-inverse);
  background: var(--color-accent);
  transform: translateY(-100%);
  transition: transform 0.15s ease;
}
.skip-link:focus { transform: translateY(var(--space-2)); }

/* ------------------- резиновая шкала до 1024px ---------------------------
   Нижний участок той же кривой, что описана в шапке файла: от макета 375
   до значений, с которых начинается десктоп. Благодаря этому на границе
   1023/1024 ничего не прыгает, а планшет 768…1023 перестал быть ступенькой
   с фиксированными метриками.

   Крупные кегли в двух макетах разные (64/48/40 против 28/24/20), поэтому
   они текучие. Мелкие — одинаковые в обоих (20/18/16/14/12) и остаются
   макетными на всех ширинах: там нечего интерполировать, а занижать их
   ради «пропорций» значило бы ухудшить читаемость основного текста.
   ----------------------------------------------------------------------- */
:root {
  --fluid-s: calc(clamp(375px, 100vw, 1024px) - 375px);   /* путь 0…649px */

  --layout-gutter:  calc(20px + 28 * var(--fluid-s) / 649);
  --space-section:  calc(32px + 32 * var(--fluid-s) / 649);

  --font-size-3xl:  calc(28px + 8 * var(--fluid-s) / 649);
  --font-size-2xl:  calc(24px + 8 * var(--fluid-s) / 649);
  --font-size-xl:   calc(20px + 6 * var(--fluid-s) / 649);
}

/* Общий контейнер: боковой отступ = gutter из токенов */
.site-header__inner,
.standards,
.advantages,
.sizes__inner,
.elements,
.prices__inner,
.calc__inner,
.soffits,
.site-footer > * {
  padding-inline: var(--layout-gutter);
}

/* --------------------------- типографика --------------------------------- */

.section-title {
  font-size: var(--font-size-2xl);
  font-weight: var(--font-weight-medium);
  line-height: var(--line-height-base);
  letter-spacing: var(--letter-spacing-base);
  text-transform: uppercase;
}
.section-title--accent { color: var(--color-accent); }
.section-title--light  { color: var(--color-text-inverse); }

.section-subtitle {
  font-size: var(--font-size-xl);
  font-weight: var(--font-weight-bold);
  line-height: var(--line-height-base);
  letter-spacing: var(--letter-spacing-base);
  text-transform: uppercase;
}
.section-subtitle--accent { color: var(--color-accent); }

.lead {
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-regular);
}

.rule { width: 100%; height: 1px; }

/* Логотип-маска: у макеті це біла заливка, обрізана альфа-каналом PNG,
   а не саме зображення — тому mask-image, а не <img>. */
.logo-mask {
  display: block;
  background-color: var(--color-white);
  mask-image: url("../imgs/logo-mark.png");
  mask-size: contain;
  mask-position: center;
  mask-repeat: no-repeat;
  -webkit-mask-image: url("../imgs/logo-mark.png");
  -webkit-mask-size: contain;
  -webkit-mask-position: center;
  -webkit-mask-repeat: no-repeat;
}

/* Иконки внутри кнопок — тоже маска, а не <img>: заливка берётся из
   currentColor, поэтому при наведении иконка перекрашивается вместе с текстом.
   Один ассет закрывает оба состояния — отдельный «белый» файл не нужен.
   mask-size: 100% 100% повторяет поведение исходных SVG (preserveAspectRatio="none"). */
.icon-mask {
  display: block;
  flex: none;
  background-color: currentColor;
  mask-size: 100% 100%;
  mask-position: center;
  mask-repeat: no-repeat;
  -webkit-mask-size: 100% 100%;
  -webkit-mask-position: center;
  -webkit-mask-repeat: no-repeat;
}

.icon-mask--calculator {
  width: 18px; height: 16px;
  mask-image: url("../imgs/icon-calculator.svg");
  -webkit-mask-image: url("../imgs/icon-calculator.svg");
}
.icon-mask--viber {
  width: 24px; height: 24px;
  mask-image: url("../imgs/icon-viber.svg");
  -webkit-mask-image: url("../imgs/icon-viber.svg");
}
.icon-mask--telegram {
  width: 24px; height: 24px;
  mask-image: url("../imgs/icon-telegram.svg");
  -webkit-mask-image: url("../imgs/icon-telegram.svg");
}
/* Ассет направлен влево — так он и нужен кнопке «назад»,
   а «вперёд» отражает его по горизонтали */
.icon-mask--arrow {
  width: 7px; height: 13px;
  mask-image: url("../imgs/icon-arrow-right.svg");
  -webkit-mask-image: url("../imgs/icon-arrow-right.svg");
}
/* Бургер: закрытое состояние (2:710) — две линии, открытое (2:905) — крест.
   Обе иконки в макете 16×16 с линией в 1px, поэтому это не два ассета,
   а один элемент из двух линий: так переход между состояниями анимируется.
   Линия длиной 16px, повёрнутая на 45°, даёт ровно тот крест, что в макете. */
.burger {
  position: relative;
  display: block;
  flex: none;
  width: 16px; height: 16px;
}
.burger span {
  position: absolute;
  left: 0;
  top: 50%;
  width: 100%; height: 1px;
  background: currentColor;
  transition: transform 0.3s ease;
}
.burger span:first-child { transform: translateY(-3px); }
.burger span:last-child  { transform: translateY(1px); }

/* Открытое окно превращает линии в крест. В меню это переход из бургера,
   в попапах — просто способ нарисовать тот же крестик 16×16 одним
   компонентом: он собирается вместе с появлением окна. */
.is-open .burger span:first-child { transform: rotate(45deg); }
.is-open .burger span:last-child  { transform: rotate(-45deg); }

/* ------------------------------ кнопки ----------------------------------- */

/* Наведение по макету `elements` (5:597) — не затухание, а обмен местами
   заливки и фона: сплошная кнопка становится контурной и наоборот.
   Прозрачная обводка заложена в базовое состояние, иначе появление рамки
   при наведении сдвигало бы кнопку на пол-пикселя. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--padding-cta);
  border: var(--border-width-hairline) solid transparent;
  border-radius: var(--radius-base);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  line-height: var(--line-height-base);
  letter-spacing: var(--letter-spacing-base);
  text-transform: uppercase;
  text-align: center;
  cursor: pointer;
  transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.btn--accent {
  color: var(--color-accent-text);
  background: var(--color-accent);
}
.btn--accent:hover {
  color: var(--color-accent);
  background: var(--color-white);
  border-color: var(--color-accent);
}

.btn--outline-accent {
  color: var(--color-accent);
  background: var(--color-white);
  border-color: var(--color-accent);
}
.btn--outline-accent:hover {
  color: var(--color-accent-text);
  background: var(--color-accent);
  border-color: transparent;
}

/* Светлой кнопки в макете состояний нет. Она встречается только на оранжевом
   фоне, поэтому обращение достроено по той же логике: заливка уходит в фон
   секции, текст и обводка становятся белыми. */
.btn--light {
  color: var(--color-accent);
  background: var(--color-white);
}
.btn--light:hover {
  color: var(--color-text-inverse);
  background: var(--color-accent);
  border-color: var(--color-white);
}

/* Контурная кнопка на оранжевом фоне — встречается только в мобильном меню
   (2:916): заливка совпадает с фоном, обводка и текст белые */
.btn--outline-light {
  color: var(--color-text-inverse);
  background: var(--color-accent);
  border-color: var(--color-white);
}
.btn--outline-light:hover {
  color: var(--color-accent);
  background: var(--color-white);
}

/* Кнопки фиксированной ширины 343px с узким внутренним отступом */
.btn--fixed {
  width: 100%;
  max-width: 343px;
  padding: var(--padding-cta-compact);
}
header .btn--fixed {
  max-width: 100%;
}
.btn__glyph { flex: none; }

.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 49px; height: 49px;
  flex: none;
  color: var(--color-accent); /* задаётся явно: в футере унаследовался бы белый */
  background: var(--color-white);
  border: var(--border-width-hairline) solid var(--color-accent);
  border-radius: var(--radius-base);
  transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.icon-btn path {
  transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;

}
/* В макете состояний кнопка показана на белом фоне, и обводка при наведении
   убирается. В вёрстке она встречается только в футере — на оранжевом, где
   заливка совпала бы с фоном и кнопка исчезла бы. Поэтому обводка не убирается,
   а становится белой — так же, как у .btn--light рядом. */
.icon-btn:hover {
  color: var(--color-accent-text);
  background: var(--color-accent);
  border-color: var(--color-white);
}
.icon-btn:hover path {
  fill: var(--color-white);
}
/* Уменьшенный вариант — в мобильном меню (2:925) */
.icon-btn--sm { width: 36px; height: 36px; }
.icon-btn--sm .icon-mask { width: 22px; height: 22px; }

/* ============================== СЛАЙДЕРЫ ================================= */
/* Общая механика двух слайдеров: переваг (.advantages) и прикладів розрахунку
   (.prices). Поведение задаётся классами на самой секции — их можно менять
   в разметке или на живой странице:

     scroll-on      колесо листает слайды, пока секция занимает экран
     autoplay-on    слайды листаются сами (примечание дизайнера 16:137)
     orientation-y  слайд уходит вверх, следующий приходит снизу
     orientation-h  слайди їдуть по горизонталі каруселлю (тільки .prices)

   Вертикальный слайдер (orientation-y): слайды лежат в одной ячейке грида
   и сменяются кросс-фейдом с небольшим уходом в сторону — контент у них
   разной высоты, и при честном сдвиге на 100% высота секции скакала бы
   от слайда к слайду.

   Горизонтальный слайдер (orientation-h): это настоящая карусель — слайды
   лежат в ряд внутри .slider-track (обёртка есть только в разметке .prices)
   и трек целиком едет transform: translateX. В любой момент виден максимум
   один целый слайд, второй уходит за пределы секции — без наложения.
   Перетягивание пальцем/мышью двигает трек в реальном времени (slider.js,
   Pointer Events), а не просто триггерит переключение по порогу. */

.orientation-y { --slide-shift-x: 0px; --slide-shift-y: 40px; }

.slider-viewport {
  display: grid;
  /* Без перехвата листание пальцем идёт поперёк прокрутки, поэтому вертикальные
     жесты остаются странице. При scroll-on значение не переопределяем: `none`
     запретил бы прокрутку и на краях слайдера, то есть из секции нельзя было бы
     выйти свайпом. */
  touch-action: pan-y;
}
.scroll-on .slider-viewport { touch-action: auto; }
/* Горизонтальной карусели палец нужен только по горизонтали — вертикаль
   всегда остаётся странице, поэтому pan-y не снимается даже при scroll-on
   (иначе браузер перехватил бы жест раньше, чем до него доберётся JS) */
.orientation-h .slider-viewport {
  touch-action: pan-y;
  overflow: hidden;
}

/* Смещение по умолчанию — вертикальное: секция без класса ориентации
   ведёт себя как orientation-y */
.slide {
  grid-area: 1 / 1;
  opacity: 0;
  transform: translate(var(--slide-shift-x, 0px), var(--slide-shift-y, 40px));
  transition: opacity 0.5s ease, transform 0.5s ease;
}
/* Показанные слайды уходят в обратную сторону, будущие ждут с исходной */
.slide.is-past {
  transform: translate(
    calc(-1 * var(--slide-shift-x, 0px)),
    calc(-1 * var(--slide-shift-y, 40px))
  );
}
.slide.is-current {
  opacity: 1;
  transform: none;
}
/* inert снимает неактивные слайды с фокуса и с читалки, но не прячет их от
   мыши — поэтому клики гасим отдельно */
.slide[inert] { pointer-events: none; }

/* ------------------------- горизонтальная карусель ------------------------ */
/* .slider-track — ряд слайдов шириной 100% каждый; flex-shrink: 0 не даёт
   им сжаться, поэтому ряд шире контейнера и торчащие слайды обрезает
   overflow: hidden у .slider-viewport. translateX(-100%) от ширины самого
   трека (=ширине одного слайда) сдвигает ровно на один слайд — не нужно
   знать точную ширину в пикселях. Сдвиг анимирует transform, а не opacity:
   слайды остаются непрозрачными и просто уезжают за край. */
.slider-track {
  display: flex;
  width: 100%;
  transition: transform 0.5s ease;
}
/* Перекрывает базовые .slide (стек/кросс-фейд) — карусели они не нужны */
.slider-track .slide {
  grid-area: auto;
  flex: 0 0 100%;
  min-width: 0;
  opacity: 1;
  transform: none;
  transition: none;
}

/* Круглая стеклянная кнопка со стрелкой (24:177). В макете нарисована только
   «вперёд»; «назад» — её зеркало, без неё к предыдущему слайду не вернуться
   мышью. Ассет стрелки тот же, что у шагов расчёта, и смотрит влево. */
.slider-arrow {
  display: grid;
  place-items: center;
  width: 48px; height: 48px;
  padding: 0;
  color: var(--color-text-inverse);
  background: var(--color-cream-03);
  border: var(--border-hairline-light);
  border-radius: 100px;
  backdrop-filter: blur(var(--blur-glass));
  -webkit-backdrop-filter: blur(var(--blur-glass));
  cursor: pointer;
  transition: background-color 0.15s ease, color 0.15s ease;
}
.slider-arrow:hover {
  color: var(--color-accent);
  background: var(--color-white);
}
.slider-arrow--next .icon-mask { transform: scaleX(-1); }

/* ============================== HEADER =================================== */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--color-bg);
}

.site-header__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2) var(--space-4);
  max-width: var(--layout-page-width);
  min-height: 52px;
  margin-inline: auto;
  padding-block: var(--space-2);
}

/* Ассет логотипа — квадрат 816×816; у макеті з нього беруть центральну
   горизонтальну смугу, тому object-fit: cover, а не масштабування. */
.site-header__logo img {
  width:  calc(120px + 30 * var(--fluid-s) / 649);
  height: calc(42px  + 10 * var(--fluid-s) / 649);
  object-fit: cover;
}

/* До 1024px шапка свёрнута: остаются логотип и кнопка «Меню» (макет 2:707),
   а навигация с контактами переезжают в модальное меню. Контакты прячутся
   в своём же блоке ниже — иначе он перебил бы display обратно на flex. */
.site-nav { display: none; }

.site-header__menu {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 0;
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-medium);
  line-height: var(--line-height-base);
  text-transform: uppercase;
  color: var(--color-accent);
  background: none;
  border: 0;
  cursor: pointer;
  transition: color 0.15s ease;
}
.site-header__menu:hover { color: var(--color-text); }

.site-nav__list {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  text-transform: uppercase;
  white-space: nowrap;
}
/* Пункт меню: тёмный → оранжевый */
.site-nav__list a { transition: color 0.15s ease; }
.site-nav__list a:hover { color: var(--color-accent); }

.site-header__contacts {
  display: none;   /* до 1024px телефон и кнопка живут в модальном меню */
  align-items: center;
  gap: var(--space-4);
}
/* Телефон в шапке: оранжевый → тёмный, обратно пункту меню */
.site-header__phone {
  display: none;
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  text-transform: uppercase;
  white-space: nowrap;   /* в макете номер всегда в одну строку, как в футере */
  color: var(--color-accent);
  transition: color 0.15s ease;
}
.site-header__phone:hover { color: var(--color-text); }
.site-header__contacts .btn { padding: var(--space-2) var(--space-3); }

/* =============================== HERO ==================================== */

.hero {
  position: relative;
  display: flex;
  align-items: flex-end;
  min-height: calc(420px + 220 * var(--fluid-s) / 649);
  overflow: hidden;
  background: var(--color-bg-inverse);
}

.hero__bg {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}

.hero__badge {
  position: absolute;
  top: 8%;
  right: var(--layout-gutter);
  width:  calc(96px + 36 * var(--fluid-s) / 649);
  height: calc(96px + 36 * var(--fluid-s) / 649);
  object-fit: cover;
}

/* Затухание фото в белый фон страницы — как в макете (310px снизу) */
.hero__fade {
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  height: 32%;
  background: var(--gradient-hero-fade);
}

.hero__content {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-5);
  width: 100%;
  max-width: var(--layout-page-width);
  margin-inline: auto;
  padding: var(--space-6) var(--layout-gutter);
}

.hero__title {
  font-size: var(--font-size-3xl);
  font-weight: var(--font-weight-semibold);
  line-height: var(--line-height-base);
  letter-spacing: var(--letter-spacing-base);
  text-transform: uppercase;
  color: var(--color-accent);
}

/* ============================= STANDARDS ================================= */

.standards {
  display: grid;
  gap: var(--space-6);
  max-width: var(--layout-page-width);
  margin-inline: auto;
  padding-block: var(--space-section);
}

.standards__text {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

.standards__gallery {
  display: grid;
  gap: var(--space-2);
}

.standards__img {
  width: 100%;
  height: auto;
  object-fit: cover;
  border-radius: var(--radius-base);
}

/* У макеті це фото збільшене до 322 % і зсунуте — обрізаємо обгорткою.
   Той самий кадр із тим самим збільшенням стоїть на 6-му слайді переваг
   (.slide__specks), тому обидва місця беруть одні й ті самі відсотки. */
.standards__crop {
  position: relative;
  overflow: hidden;
}
.standards__crop img,
.slide__specks img {
  position: absolute;
  width: 322.52%;
  height: 195.68%;
  left: -96.46%;
  top: -95.68%;
  max-width: none;
  object-fit: cover;
}

/* ============================= ADVANTAGES ================================ */
/* Слайдер переваг: 6 слайдов. Общая механика — в разделе «СЛАЙДЕРЫ» выше,
   здесь только раскладка. Ширины колонок вынесены в переменные — по ним же
   выравнивается внутренняя сетка каждого слайда. */

.advantages {
  --slide-media: 560px;
  --slide-text: var(--layout-column-text);

  display: grid;
  gap: var(--space-6);
  max-width: var(--layout-page-width);
  margin-inline: auto;
  padding-block: var(--space-section);
}

/* Индикаторы. На мобильном это полоса прогресса (закрашены пройденные),
   с планшета — вертикальный столбик с одним активным штрихом: так в макете. */
.slider-dots {
  display: flex;
  flex-direction: row;
  justify-content: center;
  gap: 4px;
  /* Ряд из шести штрихов по 50px требует 320px. Без min-width: 0 ячейка
     сетки не даёт ему сжаться ниже этой ширины, и на экранах уже 360px
     страница получала горизонтальную прокрутку. */
  min-width: 0;
}
.slider-dots button {
  flex: 0 1 50px;
  width: 50px; height: 2px;
  padding: 0;
  border: 0;
  background: var(--color-bg-muted);
  cursor: pointer;
  transition: background-color 0.3s ease, width 0.3s ease;
}
.slider-dots button.is-filled { background: var(--color-accent); }

/* ------------------------------- слайды ---------------------------------- */

.advantages .slide {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

/* Подпись цвета стоит над кадром, поэтому квадратная область — не сама figure,
   а обёртка внутри неё; она же держит систему координат для наложений */
.slide__figure {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
}
.slide__media {
  position: relative;
  display: block;
  width: min(270px, 72vw);
  aspect-ratio: 1;
}
.slide__media > img {
  width: 100%; height: 100%;
  object-fit: cover;
}

/* Кадры слайдов 3, 5 и 6 в макете смещены и увеличены — обрезаем обёрткой */
.slide__crop {
  position: absolute;
  inset: 0;
  display: block;
  overflow: hidden;
}
.slide__crop img {
  position: absolute;
  max-width: none;
  object-fit: cover;
}
.slide--funnel .slide__crop img {
  width: 82.27%; height: 105.76%;
  left: 8.87%; top: -2.75%;
}
.slide--colors .slide__crop img {
  width: 74.2%; height: 95.39%;
  left: 12.9%; top: 2.42%;
}
.slide--warranty .slide__crop img {
  width: 118.73%; height: 152.64%;
  left: -14.55%; top: -30.67%;
}

/* Россыпь рамок за трубой — тот же кадр, что в секции «стандарти» */
.slide__specks {
  position: absolute;
  left: -43.9%; top: -6.8%;
  width: 91.07%; height: 106.07%;
  display: block;
  overflow: hidden;
}
/* Селектор с потомком: иначе знак гарантии перебивался бы правилом
   основного кадра `.slide__media > img` и растянулся бы на весь квадрат */
.slide__media > .slide__badge {
  position: absolute;
  left: 48.21%; top: 19.82%;
  width: 35.71%; height: 35.71%;
  object-fit: contain;
}

.slide__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.advantages__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  /* От текста до кнопок шаг вдвое крупнее, чем между строками самого текста */
  margin-top: var(--space-2);
}
/* В макете 375 обе кнопки занимают всю ширину колонки */
.advantages__actions .btn { width: 100%; max-width: 100%;}

/* --------------------------- переключатель цветов ------------------------- */

.colors {
  /* Единичный шаг макета, в шкалу --space-* не попадает */
  --colors-gap: 9px;

  display: flex;
  flex-direction: column;
  gap: 5px;
}
.colors__name { font-size: var(--font-size-2xs); }

.colors__list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--colors-gap);
}
/* Образец цвета изделия: прозрачная рамка в базовом состоянии, чтобы выбор
   не сдвигал соседей — та же логика, что у кнопок */
.color {
  display: block;
  width: 48px; height: 48px;
  padding: 0;
  border: var(--border-width-selected) solid transparent;
  cursor: pointer;
  transition: border-color 0.15s ease;
}
.color[aria-pressed="true"] { border-color: var(--color-accent); }

.color--brick    { background: var(--color-pipe-brick); }
.color--graphite { background: var(--color-pipe-graphite); }
.color--brown    { background: var(--color-pipe-brown); }
.color--red      { background: var(--color-pipe-red); }
.color--black    { background: var(--color-pipe-black); }
/* Белый образец на белом фоне различим только по серому контуру;
   у выбранного образца серую рамку перекрывает оранжевая (aria-pressed) */
.color--white { border-color: var(--color-bg-muted); }

.slide__color-title {
  font-size: var(--font-size-xl);
  font-weight: var(--font-weight-medium);
  line-height: var(--line-height-base);
  letter-spacing: var(--letter-spacing-base);
  text-transform: uppercase;
  text-align: center;
  color: var(--color-accent);
}

/* =============================== SIZES =================================== */

.sizes {
  position: relative;
  overflow: hidden;
  background: var(--color-bg-inverse);
}

.sizes__bg {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}

/* Скрим + стеклянный слой поверх фото — два наложенных слоя из макета */
.sizes__scrim {
  position: absolute;
  inset: 0;
  background: var(--color-overlay);
  backdrop-filter: blur(var(--blur-glass));
  -webkit-backdrop-filter: blur(var(--blur-glass));
  border: var(--border-hairline-light);
}

.sizes__inner {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  max-width: var(--layout-page-width);
  margin-inline: auto;
  padding-block: var(--space-section);
  color: var(--color-text-inverse);
}

.sizes__meta {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  max-width: var(--layout-column-text);
}
.sizes__caption {
  font-size: var(--font-size-md);
  color: var(--color-cream-70);
}

/* У макеті 375 картки вже стоять по дві в ряд (2:788) — це не десктопна
   розкладка, а мобільна за замовчуванням, тому колонки задані тут,
   а не з 768px. */
.sizes__list {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-6);
}

.size-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.size-card__value {
  font-size: var(--font-size-xl);
  font-weight: var(--font-weight-semibold);
  line-height: var(--line-height-base);
  letter-spacing: var(--letter-spacing-base);
}

/* Кольцо-подсветка лежит под схемой — наложение, как в макете */
.size-card__visual {
  position: relative;
  display: grid;
  place-items: center;
}
.size-card__ring {
  position: absolute;
  left: 20%;
  width: 150px; height: 150px;
  pointer-events: none;
}
.size-card__img {
  position: relative;
  width: 100%;
  max-width: 516px;
  height: auto;
  object-fit: contain;
}

.sizes__footnote {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  max-width: var(--layout-column-text);
}
.sizes__mark { width: 16px; height: 20px; flex: none; display: none;}
.sizes__footnote p { font-size: var(--font-size-md); }

/* ============================== ELEMENTS ================================= */

.elements {
  display: grid;
  gap: var(--space-6);
  max-width: var(--layout-page-width);
  margin-inline: auto;
  padding-block: var(--space-section);
}

.elements__text {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

.elements__figure img {
  width: 100%;
  height: auto;
  object-fit: contain;
}

/* =============================== PRICES ================================== */
/* Слайдер прикладів розрахунку: 3 слайда. Общая механика — в разделе
   «СЛАЙДЕРЫ», здесь раскладка. */

.prices {
  /* Отступ стрелок от края: в макете 1920 стрелка стоит в 88px от края,
     то есть чуть внутри бокового поля страницы */
  --slider-arrow-inset: var(--layout-gutter);

  position: relative;
  overflow: hidden;
  background: var(--color-bg-inverse);
}

/* Під кожен data-bg слайду лежить свій <img>: усі в одній комірці внахлест,
   видимий вмикається class .is-current (slider.js), решта чекають прозоро
   позаду. Швидкість переходу — як у .slider-track, щоб фон і карусель
   рухались в один такт. */
.prices__bg {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 0.5s ease;
}
.prices__bg.is-current { opacity: 1; }
.prices__scrim {
  position: absolute;
  inset: 0;
  background: var(--color-overlay);
}

.prices__inner {
  position: relative;
  z-index: 1;
  display: grid;
  gap: var(--space-6);
  max-width: var(--layout-page-width);
  margin-inline: auto;
  padding-block: var(--space-section);
  color: var(--color-text-inverse);
}

/* Меняется весь расчёт целиком: параметры, стоимость и состав комплекта.
   Заголовок секции остаётся на месте, поэтому лежит вне слайдов. Фон тоже
   вне слайдов (.prices__bg, кросс-фейд по data-bg — см. «СЛАЙДЕРЫ» и
   slider.js), но переключается синхронно с ними. */
.prices .slide {
  display: grid;
  gap: var(--space-6);
  align-content: start;
}
/* В макете 375 кнопка стоит под составом комплекта, а на десктопе —
   справа от стоимости, поэтому порядок задаётся раскладкой, а не разметкой */
.prices__cta { order: 1; }

/* Стрелка в макете одна и стоит у правого края на середине высоты. Вторая
   («назад») ставится рядом с ней, а не у левого края: слева весь текст расчёта
   прижат к боковому полю, и кнопка легла бы прямо на стоимость.
   В макете 375 стрелок нет — там свайп, поэтому на мобильном они скрыты. */
.prices .slider-arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 2;
  display: none;
}
.prices .slider-arrow--prev {
  right: calc(var(--slider-arrow-inset) + 48px + var(--space-2));
}
.prices .slider-arrow--next { right: var(--slider-arrow-inset); }

.prices__params { position: relative; max-width: var(--layout-column-text); }

/* Навігація прикладами розрахунку (2:134, «slidre») — не декоративна
   картинка, а 3 крапки-перемикачі, замасковані під точки макета:
   d=4px, gap=2px, разом 16×4px, як у вихідному asset. */
.prices__thumb {
  position: absolute;
  top: 44px; right: 0;
  display: flex;
  align-items: center;
  gap: 2px;
}
.prices__thumb button {
  width: 4px; height: 4px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--color-white-70);
  cursor: pointer;
  transition: background-color 0.15s ease;
}
.prices__thumb button[aria-current="true"] { background: var(--color-white); }

.prices__label {
  margin-top: var(--space-2);
  font-size: var(--font-size-md);
  color: var(--color-text-muted);
}
.prices__value,
.prices__amount {
  font-size: var(--font-size-xl);
  font-weight: var(--font-weight-semibold);
  letter-spacing: var(--letter-spacing-base);
}
.prices__value sup { font-size: 0.645em; }

.prices__total {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* Стеклянная панель со составом комплекта */
.parts-panel {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-3);
  background: var(--color-bg-glass);
  border: var(--border-hairline-light);
  backdrop-filter: blur(var(--blur-glass));
  -webkit-backdrop-filter: blur(var(--blur-glass));
}
/* В макете 375 подпись панели прижата влево, на десктопе — по центру */
.parts-panel__title {
  font-size: 10px;
  color: var(--color-text-muted);
}
/* В макете элементы стоят плотной группой по центру, а не растянуты по ширине
   панели. На мобильном шесть штук не помещаются и панель прокручивается вбок
   пальцем (примечание дизайнера 16:140) — отсюда overflow-x вместо переноса.
   `safe center` нужен, чтобы при нехватке места не срезало первый элемент. */
.parts-panel__list {
  display: flex;
  justify-content: safe center;
  gap: var(--space-4);
  overflow-x: auto;
  scrollbar-width: none;
}
.parts-panel__list::-webkit-scrollbar { display: none; }
.part {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1);
  flex: none;
}
.part img {
  width:  calc(42px + 14 * var(--fluid-s) / 649);
  height: calc(42px + 14 * var(--fluid-s) / 649);
  object-fit: contain;
}
.part span {
  font-size: var(--font-size-2xs);
  color: var(--color-text-muted);
  text-align: center;
}

/* ========================== FORM / CALCULATOR ============================ */

/* .calc — грид с одной ячейкой: .calc__inner и .calc__thanks лежат друг на
   друге (обе grid-area: 1 / 1), высота секции берётся по более высокому из
   них (обычный grid auto-sizing). position: absolute здесь не подошёл бы:
   inset: 0 жёстко привязывает высоту перекрытия к высоте секции, и если
   тексту «Заявку прийнято» вдруг понадобится больше места, чем занимала
   форма, — его бы обрезало или он вылез бы поверх соседней секции.
   grid-template-columns фиксирует ширину колонки в 100% секции: без него
   единственная auto-колонка местами схлопывалась бы по содержимому. */
.calc {
  background: var(--color-accent);
  display: grid;
  grid-template-columns: minmax(0, 1fr);
}

.calc__inner {
  grid-area: 1 / 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-6);
  max-width: var(--layout-page-width);
  margin-inline: auto;
  padding-block: var(--space-section);
}

.calc__title {
  max-width: var(--layout-column-heading);
  text-align: left;
}

/* Три шага расчёта */
.steps {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: center;
  gap: var(--space-2);
}
.step {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  width: 98px;
}

/* Разделительная стрелка — оформление, а не шаг списка, поэтому ::after.
   Ассет направлен влево, в макете он отражён. */
.step:not(:last-child)::after {
  content: "";
  position: absolute;
  top: 21px;
  right: -24px;
  width: 24px; height: 24px;
  background-image: url("../imgs/icon-arrow-right.svg");
  background-repeat: no-repeat;
  background-position: center;
  background-size: 8px 14px;
  transform: scaleX(-1);
}
.step__img { width: 98px; height: 65px; object-fit: contain; }
.step__label {
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-light);
  color: var(--color-text-inverse);
  text-align: center;
}
/* Промежутки между шагами оставляют место под стрелку-разделитель */
.steps { column-gap: var(--space-5); }

/* Коллаж третьего шага: детали намеренно наложены — absolute оправдан */
.step__collage {
  position: relative;
  display: block;
  width: 84px; height: 65px;
}
.step__collage img {
  position: absolute;
  object-fit: contain;
}
.step__collage img:nth-child(1) { width: 35px; height: 35px; left: 42px; top: 35px; }
.step__collage img:nth-child(2) { width: 32px; height: 32px; left: 27px; top: 0; }
.step__collage img:nth-child(3) { width: 42px; height: 42px; left: 0; top: 19px; }
.step__collage-mark {
  position: absolute;
  width: 16px; height: 20px;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
}

.calc__form {
  display: grid;
  gap: var(--space-4);
  width: 100%;
  max-width: 1069px;
}

.field { margin: 0; }
.field input {
  width: 100%;
  padding: var(--padding-cta-compact);
  font-family: inherit;
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  line-height: var(--line-height-base);
  letter-spacing: var(--letter-spacing-base);
  text-transform: uppercase;
  text-align: center;
  color: var(--color-text);
  background: var(--color-white);
  border: var(--border-hairline-light);
  border-radius: var(--radius-base);
}
.field input::placeholder {
  color: var(--color-text);
  opacity: 1;
}
.field--submit .btn { max-width: none; }

/* Ошибка валидации: рамка поля и подпись под ним — как в .popup-field,
   но красный текст на оранжевом фоне секции нечитаем (контраст ~1.3:1),
   поэтому подпись здесь тёмная — на оранжевом она даёт контраст ~5:1 */
.calc-field--invalid input { border: var(--border-hairline-error); }
.calc-field__error {
  display: block;
  min-height: calc(var(--font-size-2xs) * var(--line-height-base));
  margin-top: var(--space-2);
  font-size: var(--font-size-2xs);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text);
  text-align: center;
}

.consent {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
  font-size: var(--font-size-2xs);
  font-weight: var(--font-weight-light);
  color: var(--color-text-inverse);
}
/* У макеті — білий квадрат 20×20 з оранжевою галочкою */
.consent__box {
  position: relative;
  width: 20px; height: 20px;
  flex: none;
}
.consent input {
  appearance: none;
  -webkit-appearance: none;
  position: absolute;
  inset: 0;
  margin: 0;
  background: var(--color-white);
  border: 0;
  border-radius: var(--radius-base);
  cursor: pointer;
}

/* Галочка экспортирована из Figma в исходной ориентации: внутри компонента
   Done_light она повёрнута на 90°, поэтому поворот повторён здесь; квадратная
   область при повороте на 90° формы не меняет, поэтому можно крутить весь
   слой целиком, а не только сам глиф.
   Раньше это был ::before на самом <input>: генерируемый контент на
   replaced-элементах вроде чекбоксов — не часть спецификации, Firefox
   и Safari его не рисуют (в Chromium совпадение — там это иногда работает).
   Поэтому галочка — обычный <span>-сосед. Он тоже absolute (и идёт в DOM
   после input) — иначе позиционированный input перекрыл бы его своим фоном,
   тот же порядок отрисовки, что уже встречался с .calc__thanks. */
.consent__check {
  position: absolute;
  inset: 0;
  background: url("../imgs/icon-check.svg") no-repeat center / 10px 12px;
  transform: rotate(90deg);
  opacity: 0;
  pointer-events: none;
}
.consent input:checked ~ .consent__check { opacity: 1; }

/* Перекрывает всю секцию сплошным фоном того же цвета, что и .calc — заголовок,
   шаги и форма под ней остаются в DOM (и в inert, см. popup.js), просто не видны.
   grid-area: 1 / 1 — та же ячейка, что у .calc__inner (см. .calc выше), и в
   отличие от него без своих max-width/margin-inline: растягивается на всю
   ширину секции, а не только на центральную колонку контента. hidden
   снимается в popup.js, opacity — тем же приёмом, что открытие попапов:
   класс is-open добавляется кадром позже, чтобы переход отыграл, а не
   схлопнулся в одно и то же состояние */
.calc__thanks {
  grid-area: 1 / 1;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-5);
  padding: var(--space-section) var(--layout-gutter);
  background: var(--color-accent);
  text-align: center;
  opacity: 0;
  transition: opacity 0.25s ease;
}
/* [hidden] и класс — одинаковая специфичность, а класс идёт в каскаде
   позже: без этого правила снятие/установка hidden из popup.js ни на что
   не влияли бы */
.calc__thanks[hidden] { display: none; }
.calc__thanks.is-open { opacity: 1; }
.calc__thanks-title { max-width: var(--layout-column-heading); }
.calc__thanks-lead {
  max-width: var(--layout-column-text);
  font-size: var(--font-size-md);
  font-weight: var(--font-weight-light);
  color: var(--color-text-inverse);
}

/* ============================== SOFFITS ================================== */

.soffits {
  display: grid;
  gap: var(--space-6);
  max-width: var(--layout-page-width);
  margin-inline: auto;
  padding-block: var(--space-section);
}

.soffits__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
}
.soffits__body .section-title { max-width: var(--layout-column-text); }

.finishes {
  display: grid;
  gap: var(--space-4);
}
.finish {
  display: grid;
  grid-template-columns: auto auto 1fr;
  align-items: center;
  gap: var(--space-4);
}
.finish__swatch {
  width:  calc(120px + 12 * var(--fluid-s) / 649);
  height: calc(120px + 12 * var(--fluid-s) / 649);
  object-fit: cover;
}
.finish__logo   { width: 100px; height: 50px; object-fit: contain; }
.finish__name   { font-size: var(--font-size-md); }

.soffits__figure img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* =============================== FOOTER ================================== */

.site-footer {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  padding-block: var(--space-section);
  color: var(--color-text-inverse);
  background: var(--color-accent);
}

.site-footer__brand {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
}
.site-footer__swoosh { width: min(240px, 60%); height: auto; }
.site-footer__logo {
  width: min(240px, 60%);
  aspect-ratio: 375 / 130;
  background-color: var(--color-white);
  mask-image: url("../imgs/logo-footer.png");
  mask-size: contain;
  mask-position: center;
  mask-repeat: no-repeat;
  -webkit-mask-image: url("../imgs/logo-footer.png");
  -webkit-mask-size: contain;
  -webkit-mask-position: center;
  -webkit-mask-repeat: no-repeat;
}

.site-footer__main {
  display: grid;
  gap: var(--space-6);
  max-width: var(--layout-page-width);
  margin-inline: auto;
  width: 100%;
}
.site-footer__col {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.site-footer__hours {
  max-width: var(--layout-column-text);
  font-size: var(--font-size-md);
  font-weight: var(--font-weight-light);
}

.site-footer__phone {
  font-size: var(--font-size-3xl);
  font-weight: var(--font-weight-semibold);
  line-height: var(--line-height-base);
  letter-spacing: var(--letter-spacing-base);
  text-transform: uppercase;
  white-space: nowrap;
}

.site-footer__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}

/* Три зони: посилання ліворуч, копірайт по центру сторінки — як у макеті */
.site-footer__legal {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: var(--space-2);
  max-width: var(--layout-page-width);
  width: 100%;
  margin-inline: auto;
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-light);
}
.site-footer__legal a:hover { text-decoration: underline; }
.site-footer__copyright { text-align: center; }

/* ============================ МОБІЛЬНЕ МЕНЮ ============================== */
/* Источник: `menu_375` (2:896), свёрнутая шапка — `header` (2:707).
   Тот же нативный <dialog>, что и у попапов, поэтому здесь только оформление:
   открытие, Esc, удержание фокуса и блокировка прокрутки страницы уже описаны
   в разделе «ПОПАПЫ». */

.mobile-menu {
  position: fixed;
  inset: 0;
  width: 100%;
  max-width: none;
  height: 100%;
  max-height: none;
  margin: 0;
  padding: 0;
  overflow: auto;
  color: var(--color-text-inverse);
  background: var(--color-accent);
  border: 0;
  /* Появление и уход: класс is-open навешивается кадром позже открытия
     и снимается до закрытия — <dialog> сам по себе переключает display,
     а от display переход не запускается. Сколько ждать, popup.js берёт
     из этого же transition-duration. */
  opacity: 0;
  transition: opacity 0.3s ease;
}
.mobile-menu.is-open { opacity: 1; }
.mobile-menu:not([open]) { display: none; }
.mobile-menu::backdrop { background: var(--color-overlay); }

/* Содержимое подъезжает следом за фоном — панель «раскрывается» сверху */
.mobile-menu .mobile-menu__inner {
  transform: translateY(-12px);
  transition: transform 0.3s ease;
}
.mobile-menu.is-open .mobile-menu__inner { transform: none; }

.mobile-menu__inner {
  display: flex;
  flex-direction: column;
  min-height: 100%;
  padding: 0 var(--layout-gutter-mobile) var(--space-4);
}
.mobile-menu__inner:focus { outline: none; }

/* Шапка меню повторяет свёрнутую: логотип слева, «Закрити» справа.
   Отрицательные поля возвращают её к краям экрана поверх отступов оболочки. */
.mobile-menu__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 52px;
  margin-inline: calc(-1 * var(--layout-gutter-mobile));
  padding-inline: 5px var(--layout-gutter-mobile);
}
/* Логотип в меню — белая заливка по маске, как в футере */
.mobile-menu__logo {
  display: block;
  width: 120px; height: 42px;
  background-color: var(--color-white);
  mask-image: url("../imgs/logo-menu.png");
  mask-size: contain;
  mask-position: center;
  mask-repeat: no-repeat;
  -webkit-mask-image: url("../imgs/logo-menu.png");
  -webkit-mask-size: contain;
  -webkit-mask-position: center;
  -webkit-mask-repeat: no-repeat;
}
.mobile-menu__close {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 0;
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-medium);
  line-height: var(--line-height-base);
  text-transform: uppercase;
  color: var(--color-text-inverse);
  background: none;
  border: 0;
  cursor: pointer;
}

/* Пункты идут от шапки, а контакты и кнопки прижаты к низу экрана */
.mobile-menu__nav {
  margin-top: var(--space-6);
  margin-bottom: auto;
}
.mobile-menu__nav ul {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.mobile-menu__nav a {
  /* Единственное место, где встречается этот кегль, — в шкалу он не попадает */
  font-size: 24px;
  font-weight: var(--font-weight-semibold);
  line-height: var(--line-height-base);
  letter-spacing: var(--letter-spacing-base);
  text-transform: uppercase;
  transition: opacity 0.15s ease;
}
.mobile-menu__nav a:hover { opacity: 0.7; }

.mobile-menu__contacts {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  margin-bottom: var(--space-5);
}
.mobile-menu__hours {
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-light);
}
.mobile-menu__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
}
.mobile-menu__phone {
  font-size: 28px;
  font-weight: var(--font-weight-semibold);
  line-height: var(--line-height-base);
  letter-spacing: var(--letter-spacing-base);
  white-space: nowrap;
}
.mobile-menu__messengers {
  display: flex;
  gap: var(--space-2);
}

.mobile-menu__actions {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
}

/* ================================ ПОПАПЫ ================================= */
/* Источник: `form_popup` (2:217), `form_popup_focus_error` (2:243),
   `popup_thanks` (2:234).
   Взят нативный <dialog>: модальность, затемнение фона, закрытие по Esc
   и удержание фокуса внутри окна достаются поведением браузера, без своего кода.
   В макете попап — сплошной белый лист во весь кадр, поэтому ::backdrop
   почти не виден, но остаётся на время открытия и на узких экранах. */

.popup {
  /* Расстояние от подписи поля до рамки. Единичное значение макета,
     в шкалу --space-* не попадает, поэтому живёт на самом компоненте. */
  --popup-label-gap: 5px;

  position: fixed;
  inset: 0;
  width: 100%;
  max-width: none;
  height: 100%;
  max-height: none;
  margin: 0;
  padding: 0;
  overflow: auto;
  color: var(--color-text);
  background: var(--color-bg);
  border: 0;
  /* Появление и уход — та же механика, что у мобильного меню: класс is-open
     ставится кадром позже открытия, длительность отсюда же читает popup.js */
  opacity: 0;
  transition: opacity 0.25s ease;
}
.popup.is-open { opacity: 1; }

/* Содержимое всплывает следом за фоном */
.popup .popup__inner {
  transform: translateY(12px);
  transition: transform 0.25s ease;
}
.popup.is-open .popup__inner { transform: none; }

.popup::backdrop { background: var(--color-overlay); }

/* Браузер без поддержки <dialog> покажет закрытое окно как обычный блок */
.popup:not([open]) { display: none; }

/* Страница под открытым окном не должна прокручиваться */
body:has(.popup[open]),
body:has(.mobile-menu[open]) { overflow: hidden; }

.popup__inner {
  position: relative;
  display: grid;
  justify-items: center;
  align-content: center;
  align-content: safe center; /* высокий контент на низком экране не обрезается сверху */
  min-height: 100%;
  /* Отступы сверху и снизу равны, иначе центрированный блок уедет вниз
     на высоту строки «Закрити» */
  padding: calc(var(--space-4) + var(--space-6)) var(--layout-gutter);
}

/* Оболочка принимает фокус при открытии окна, но это не орган управления,
   поэтому обводка ей не нужна */
.popup__inner:focus { outline: none; }

.popup__close {
  position: absolute;
  top: var(--space-4);
  right: var(--layout-gutter);
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 0;
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-medium);
  line-height: var(--line-height-base);
  text-transform: uppercase;
  color: var(--color-accent);
  background: none;
  border: 0;
  cursor: pointer;
  transition: color 0.15s ease;
}
/* Ведёт себя как текстовая ссылка — по той же логике, что телефон в шапке */
.popup__close:hover { color: var(--color-text); }

.popup__body {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-7);
  width: 100%;
  max-width: var(--layout-page-width);
}

/* Заголовок и вводный текст идут плотнее, чем блок целиком */
.popup__intro {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-5);
}

.popup__title { max-width: var(--layout-column-heading); text-align: center; }
.popup__lead {
  max-width: var(--layout-column-text);
  font-size: var(--font-size-md);
  text-align: center;
}

/* ------------------------------ форма ------------------------------------ */

/* На узких экранах поля стоят в столбец, и к межстрочному отступу добавляется
   зарезервированная строка подписи — поэтому здесь шаг мельче, а макетные 30px
   включаются с 1024px, где этот отступ отделяет форму от строки согласия. */
.popup-form {
  display: grid;
  gap: var(--space-4);
  align-items: end;
  width: 100%;
  max-width: 1069px;
}

.popup-field {
  display: flex;
  flex-direction: column;
  gap: var(--popup-label-gap);
}

/* Строка подписи над полем. Место под неё зарезервировано всегда, поэтому
   появление подписи при фокусе не сдвигает раскладку. */
.popup-field__meta {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2);
  min-height: calc(var(--font-size-2xs) * var(--line-height-base));
  font-size: var(--font-size-2xs);
  font-weight: var(--font-weight-light);
}

/* В базовом состоянии макета подписей нет, в состоянии ввода — есть */
.popup-field__label {
  opacity: 0;
  transition: opacity 0.15s ease;
}
.popup-field:focus-within .popup-field__label,
.popup-field:has(input:not(:placeholder-shown)) .popup-field__label,
.popup-field--invalid .popup-field__label { opacity: 1; }

.popup-field__error {
  color: var(--color-error);
  text-align: right;
}

.popup-field input { border: var(--border-hairline-dark); }
.popup-field--invalid input { border: var(--border-hairline-error); }

.popup-form__submit { margin: 0; }
.popup-form__cta {
  width: 100%;
  padding: var(--padding-cta-compact);
}

/* Тот же чекбокс, что в секции расчёта, но на светлом фоне цвета инвертированы:
   оранжевый квадрат с белой галочкой вместо белого с оранжевой. */
.consent--dark { color: var(--color-text); }
.consent--dark input { background: var(--color-accent); }
.consent--dark .consent__check { background-image: url("../imgs/icon-check-light.svg"); }

/* ========================================================================= */
/* ============================ ПЛАНШЕТ 768+ =============================== */
/* ========================================================================= */

/* Здесь остались только переключения раскладки. Все метрики — поля, кегли,
   высоты, размеры картинок — тянутся сквозной шкалой из :root и своих
   ступенек на 768 больше не имеют. */
@media (min-width: 768px) {

  /* Коллаж «стандартов»: широкое фото сверху, два — в ряд под ним */
  .standards__gallery {
    grid-template-columns: 1fr 1fr;
    grid-template-areas:
      "wide wide"
      "tall low";
  }
  .standards__img--wide { grid-area: wide; aspect-ratio: 930 / 538; }
  .standards__img--tall { grid-area: tall; aspect-ratio: 510 / 594; }
  .standards__img--low  { grid-area: low;  aspect-ratio: 634 / 340; }

  /* С планшета индикаторы уходят влево и становятся столбиком: активный штрих
     шире остальных, заливка «пройденного» больше не нужна */
  .advantages { grid-template-columns: auto minmax(0, 1fr); }
  .slider-dots {
    flex-direction: column;
    align-self: center;
    gap: var(--space-4);
  }
  .slider-dots button { flex: none; height: 4px; }
  .slider-dots button.is-filled { background: var(--color-bg-muted); }
  .slider-dots button[aria-current="true"] {
    width: 80px;
    background: var(--color-accent);
  }

  /* Стрелок в макете 375 нет — там свайп; с планшета показываем обе */
  .prices .slider-arrow { display: grid; }

  .advantages .slider-viewport { align-self: center; }
  .slide__media { width: min(420px, 45vw); }
  /* Планшета в макете нет: держим кнопки на макетных 343px, чтобы пара
     не разъезжалась по ширине колонки */
  .advantages__actions .btn { max-width: 343px; }

  .calc__form {
    grid-template-columns: 1fr 1fr;
    align-items: start;
  }
  .consent { grid-column: 1 / -1; }

  .finishes { gap: var(--space-5); }
  .finish__swatch { width: 160px; height: 160px; }

  .site-footer__main { grid-template-columns: 1fr 1fr; }
  .site-footer__col--contacts { align-items: flex-start; }

  .popup-form { grid-template-columns: 1fr 1fr; }
  .popup-form__submit,
  .popup-form__consent { grid-column: 1 / -1; }
  .slider-dots button {
    position: relative;
  }
  .slider-dots button::before {
    content: "";
    display: block;
    width: 100%;
    height: 34px;
    position: absolute;
    top: -17px;
    left: 0;
    opacity: 0;
  }
}

/* ========================================================================= */
/* ============================ ДЕСКТОП 1024+ ============================== */
/* ========================================================================= */

@media (min-width: 1024px) {


  :root {
    --fluid: calc(clamp(1024px, 100vw, 1920px) - 1024px);

    --layout-gutter:         calc(48px  + 52  * var(--fluid) / 896);
    --layout-column-text:    calc(420px + 214 * var(--fluid) / 896);
    --layout-column-heading: calc(620px + 390 * var(--fluid) / 896);
    --space-section:         calc(64px  + 56  * var(--fluid) / 896);
    --space-7:               calc(32px  + 18  * var(--fluid) / 896);

    /* Текучи только крупные кегли — они и продолжают шкалу, начатую до 1024.
       Мелкие (lg/md/sm/xs/2xs) в обоих макетах одинаковы и остаются
       макетными, поэтому здесь их нет. Отдельная ступенька на 1600px после
       этого не нужна: её роль играет верхняя граница на 1920. */
    --font-size-3xl: calc(36px + 28 * var(--fluid) / 896);
    --font-size-2xl: calc(32px + 16 * var(--fluid) / 896);
    --font-size-xl:  calc(26px + 14 * var(--fluid) / 896);
  }

  .site-header__inner { min-height: calc(88px + 22 * var(--fluid) / 896); }
  .site-header__logo { flex: none; }
  .site-header__logo img {
    width:  calc(150px + 50 * var(--fluid) / 896);
    height: calc(52px  + 18 * var(--fluid) / 896);
  }

  /* HERO: заголовок слева, кнопка справа — одна строка по низу кадра */
  /* Значок стоит не у края, а над кнопкой. До 1920 его отступ считается долей
     ширины (601/1920), выше — от края центрированного контента, иначе на
     широком мониторе он уехал бы от кадра вправо вместе с окном. */
  .hero__badge {
    top: calc(160px + 86 * var(--fluid) / 896);
    right: max(31.302%, calc(50% - 359px));
    width:  calc(132px + 68 * var(--fluid) / 896);
    height: calc(132px + 68 * var(--fluid) / 896);
  }
  .hero__fade { height: calc(200px + 110 * var(--fluid) / 896); }
  .hero__content {
    flex-direction: row;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--space-6);
    padding-inline: var(--layout-gutter);
    padding-bottom: calc(60px + 34 * var(--fluid) / 896);
  }
  /* У макеті заголовок hero — один рядок без переносу. Кегль тепер росте
     разом із шириною вікна, тому рядок укладається на будь-якій ширині
     десктопа, а не тільки на 1920 */
  .hero__title { max-width: none; white-space: nowrap; }

  /* STANDARDS: текст слева, коллаж с наложением справа */
  .standards {
    grid-template-columns: minmax(0, var(--layout-column-heading)) 1fr;
    gap: var(--space-6) var(--space-5);
  }
  .standards__text { grid-column: 1; }
  .standards__gallery {
    grid-column: 1 / -1;
    grid-template-columns: repeat(12, 1fr);
    grid-template-rows: auto auto;
    gap: 0;
    align-items: end;
  }
  .standards__img--wide {
    grid-column: 6 / -1;
    grid-row: 1 / 3;
    aspect-ratio: 930 / 538;
  }
  .standards__img--tall {
    grid-column: 5 / 9;
    grid-row: 1 / 3;
    z-index: 2;
    aspect-ratio: 510 / 594;
    align-self: start;
  }
  .standards__img--low {
    grid-column: 1 / 5;
    grid-row: 2;
    z-index: 1;
    aspect-ratio: 634 / 340;
  }

  /* ADVANTAGES: индикаторы | фото | текст.
     Слайд занимает обе правые колонки и повторяет их ширины внутри себя —
     так фото и текст стоят там же, где в макете (560 и 634 с зазором 220). */
  .advantages {
    /* Фото слайда тянется вместе с текстовой колонкой (--slide-text уже
       текучий), иначе к 1024px оно съело бы всю ширину слайда */
    --slide-media: calc(360px + 200 * var(--fluid) / 896);

    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    gap: var(--space-6);
  }
  .advantages .slider-viewport { grid-column: 2; }

  .advantages .slide {
    display: grid;
    grid-template-columns: var(--slide-media) minmax(0, var(--slide-text));
    justify-content: space-between;
    align-items: center;
    gap: var(--space-6);
  }
  .slide__media { width: var(--slide-media); }
  .slide__body { gap: var(--space-5); }
  /* От текста до кнопок в макете шаг крупнее, чем внутри самого текста */
  .slide__body .advantages__actions { margin-top: var(--space-4); }
  /* Подписи кнопок в макете однострочные. Если пара перестаёт помещаться
     в колонку (экран уже макетных 1920), вниз уходит вторая кнопка целиком,
     а не вторая строка её текста. */
  .advantages__actions .btn { white-space: nowrap; }
  /* Ширину 343px держит только кнопка расчёта (.btn--fixed);
     кнопка консультации в макете обжимает свою подпись */
  .advantages__actions .btn--accent { width: auto; }

  .colors { gap: var(--space-1); }
  .slide__color-title { font-weight: var(--font-weight-bold); }

  .sizes__inner .section-title { max-width: var(--layout-column-heading); }
  .sizes__list { gap: var(--space-6); align-items: end; }
  .size-card__ring { left: 30%; }

  /* Секция не выше экрана под шапкой — та же мерка, что у .prices выше.
     Именно max-height, а не height: если контент короче, секция остаётся
     низкой и пустоты внизу не появляется.

     Чтобы контент при этом всегда помещался, весь запас высоты забирает
     список карточек: заголовок, подпись и сноска стоят своей высотой
     (flex: none), а .sizes__list сжимается (min-height: 0 снимает
     автоматический минимум флекс-элемента, без него он упёрся бы в высоту
     содержимого и секция всё равно вылезла бы за экран).

     Внутри карточки так же сжимается схема: max-height не даёт ей выйти за
     свою ячейку, object-fit: contain держит пропорции, а object-position
     оставляет её прижатой к низу — карточки в макете выровнены по нижнему
     краю (align-items: end строкой выше). */
  /* Нижний предел 720px: на совсем коротком окне секция чуть выйдет за
     экран (страница просто доскроллится), но ринвы не сожмутся в точку —
     раньше при 100vh ≈ 740px на них оставалось меньше 100px высоты. */
  .sizes { max-height: max(calc(100vh - 90px), 720px); }
  .sizes__inner {
    max-height: max(calc(100vh - 90px), 720px);
    /* Первыми сжимаются отступы, а не ринвы: на окне до 900px высоты
       отступ 40px, к 980px дорастает до макетных --space-section (120px
       на 1920). На обычных 1080p — макетный отступ, как и было. */
    padding-block: clamp(40px, calc(100vh - 860px), var(--space-section));
  }
  .sizes__inner > * { flex: none; }
  /* В одну-две строки вместо трёх — экономит высоту ради ринв */
  .sizes__footnote { max-width: 100%; }
  .sizes__list {
    flex: 1 1 auto;
    min-height: 0;
    grid-template-rows: minmax(0, 1fr);
    /* Карточки тянутся на высоту строки: только так они получают ту самую
       ограниченную высоту, внутри которой сжимается схема. Выравнивание по
       нижнему краю из строки выше при этом сохраняется — его теперь держит
       сама схема (align-self: end + object-position ниже). */
    align-items: stretch;
  }
  .size-card { min-height: 0; }
  .size-card__visual {
    min-height: 0;
    grid-template-rows: minmax(0, 1fr);
  }
  .size-card__img {
    min-height: 0;
    max-height: 100%;
    align-self: end;
    object-position: center bottom;
  }

  /* ELEMENTS: текст слева, фото справа.
     Колонки заданы долями макета (1010 и 680), а не пикселями: пропорция
     держится на любой ширине, а зазор между ними остаётся gap'ом. */
  .elements {
    grid-template-columns: minmax(0, 1010fr) minmax(0, 680fr);
    align-items: center;
    gap: var(--space-5);
  }

  /* PRICES: параметры и стоимость слева, CTA справа, панель во всю ширину.
     Сетка теперь у слайда — в нём лежит весь расчёт целиком.
     Высота секции взята из макета: от неё зависит, что стрелки попадают
     в пустой промежуток между параметрами и стоимостью. */
  .prices { --slider-arrow-inset: calc(48px + 40 * var(--fluid) / 896); height: calc(100vh - 90px);}
  /* Высота тянется вместе с шириной, но снизу ограничена жёстче остальных
     метрик: стрелки стоят по центру секции, и если средняя строка сожмётся
     сильнее, они наедут на CTA — панель элементов внизу почти не сжимается,
     поэтому весь запас высоты забирает именно она. */
  .prices__inner {
    grid-template-rows: auto 1fr;
    height: 100%;
    padding-bottom: calc(100vh - 700px);
  }
  .prices .slider-arrow {
    top: auto;
    bottom: 50%;
  }
  /* Средняя строка тянется, а стоимость прижата к её низу: в макете от
     параметров до стоимости далеко, а от стоимости до панели — почти вплотную */
  .prices .slide {
    grid-template-columns: minmax(0, var(--layout-column-text)) auto;
    grid-template-rows: auto 1fr auto;
    gap: var(--space-6);
  }
  .prices__params { grid-column: 1; grid-row: 1; }
  .prices__total  { grid-column: 1; grid-row: 2; align-self: end; }
  /* Кнопка в макете стоит справа на уровне стоимости, а не параметров */
  .prices__cta    { grid-column: 2; grid-row: 2; justify-self: end; align-self: end; }
  .parts-panel    { grid-column: 1 / -1; grid-row: 3; }

  .parts-panel {
    gap: var(--space-4);
    padding: var(--space-5) var(--space-4);
  }
  .parts-panel__title { font-size: var(--font-size-md); text-align: center; }
  .parts-panel__list { gap: var(--space-5); }
  .part img {
    width:  calc(56px + 24 * var(--fluid) / 896);
    height: calc(56px + 24 * var(--fluid) / 896);
  }
  .part span { font-size: var(--font-size-md); }

  .calc__form {
    grid-template-columns: repeat(3, minmax(0, 343px));
    justify-content: center;
    gap: var(--space-4);
  }
  .consent { grid-column: 3; }

  /* SOFFITS: текст и образцы слева, фото справа во всю высоту */
  /* У макеті фото виходить у правий край екрана, тому праворуч відступу немає */
  .soffits {
    grid-template-columns: minmax(0, 634fr) minmax(0, 1150fr);
    gap: var(--space-6);
    align-items: stretch;
    padding-right: 0;
  }
  .soffits__figure { height: 100%; }
  /* Первая колонка — образец, вторая — зазор до подписи (в макете 100px) */
  .finish {
    grid-template-columns:
      calc(132px + 68 * var(--fluid) / 896)
      calc(64px  + 36 * var(--fluid) / 896)
      1fr;
  }
  .finish__swatch {
    width:  calc(132px + 68 * var(--fluid) / 896);
    height: calc(132px + 68 * var(--fluid) / 896);
  }

  .site-footer { padding-block: var(--space-section) var(--space-6); }
  .site-footer__logo {
    width:  calc(260px + 115 * var(--fluid) / 896);
    height: calc(90px  + 40  * var(--fluid) / 896);
  }
  .site-footer__swoosh {
    width:  calc(260px + 115 * var(--fluid) / 896);
    height: calc(35px  + 15  * var(--fluid) / 896);
  }
  .site-footer__col--contacts { align-items: flex-end; text-align: right; }
  .site-footer__legal { margin-top: var(--space-6); }

  .popup__inner {
    padding: calc(var(--space-7) + var(--space-6)) var(--layout-gutter);
  }
  .popup__close { top: var(--space-7); right: var(--layout-gutter-popup); }

  /* Как в макете: два поля и кнопка в одну строку, согласие — под кнопкой */
  .popup-form {
    grid-template-columns: repeat(3, minmax(0, 343px));
    justify-content: center;
    gap: var(--space-5) var(--space-4);
  }
  .popup-form__submit  { grid-column: 3; grid-row: 1; }
  .popup-form__consent { grid-column: 3; grid-row: 2; }
  .calc__title {
    text-align: center;
  }
  .finish__logo {
    width: 120px;
    height: auto;
    object-fit: contain;
    max-width: none;
    margin-left: -30px;
  }
}
@media (min-width: 1024px) and (min-height: 750px){
  .prices__inner {
    padding-bottom: 40px;
  }

}
/* ========================================================================= */
/* ======================= ШАПКА В РЯДОК 1280+ ============================= */
/* ========================================================================= */

/* Единственное место, где раскладка всё же переключается ступенькой.
   Логотип, пункты меню, телефон и кнопка в один ряд требуют около 1050px
   даже на самых мелких кеглях, а на 1024 для контента есть только 913 —
   ряд там не помещается ни при каком масштабе. Поэтому до 1280 шапка
   остаётся свёрнутой в бургер (меню и телефон живут в модальном окне),
   а разворачивается там, где для неё хватает ширины. */
@media (min-width: 1340px) {
  :root {
    --layout-column-text:    calc(620px + 214 * var(--fluid) / 896);
  }
  .site-header__inner {
    flex-wrap: nowrap;
    gap: var(--space-2) calc(12px + 8 * var(--fluid) / 896);
  }
  .site-nav { display: block; }
  .site-header__contacts { display: flex; gap: calc(12px + 8 * var(--fluid) / 896); }
  .site-header__phone { display: block; }
  .site-header__menu { display: none; }
  /* Горизонтальный padding кнопки тоже текучий — на нижней границе ряда
     макетные 32px с каждой стороны и были той парой десятков пикселей,
     из-за которых подпись кнопки ломалась на две строки */
  .site-header__contacts .btn {
    padding: var(--space-3) calc(20px + 12 * var(--fluid) / 896);
  }
  /* Зазоры между пунктами меню — тоже текучие */
  .site-nav__list { gap: calc(12px + 8 * var(--fluid) / 896); }
}

/* --------------------- уважение к системным настройкам ------------------- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

/* ============================================================================
   PROFiL landing page — пиннинг слайдеров (переваги, приклади розрахунку)

   Новый файл вместо правки style.css. Работает в паре со slider.js:
   JS меряет фактическую высоту .slider-pin__stick (она уже учитывает самый
   высокий слайд — оба слайдера складывают слайды в одну ячейку/ряд, поэтому
   контейнер и так авто-высится по максимуму, см. комментарий в slider.js) и
   выставляет .slider-pin высоту = высота стика + (число слайдов − 1) высот
   экрана. Пока пользователь скроллит этот «разгон», стик стоит прилипшим
   (position: sticky) под шапкой, а JS на каждый кадр скролла двигает слайды —
   это и даёт «нельзя проскроллить, пока не долистал» и живой drag-follow
   одновременно, без перехвата wheel/touchmove.

   --pin-top       высота шапки (slider.js меряет .site-header и пишет сюда) —
                   на неё сдвинут sticky top, чтобы стик не заезжал под шапку
   ========================================================================== */

.slider-pin {
  position: relative;
}

.slider-pin__stick {
  position: sticky;
  top: var(--pin-top, 0px);
  display: flex;
  align-items: center;
  /* Не 100vh: стик и так сдвинут вниз на --pin-top (высота шапки), полная
     100vh отсюда вылезла бы своим нижним краем за экран */
  min-height: calc(100vh - var(--pin-top, 0px));
}

.slider-pin__stick > section {
  width: 100%;
}

/* Пока slider.js не отработал (например, JS отключён) — секции остаются
   в обычном потоке, просто без пиннинга и авто-высоты у обёртки */
.slider-pin:not([data-pin-ready]) {
  height: auto !important;
}

#advantages-pin .slider-pin__stick { background: var(--color-bg); }
#prices-pin .slider-pin__stick { background: var(--color-bg-inverse); }

/* ---------------------- смена слайдов: orientation-y ----------------------
   В style.css слайд уходит вверх, следующий приходит снизу, сдвиг всего 40px
   (лёгкий fade). Переопределяем на полноценный «пуш» — так же, по ходу
   обычного скролла страницы вниз (старый слайд уезжает ВВЕРХ, новый
   заезжает СНИЗУ — направление совпадает с тем, что приходило до правки на
   180°, только теперь на полную высоту, а не на 40px). translateY в % — это
   доля высоты самого слайда, поэтому 100% всегда даёт ровно полный
   уход/заезд независимо от того, какой слайд выше/ниже.
   :not(.is-current):not(.is-past) — без этого база (2 класса) совпала бы по
   специфичности с .slide.is-current из style.css (тоже 2 класса) и, идя
   в каскаде позже, перебивала бы и его — текущий слайд тоже уезжал бы. */
.orientation-y {
  --slide-shift-x: 0px;
  --slide-shift-y: 100%;
}
.orientation-y .slide:not(.is-current):not(.is-past) {
  transform: translate(var(--slide-shift-x, 0px), var(--slide-shift-y, 100%));
}
.orientation-y .slide.is-past {
  transform: translate(var(--slide-shift-x, 0px), calc(-1 * var(--slide-shift-y, 100%)));
}
/* ============================================================================
   PROFiL landing page — точкові правки

   Новий файл, style.css не чіпаємо. Дві секції:
   1. Баги на мобільній ширині (< 768px) — #calculator і #soffits.
   2. Анімація появи кроків розрахунку (#calculator, макет 2:1252) — працює
      в парі з reveal.js, який один раз додає .is-visible на .steps через
      IntersectionObserver.
   ========================================================================== */

@media (max-width: 767.98px) {

  /* --- #calculator: три кроки не влазять в один ряд на 375px ------------
     .steps у style.css має column-gap: var(--space-5) = 30px — цього
     вистачає з планшета, а на мобільному 3 × 98px + 2 × 30px = 354px не
     влазить у контейнер (~335px при боковому відступі 20px), і третій крок
     переносить на новий рядок (макет 2:753 тримає всі три в один ряд). */
  .steps { column-gap: var(--space-3); }

  /* --- #soffits: лого мало лежати поверх зразка, а не окремою колонкою --
     Коментар у style.css над десктопним .finish прямо каже: «друга колонка —
     зазор до підпису» — тобто лого й задумувалося як накладення на зразок,
     просто це так і не було реалізовано (position: absolute бракувало), і на
     вузькій мобільній ширині трьом колонкам (зразок + лого + підпис) просто
     не вистачає місця. Зразок і лого кладемо в одну комірку грида (той самий
     прийом, що й .slide з grid-area: 1 / 1 у слайдерах) — лого притискається
     до низу-лівого краю зразка своїми ж 100×50, підпис іде окремим рядком
     під низ на всю ширину. */
  .finish {
    grid-template-columns: 1fr;
    grid-template-rows: auto auto;
    row-gap: var(--space-2);
  }
  .finish__swatch { grid-row: 1; grid-column: 1; }
  .finish__logo {
    grid-row: 1;
    grid-column: 1;
    align-self: end;
    justify-self: start;
    margin: var(--space-2);
  }
  .finish__name { grid-row: 2; grid-column: 1; }

  /* --- #soffits: макет (2:741) двоколонковий навіть на мобільному — зліва
     заголовок + зразки, справа фото на всю висоту впритул до краю екрана.
     У style.css .soffits — грід без колонок (одна на одну, обидва блоки
     в стовпчик) аж до 1024px; тут вмикаємо ту саму ідею, що й на десктопі,
     просто з вужчими пропорціями під мобільну ширину. */
  .soffits {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: var(--space-4);
    align-items: stretch;
    padding-right: 0;
  }
  .soffits__figure { height: 100%; }
}

/* ==================== ТЕКСТ ПОМИЛКИ ПОЛЯ (#calculator) ====================
   У style.css .calc-field__error завжди резервує висоту одного рядка
   (min-height) і відступ зверху — навіть коли текст порожній. Це і є «занадто
   великі відступи між полями»: заготовка під помилку, якої ще немає. Ховаємо
   її до нуля за замовчуванням і повертаємо тільки коли popup.js виставляє
   .calc-field--invalid (разом із самим текстом помилки). */
.calc-field__error {
  min-height: 0;
  margin-top: 0;
  overflow: hidden;
  transition: min-height 0.2s ease, margin-top 0.2s ease;
}
.calc-field--invalid .calc-field__error {
  min-height: calc(var(--font-size-2xs) * var(--line-height-base));
  margin-top: var(--space-2);
}

@media (prefers-reduced-motion: reduce) {
  .calc-field__error { transition: none; }
}

/* ============== АНІМАЦІЯ КРОКІВ РОЗРАХУНКУ (#calculator) =================
   За макетом кроки з'являються по черзі, коли блок доходить до екрана, а не
   всі одразу. Стрілка-роздільник — ::after самого .step (style.css), тому
   їде разом зі своїм кроком без окремих правил. */
.steps .step {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 0.5s ease, transform 0.5s ease;
}
.steps.is-visible .step {
  opacity: 1;
  transform: none;
}
.steps.is-visible .step:nth-child(2) { transition-delay: 0.15s; }
.steps.is-visible .step:nth-child(3) { transition-delay: 0.3s; }

@media (prefers-reduced-motion: reduce) {
  .steps .step {
    opacity: 1;
    transform: none;
    transition: none;
  }
}



.page-simple article {
  padding-top: 60px;
  padding-bottom: 120px;
}
.page-simple .container {
  margin: 0 auto;
  max-width: 1100px;
  width: 100%;
  padding: 0 45px;
}
.page-simple h1,
.page-simple h2,
.page-simple h3,
.page-simple h4,
.page-simple h5,
.page-simple h6 {
  margin-bottom: 10px;
  color: #F15F22;
  font-family: "Noto Sans";
  font-size: 40px;
  font-style: normal;
  font-weight: 500;
  line-height: 120%; /* 48px */
  letter-spacing: -0.8px;
  text-transform: uppercase;
}
.page-simple h1 {
  font-size: 48px;
  letter-spacing: -0.96px;
}
.page-simple p {
  margin-bottom: 0;
}
.page-simple ul {
  margin-bottom: 30px;
}
.page-simple br {
  display: block;
  margin-bottom: 24px;
}
.page-simple ul {
  padding-left: 26px;
}
.page-simple li {
  list-style: disc;
  font-size: 18px;
  font-style: normal;
  font-weight: 400;
  line-height: 120%; /* 21.6px */
  letter-spacing: -0.36px;
}

@media(max-width: 880px){
  .page-simple article {
    padding-top: 30px;
    padding-bottom: 60px;
  }
  .page-simple .container {
    padding: 0 16px;
  }
  .page-simple h1,
  .page-simple h2,
  .page-simple h3,
  .page-simple h4,
  .page-simple h5,
  .page-simple h6 {
    font-size: 20px;
    letter-spacing: -0.4px;
  }
  .page-simple h1 {
    font-size: 24px;
    letter-spacing: -0.48px;
  }
  .page-simple p {
    margin-bottom: 0;
    font-size: 16px;
  }
  .page-simple ul {
    margin-bottom: 20px;
  }
  .page-simple br {
    display: block;
    margin-bottom: 20px;
  }
  .page-simple ul {
    padding-left: 24px;
  }
  .page-simple li {
    font-size: 16px;
    letter-spacing: -0.28px;
  }
  #soffits {
    position: relative;
    display: block;
  }
  .soffits__body {
    width: 100%;
    max-width: 100%;
    position: relative;
    z-index: 2;
  }
  .soffits__figure img {
    position: absolute;
    top: 0;
    width: 190px;
    height: 100%;
    right: 0;
  }
  .finish__name {
    font-size: 13px;
  }
  .finish {
    position: relative;
  }
  .finish__logo {
    position: absolute;
    top: 90px;
    left: 80px;
    margin: 0;
    width: 50px;
    height: auto;
  }
  .color {
    width: 36px;
    height: 36px;
  }
  .advantages__actions .btn,
  .prices .btn {
    font-size: 13px;
  }
  .slider-pin__stick > section.advantages {
    padding-top: 0;
  }
  .parts-panel {
    min-width: 0;
    max-width: 100%;
    width: 100%;
  }
  .standards__gallery {
    display: flex;
    flex-direction: column;
    gap: 10px;
  }
}
/* ================== MOBILE UX FIXES (24.09.2026) ========================= */
/* iOS Safari зумить сторінку при фокусі на полі з кеглем <16px — під час
   введення імені/телефону поле тікає з-під пальця. */
@media (max-width: 880px) {
  .field input,
  .popup-form input,
  .profil-calc-page input,
  [data-profil-calc] input {
    font-size: 16px;
  }

  /* Тач-таргети: візуал не змінюємо, додаємо зону попадання пальцем
     (рекомендації Apple HIG ≥44px у діаметрі). */
  .slider-dots button {
    position: relative;
  }
  .slider-dots button::before {
    content: "";
    display: block;
    width: 100%;
    height: 34px;
    position: absolute;
    top: -17px;
    left: 0;
    opacity: 0;
  }
  .prices__thumb button {
    position: relative;
  }
  .prices__thumb button::before {
    content: "";
    display: block;
    width: 28px;
    height: 28px;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    border-radius: 50%;
    opacity: 0;
  }
  .site-header__menu {
    padding: 14px 10px;
    margin: -14px -10px;
  }
  .mobile-menu__close {
    padding: 14px 10px;
    margin: -14px -10px;
  }
  .popup__close {
    padding: 14px 10px;
    margin: -14px -10px;
  }
  .color {
    width: 44px;
    height: 44px;
  }
}

/* Ціни — автоплей-карусель, а не скрол-пін: на мобільному контент секції
   нижчий за екран, і min-height:100vh стика розтягує обгортку — секція
   центрується, а зверху/знизу визирає темний фон стика. Прибираємо
   розтягування: висота секції = її контенту. */
@media (max-width: 880px) {
  #prices-pin .slider-pin__stick {
    min-height: 0;
  }
}
