/* ==========================================================================
   home.css — ритм страниц и механизм появления при прокрутке.
   Разделы 1–5 — общие примитивы, их не переопределяют; 6 и дальше — по
   разделу на секцию. Подключается ПОСЛЕ css/styles.css: раздел 1 переносит
   токены варианта в --home-*, и это единственное место, знающее про вариант.

   Оглавление:
     1. Привязка к палитре варианта
     2. Ритм секций
     3. Шапка секции
     4. Сетка контента и базовая ячейка
     5. Механизм появления при прокрутке (js/reveal.js)
     6. Секция #products — пять строк-разворотов
     7. Секция #why — bento доверия со счётчиками цифр
     8. Секция #process — пять этапов, крупные кружки с цифрами
     9. Секция #faq — семь вопросов
    10. Секция #works — залипающая лента работ
    11. Секция #calc — калькулятор стоимости и сводка расчёта в модалке
    12. Секция #reviews — счётчик и лента с местом под настоящие отзывы
    13. Секция #request — финальная заявка со свечением контуров
    14. Футер #contacts — контакты, мессенджеры, адрес и карта
    15. Страница «Рольставни» — intro направления, карточки, заглушка акций
    16. Страница «Примеры работ» — интро, чипы, сетка снимков, GLightbox
    17. Страница «О компании» — слайдер сканов сертификатов
    18. Секция #profiles — производители профильных систем
    19. Секция #clients — логотипы клиентов
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Привязка к палитре варианта
   -------------------------------------------------------------------------- */

body[data-variant="3"] {
  --home-bg: var(--v3-page);
  /* Светлее страницы, но темнее ячейки, иначе карточки на ней не читаются */
  --home-bg-tint: var(--v3-page-tint);
  --home-surface: var(--v3-cell);
  --home-surface-hi: var(--v3-cell-hi);
  --home-line: var(--v3-line);
  --home-line-strong: var(--v3-line-strong);
  --home-ink: var(--v3-ink);
  --home-ink-muted: var(--v3-ink-muted);
  --home-ink-dim: var(--v3-ink-dim);
  --home-accent: var(--rrs-accent);
  --home-radius: var(--v3-radius);
  --home-gap: var(--v3-gap);
  --home-card-pad: var(--v3-cell-pad);
  --home-header-h: var(--v3-header-h);
  /* Сигнал ошибки янтарный, а не красный: акцент варианта сам красный. */
  --home-danger: var(--rrs-modal-danger);
}

/* --------------------------------------------------------------------------
   2. Ритм секций
   -------------------------------------------------------------------------- */

.home-section {
  --home-section-pad: clamp(40px, 6vw, 76px);

  position: relative;
  padding-block: var(--home-section-pad);
  /* шапка sticky: якорь не должен уезжать под неё */
  scroll-margin-top: calc(var(--home-header-h, 60px) + 8px);
  border-top: 1px solid var(--home-line);
  background-color: var(--home-bg);
  color: var(--home-ink);
}

.home-section--tint {
  background-color: var(--home-bg-tint);
}

/* .btn--ghost из base.css рассчитан на светлую страницу; здесь подложка
   тёмная, и без этой правки кнопка тёмная по тёмному. */
.home-section .btn--ghost {
  color: var(--home-ink);
}

.home-section .btn--ghost:hover {
  background-color: var(--home-ink);
  color: var(--home-bg);
  box-shadow: none;
}

.home-section .btn--ghost .btn__icon {
  background-color: color-mix(in srgb, var(--home-ink) 10%, transparent);
}

.home-section .btn--ghost:hover .btn__icon {
  background-color: color-mix(in srgb, var(--home-bg) 18%, transparent);
}

.home-section--flush {
  border-top: 0;
}

.home-section--tight {
  --home-section-pad: clamp(28px, 4vw, 52px);
}

/* Подрезает вылет data-reveal="left|right" за край экрана. Именно clip,
   а не hidden: hidden сделал бы секцию контейнером прокрутки и сломал
   position: sticky у потомков. */
.home-section--clip {
  overflow-x: clip;
}

/* --------------------------------------------------------------------------
   3. Шапка секции
   -------------------------------------------------------------------------- */

.home-section__head {
  display: grid;
  gap: var(--rrs-space-2);
}

.home-section__headline {
  display: grid;
  gap: var(--rrs-space-1);
}

.home-section__label {
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--home-ink-dim);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: var(--rrs-ls-label);
  text-transform: uppercase;
}

.home-section__label::before {
  content: "";
  flex: 0 0 auto;
  width: 18px;
  height: 1px;
  background-color: var(--home-accent);
}

/* overflow-wrap: anywhere, а не break-word: только это значение уменьшает
   min-content заголовка, поэтому длинное слово («конфиденциальности» на 320px)
   переносится само и не растягивает страницу вбок. С break-word ширина
   колонки осталась бы прежней. Разрывов в разметке заголовков быть не должно. */
/* font-family/font-weight заданы явно: часть заголовков секции теперь <p>
   (сквозные футер/заявка — не должны попадать в контур h1-h6), и правило
   h1,h2 в base.css их больше не красит. */
.home-section__title {
  max-width: 22ch;
  font-family: var(--rrs-font-heading);
  font-size: clamp(24px, 3vw, 34px);
  font-weight: 700;
  line-height: 1.06;
  letter-spacing: -.03em;
  text-wrap: balance;
  overflow-wrap: anywhere;
}

.home-section__lead {
  max-width: 54ch;
  color: var(--home-ink-muted);
  font-size: var(--rrs-fs-body);
  line-height: 1.55;
}

.home-section__aside {
  display: flex;
  flex-wrap: wrap;
  gap: var(--rrs-space-1);
}

.home-section__body {
  margin-top: clamp(28px, 4vw, 48px);
}

.home-section__foot {
  margin-top: clamp(20px, 3vw, 32px);
  color: var(--home-ink-dim);
  font-size: var(--rrs-fs-small);
  line-height: 1.5;
}

/* --------------------------------------------------------------------------
   4. Сетка контента и базовая ячейка
   -------------------------------------------------------------------------- */

.home-grid {
  display: grid;
  gap: var(--home-gap);
  grid-template-columns: repeat(var(--home-cols, 1), minmax(0, 1fr));
}

.home-card {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--rrs-space-1);
  padding: var(--home-card-pad);
  border: 1px solid var(--home-line);
  border-radius: var(--home-radius);
  background-color: var(--home-surface);
  transition: border-color var(--rrs-dur) var(--rrs-ease),
              background-color var(--rrs-dur) var(--rrs-ease),
              transform var(--rrs-dur) var(--rrs-ease);
}

/* Необязательная отметка в правом верхнем углу карточки: заголовок остаётся
   первым, что видит глаз, а иконка читается как инженерная маркировка.
   Добавка аддитивная — там, где .home-card__icon нет, не меняется ничего. */
.home-card__icon {
  position: absolute;
  top: var(--home-card-pad);
  right: var(--home-card-pad);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  color: var(--home-accent);
}

/* Толщина контура абсолютная и одна на все иконки сайта (вторая половина —
   .spec-list__icon в pages.css): на странице уже есть один вес линии — 1px
   у разделителей и рамок, — и иконка обязана попадать в него, а не считать
   свою толщину от собственного размера. */
.home-card__icon svg {
  width: 100%;
  height: 100%;
  stroke-width: 1.5;
}

/* Заголовок не заезжает под отметку: ширина иконки плюс отбивка. */
.home-card__icon + .home-card__title {
  padding-right: 38px;
}

/* Кнопка карточки прижата к низу — требование верстки проекта. */
.home-card__foot {
  margin-top: auto;
  padding-top: var(--rrs-space-2);
}

@media (min-width: 560px) {
  .home-grid--2,
  .home-grid--4 { --home-cols: 2; }
}

@media (min-width: 900px) {
  .home-section__head {
    grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr);
    align-items: end;
    column-gap: var(--rrs-space-6);
  }

  .home-section__lead {
    font-size: var(--rrs-fs-body-lg);
  }

  .home-grid--3 { --home-cols: 3; }
}

@media (min-width: 1180px) {
  .home-grid--4 { --home-cols: 4; }
}

/* Низкое окно десктопа — порог из контрактного набора base.css, §1.
   Отступ секции считается от ширины, и на ноутбуке съедал бы треть высоты. */
@media (min-width: 900px) and (max-height: 1000px) {
  .home-section {
    --home-section-pad: clamp(28px, 3.5vw, 48px);
  }
}

@media (hover: hover) and (pointer: fine) {
  .home-card--interactive:hover {
    border-color: var(--home-line-strong);
    background-color: var(--home-surface-hi);
    transform: translateY(-2px);
  }
}

/* --------------------------------------------------------------------------
   5. Механизм появления при прокрутке
   Контракт с js/reveal.js: data-reveal="up|fade|scale|left|right" (пустое =
   up), data-reveal-group — очередь --reveal-index, data-revealed — конечное
   состояние. Скрытое начальное состояние разрешено ТОЛЬКО под флагом
   html[data-reveal-engine="on"], который ставит скрипт: без JS видно всё.
   -------------------------------------------------------------------------- */

[data-reveal] {
  transition: opacity 400ms var(--rrs-ease),
              transform 400ms var(--rrs-ease);
  transition-delay: calc(var(--reveal-index, 0) * 55ms);
  will-change: opacity, transform;
}

[data-reveal][data-revealed] {
  will-change: auto;
}

html[data-reveal-engine="on"] [data-reveal]:not([data-revealed]) {
  opacity: 0;
  transform: translate3d(0, 16px, 0);
}

html[data-reveal-engine="on"] [data-reveal="fade"]:not([data-revealed]) {
  transform: none;
}

html[data-reveal-engine="on"] [data-reveal="scale"]:not([data-revealed]) {
  transform: translate3d(0, 8px, 0) scale(.985);
}

/* Горизонтальный выезд — только с 900px и только внутри .home-section--clip:
   вне обрезающей секции сдвиг вбок даёт горизонтальную прокрутку.
   Ограничение держит селектор; в остальных случаях эффект вырождается в up. */
@media (min-width: 900px) {
  html[data-reveal-engine="on"] .home-section--clip [data-reveal="left"]:not([data-revealed]) {
    transform: translate3d(-24px, 0, 0);
  }

  html[data-reveal-engine="on"] .home-section--clip [data-reveal="right"]:not([data-revealed]) {
    transform: translate3d(24px, 0, 0);
  }
}

/* Страховка на случай, когда reduce включили на уже открытой странице. */
@media (prefers-reduced-motion: reduce) {
  html[data-reveal-engine="on"] [data-reveal] {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
}

/* --------------------------------------------------------------------------
   6. Секция #products — строки-развороты
   Разметка всех строк идентична буква в букву ради CMS-повторителя:
   чередование сторон и направление выезда задаёт :nth-child(even) ниже,
   а не модификатор класса в HTML.
   -------------------------------------------------------------------------- */

.products-row {
  display: grid;
  gap: var(--rrs-space-3);
  padding-block: clamp(28px, 4vw, 44px);
}

.products-row:first-child {
  padding-block-start: 0;
}

.products-row:last-child {
  padding-block-end: 0;
}

.products-row + .products-row {
  border-top: 1px solid var(--home-line);
}

/* --- кадр направления ---------------------------------------------------- */

.products-row__frame {
  position: relative;
  overflow: hidden;
  aspect-ratio: 4 / 3;
  border: 1px solid var(--home-line);
  border-radius: var(--home-radius);
  background-color: var(--home-surface);
}

/* 6% запаса сверху и снизу — ровно столько, сколько съедает параллакс. */
.products-row__img {
  position: absolute;
  inset: -6% 0;
}

.products-row__img img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--rrs-dur) var(--rrs-ease);
}

/* Переход на страницу направления — по картинке и по названию; картинка
   декоративна для клавиатуры и скринридера (настоящая ссылка одна,
   на названии), но для курсора остаётся полноценной целью и откликается
   тем же приёмом, что .works__img, .gallery-shot__img и .cert-card__img. */
@media (hover: hover) and (pointer: fine) {
  .products-row__media:hover .products-row__img img {
    transform: scale(1.04);
  }
}

@keyframes products-parallax {
  from { transform: translate3d(0, -4.5%, 0); }
  to   { transform: translate3d(0, 4.5%, 0); }
}

@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .products-row__img {
      animation: products-parallax linear both;
      animation-timeline: view();
      animation-range: cover 0% cover 100%;
    }
  }
}

/* --- заглушка на месте будущей фотографии --------------------------------
   Фото ещё не переданы; пунктир и штриховка нужны, чтобы пустое место
   нельзя было принять за элемент дизайна. Имена файлов — в data-todo. */

.products-row__frame--empty {
  border-style: dashed;
  border-color: var(--home-line-strong);
  background-color: var(--home-bg-tint);
}

.products-row__empty {
  position: absolute;
  inset: 0;
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 10px;
  padding: var(--rrs-space-3);
  text-align: center;
}

.products-row__empty-icon {
  display: inline-flex;
  color: var(--home-ink-dim);
}

.products-row__empty-icon svg {
  width: 26px;
  height: 26px;
  stroke-width: 1.5;
}

.products-row__empty-text {
  color: var(--home-ink-dim);
  font-size: 13px;
  font-weight: 500;
}

/* --- текстовая колонка --------------------------------------------------- */

.products-row__text {
  display: flex;
  flex-direction: column;
  gap: var(--rrs-space-2);
}

.products-row__name {
  font-family: var(--rrs-font-heading);
  font-size: clamp(19px, 2.4vw, 28px);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -.03em;
  text-wrap: balance;
}

/* Название — ссылка на страницу направления; h3 здесь нет нарочно:
   это один из двух переходов на странице, второй — картинка выше. */
.products-row__name a {
  color: inherit;
  text-decoration: none;
  transition: color var(--rrs-dur) var(--rrs-ease);
}

.products-row__name a:hover,
.products-row__name a:focus-visible {
  color: var(--home-accent);
}

.products-row__tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: -8px;
}

.products-row__tag {
  padding: 4px 12px;
  border: 1px solid var(--home-line);
  border-radius: var(--rrs-radius-pill);
  background-color: var(--home-surface-hi);
  color: var(--home-ink-muted);
  font-size: 12px;
  font-weight: 500;
  white-space: nowrap;
}

.products-row__desc {
  max-width: 62ch;
  color: var(--home-ink-muted);
  font-size: var(--rrs-fs-body);
  line-height: 1.6;
}

.products-row__spec {
  display: grid;
  border-top: 1px solid var(--home-line);
}

.products-row__spec-row {
  display: grid;
  gap: 2px;
  padding-block: 12px;
  border-bottom: 1px solid var(--home-line);
}

.products-row__spec-key {
  color: var(--home-ink-dim);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: var(--rrs-ls-label);
  text-transform: uppercase;
}

.products-row__spec-val {
  margin: 0;
  color: var(--home-ink-muted);
  font-size: var(--rrs-fs-small);
  line-height: 1.45;
}

.products-row__foot {
  display: grid;
  gap: 12px;
  margin-top: auto;
  padding-top: var(--rrs-space-1);
}

/* Цены в разделе нет: цена после замера, вместо цифры ссылка на расчёт. */
.products-row__price {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--home-ink-dim);
  font-size: var(--rrs-fs-small);
}

.products-row__price::before {
  content: "";
  flex: 0 0 auto;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background-color: var(--home-accent);
}

.products-row__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px var(--rrs-space-3);
}

@media (min-width: 560px) {
  .products-row__spec-row {
    grid-template-columns: 132px minmax(0, 1fr);
    gap: var(--rrs-space-2);
    align-items: baseline;
  }
}

@media (min-width: 900px) {
  .products-row {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: clamp(28px, 4vw, 56px);
    align-items: stretch;
    padding-block: clamp(40px, 5vw, 64px);
  }

  /* aspect-ratio снят намеренно: вместе с height: 100% браузер выводит
     из высоты ШИРИНУ, и кадр вылезает за свою колонку грида. */
  .products-row__media {
    display: flex;
  }

  .products-row__frame {
    flex: 1;
    aspect-ratio: auto;
    min-height: 340px;
  }

  /* Стороны меняет колонка, а не order: порядок обхода с клавиатуры
     остаётся прежним. Чётность считает :nth-child, разметка строк одинакова. */
  .products-row:nth-child(even) .products-row__media {
    grid-column: 2;
    grid-row: 1;
  }

  .products-row:nth-child(even) .products-row__text {
    grid-column: 1;
    grid-row: 1;
  }

  /* Направление выезда на чётных строках переопределяется здесь, а не
     другим значением data-reveal в разметке: атрибут везде одинаковый. */
  html[data-reveal-engine="on"] .products-row:nth-child(even) [data-reveal="right"]:not([data-revealed]) {
    transform: translate3d(-24px, 0, 0);
  }

  html[data-reveal-engine="on"] .products-row:nth-child(even) [data-reveal="left"]:not([data-revealed]) {
    transform: translate3d(24px, 0, 0);
  }
}

/* --------------------------------------------------------------------------
   7. Секция #why — bento доверия
   Цифры добегают счётчиком на CSS (@property --why-num + counter()), пуск
   даёт data-revealed от общего механизма раздела 5 — своего наблюдателя нет.
   Конечное значение лежит в разметке текстом и прячется только под флагом.
   -------------------------------------------------------------------------- */

@property --why-num {
  syntax: "<integer>";
  initial-value: 0;
  inherits: true;
}

.why-bento {
  display: grid;
  gap: var(--home-gap);
}

.why-bento__cell {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: clamp(18px, 2vw, 26px);
  border: 1px solid var(--home-line);
  border-radius: var(--home-radius);
  background-color: var(--home-surface);
}

.why-bento__cell--lead {
  gap: var(--rrs-space-2);
  border-color: var(--home-line-strong);
}

.why-bento__title {
  font-family: var(--rrs-font-heading);
  font-size: clamp(18px, 2.1vw, 25px);
  font-weight: 700;
  line-height: 1.14;
  letter-spacing: -.03em;
  text-wrap: balance;
}

.why-bento__subtitle {
  font-size: 15px;
  font-weight: 600;
  line-height: 1.25;
}

.why-bento__text {
  color: var(--home-ink-muted);
  font-size: var(--rrs-fs-small);
  line-height: 1.55;
}

.why-bento__cell--lead .why-bento__text {
  max-width: 46ch;
  font-size: var(--rrs-fs-body);
}

/* --- цифра --------------------------------------------------------------- */

.why-bento__num {
  position: relative;
  font-family: var(--rrs-font-heading);
  font-size: clamp(38px, 5vw, 58px);
  font-weight: 700;
  line-height: .92;
  letter-spacing: -.05em;
  font-variant-numeric: tabular-nums;
}

.why-bento__num--objects { --why-num: 350; }
.why-bento__num--visit { --why-num: 3; }
.why-bento__num--warranty { --why-num: 5; }
.why-bento__num--mount { --why-num: 60; }

.why-bento__unit {
  margin-left: .04em;
  color: var(--home-accent);
  font-size: .5em;
  vertical-align: .72em;
}

.why-bento__caption {
  margin-top: auto;
  padding-top: var(--rrs-space-2);
  color: var(--home-ink-muted);
  font-size: 13px;
  line-height: 1.35;
}

/* По умолчанию цифра — обычный текст разметки, счётчик выключен. */
.why-bento__count {
  display: none;
}

.why-bento__count::after {
  counter-reset: why-num var(--why-num);
  content: counter(why-num);
}

@keyframes why-count {
  from { --why-num: 0; }
}

/* Счётчик кладётся ПОВЕРХ настоящего текста: он держит ширину, а диктор
   читает конечную цифру. @supports обязателен — без поддержки @property
   настоящая цифра была бы прозрачной, а счётчик печатал бы ноль. */
@supports at-rule(@property) {
  html[data-reveal-engine="on"] .why-bento__count {
    position: absolute;
    top: 0;
    left: 0;
    display: inline-block;
  }

  html[data-reveal-engine="on"] .why-bento__plain {
    color: transparent;
  }
}

html[data-reveal-engine="on"] .why-bento__cell[data-revealed] .why-bento__count::after {
  animation: why-count 900ms var(--rrs-ease) both;
}

@media (min-width: 560px) {
  .why-bento {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .why-bento__cell--lead,
  .why-bento__cell--wide {
    grid-column: span 2;
  }
}

@media (min-width: 900px) {
  .why-bento {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }

  .why-bento__cell--lead {
    grid-column: span 2;
    grid-row: span 2;
    justify-content: center;
    padding: clamp(26px, 2.6vw, 34px);
  }
}

/* --------------------------------------------------------------------------
   8. Секция #process — этапы, кружки с цифрами
   Номера рисует счётчик, в разметке их нет. Прятать кружок разрешено только
   под html[data-reveal-engine="on"]: без JS и при reduce видны все шаги.
   Очередь на десктопе задаёт --process-gap; своего наблюдателя тут нет.
   -------------------------------------------------------------------------- */

.process {
  /* Диаметр кружка — единственный размер секции: от него считаются цифра
     и отступ под текст. */
  --process-node: 52px;
  /* Три темпа разведены намеренно: --process-gap — кружок, --process-step-gap
     — текст шага (жёсткий бюджет 600 мс), --process-glow-gap — вспышка.
     Общий шаг для всех трёх сливал вспышки и затягивал текст. */
  --process-gap: 0ms;
  --process-step-gap: 0ms;
  --process-glow-gap: 0ms;
  --process-ignite: 550ms;
  --process-glow-dur: 460ms;
}

.process__steps {
  display: grid;
  counter-reset: process;
}

.process__step {
  position: relative;
  padding-left: calc(var(--process-node) + 20px);
  padding-bottom: clamp(28px, 3.4vw, 40px);
  counter-increment: process;
}

.process__step:last-child {
  padding-bottom: 0;
}

/* Перебивает общую задержку раздела 5: группы у секции нет, шаги
   наблюдаются поштучно и очередь считается по порядку в списке. */
.process__step[data-reveal] {
  transition-delay: calc(var(--process-order, 0) * var(--process-step-gap));
}

.process__step:nth-child(2) { --process-order: 1; }
.process__step:nth-child(3) { --process-order: 2; }
.process__step:nth-child(4) { --process-order: 3; }
.process__step:nth-child(5) { --process-order: 4; }

/* Кружок анимируется только transform и opacity: раскладка не едет. */
.process__node {
  position: absolute;
  top: 0;
  left: 0;
  display: grid;
  place-items: center;
  width: var(--process-node);
  height: var(--process-node);
  border: 2px solid var(--home-accent);
  border-radius: 50%;
  background-color: color-mix(in srgb, var(--home-accent) 14%, transparent);
  color: var(--home-ink);
  font-family: var(--rrs-font-heading);
  font-size: calc(var(--process-node) * .4);
  font-weight: 600;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  transform: scale(1) translateY(0);
  opacity: 1;
  transition: transform var(--process-ignite) var(--rrs-ease),
              opacity var(--process-ignite) var(--rrs-ease),
              color var(--process-ignite) var(--rrs-ease),
              border-color var(--process-ignite) var(--rrs-ease),
              background-color var(--process-ignite) var(--rrs-ease);
  transition-delay: calc(var(--process-order, 0) * var(--process-gap));
}

.process__node::before {
  content: counter(process);
}

/* Кольцо вспышки: расходится один раз в момент зажигания и гаснет. */
.process__node::after {
  content: "";
  position: absolute;
  inset: -2px;
  border: 2px solid var(--home-accent);
  border-radius: 50%;
  opacity: 0;
  pointer-events: none;
}

/* Порядок функций важен: translateY идёт после scale, поэтому итоговый
   сдвиг — 18px × .55 ≈ 10px, а не 18px. */
html[data-reveal-engine="on"] .process__step:not([data-revealed]) .process__node {
  transform: scale(.55) translateY(18px);
  opacity: 0;
  border-color: var(--home-line-strong);
  background-color: transparent;
  color: var(--home-ink-dim);
}

html[data-reveal-engine="on"] .process__step[data-revealed] .process__node::after {
  animation: process-ignite var(--process-glow-dur) var(--rrs-ease) both;
  animation-delay: calc(var(--process-order, 0) * var(--process-glow-gap));
}

@keyframes process-ignite {
  from { opacity: .6; transform: scale(1); }
  to   { opacity: 0;  transform: scale(1.3); }
}

/* Отступом, а не min-height: при min-height в диаметр кружка абзац
   отъезжал под кружок и отрывался от заголовка. */
.process__name {
  padding-top: calc((var(--process-node) - 1.2em) / 2);
  color: var(--home-ink);
  font-size: 16px;
  font-weight: 600;
  letter-spacing: -.01em;
  line-height: 1.2;
}

.process__text {
  margin-top: 8px;
  max-width: 34ch;
  color: var(--home-ink-muted);
  font-size: 14px;
  line-height: 1.5;
}

/* Страховка на случай, когда reduce включили на уже открытой странице. */
@media (prefers-reduced-motion: reduce) {
  .process__node {
    transition: none;
  }

  html[data-reveal-engine="on"] .process__step[data-revealed] .process__node::after {
    animation: none;
  }
}

@media (min-width: 480px) {
  .process {
    --process-node: 60px;
  }
}

@media (min-width: 900px) {
  .process {
    --process-node: clamp(68px, 5.6vw, 84px);
    /* Декорация: 4 × 220 + 550 = 1430 мс, потолок ряда 1.5 с */
    --process-gap: 220ms;
    /* Текст: 4 × 45 + 400 = 580 мс, бюджет «не позже 600 мс» */
    --process-step-gap: 45ms;
    /* Вспышке нужен шаг шире, чем у кружка, иначе 3–5 сливаются с 1–2 */
    --process-glow-gap: 260ms;
    --process-glow-dur: 400ms;
  }

  .process__steps {
    grid-template-columns: repeat(5, minmax(0, 1fr));
    column-gap: var(--rrs-space-3);
  }

  .process__step {
    padding-top: calc(var(--process-node) + 22px);
    padding-bottom: 0;
    padding-left: 0;
  }

  .process__name {
    padding-top: 0;
    font-size: 17px;
  }
}

/* Subgrid выдаёт шагам общие строки: иначе длинное название в две строки
   сдвигает свой абзац вниз и ряд разъезжается. */
@supports (grid-template-rows: subgrid) {
  @media (min-width: 900px) {
    .process__steps {
      grid-template-rows: auto auto;
    }

    .process__step {
      display: grid;
      grid-row: span 2;
      grid-template-rows: subgrid;
      align-content: start;
      row-gap: 0;
    }
  }
}

/* --------------------------------------------------------------------------
   9. Секция #faq
   Без скрипта это обычные <details>. Со скриптом (data-faq-ready) они
   держатся открытыми, а высота едет grid-template-rows 0fr → 1fr: через
   display плавности не бывает. visibility убирает свёрнутый ответ из обхода.
   -------------------------------------------------------------------------- */

.faq {
  display: grid;
}

.faq__item {
  border-top: 1px solid var(--home-line);
  transition: border-color var(--rrs-dur) var(--rrs-ease);
}

.faq__item:last-child {
  border-bottom: 1px solid var(--home-line);
}

.faq__item[data-faq-open] {
  border-top-color: color-mix(in srgb, var(--home-accent) 60%, transparent);
}

.faq__q {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--rrs-space-2);
  padding-block: clamp(16px, 2vw, 20px);
  color: var(--home-ink);
  cursor: pointer;
  list-style: none;
  transition: color var(--rrs-dur) var(--rrs-ease);
}

/* Штатный треугольник убирается в обеих реализациях: свой знак у нас справа. */
.faq__q::-webkit-details-marker { display: none; }
.faq__q::marker { content: ""; }

.faq__q:focus-visible {
  outline: 2px solid var(--home-accent);
  outline-offset: -2px;
  border-radius: 6px;
}

.faq__q-text {
  max-width: 60ch;
  font-size: clamp(15px, 1.3vw, 17px);
  font-weight: 600;
  letter-spacing: -.01em;
  line-height: 1.35;
}

.faq__mark {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border: 1px solid var(--home-line);
  border-radius: var(--home-radius);
  color: var(--home-ink-dim);
  transition: border-color var(--rrs-dur) var(--rrs-ease),
              color var(--rrs-dur) var(--rrs-ease);
}

/* Доворачивается только знак, не рамка: иначе квадрат станет ромбом. */
.faq__mark svg,
.faq__mark::before,
.faq__mark::after {
  transition: transform 320ms var(--rrs-ease);
}

.faq__mark svg {
  grid-area: 1 / 1;
  width: 16px;
  height: 16px;
}

/* Запасной плюс на случай, когда lucide не приехал; при появлении
   настоящей иконки :has(svg) ниже его убирает. */
.faq__mark::before,
.faq__mark::after {
  content: "";
  grid-area: 1 / 1;
  background-color: currentColor;
}

.faq__mark::before {
  width: 12px;
  height: 1.5px;
}

.faq__mark::after {
  width: 1.5px;
  height: 12px;
}

.faq__mark:has(svg)::before,
.faq__mark:has(svg)::after {
  content: none;
}

/* Без скрипта состояние держит сам <details>: знак должен отвечать и на него. */
.faq:not([data-faq-ready]) .faq__item[open] .faq__mark {
  border-color: var(--home-accent);
  color: var(--home-accent);
}

.faq:not([data-faq-ready]) .faq__item[open] .faq__mark svg,
.faq:not([data-faq-ready]) .faq__item[open] .faq__mark::before,
.faq:not([data-faq-ready]) .faq__item[open] .faq__mark::after {
  transform: rotate(45deg);
}

.faq__item[data-faq-open] .faq__mark {
  border-color: var(--home-accent);
  color: var(--home-accent);
}

.faq__item[data-faq-open] .faq__mark svg,
.faq__item[data-faq-open] .faq__mark::before,
.faq__item[data-faq-open] .faq__mark::after {
  transform: rotate(45deg);
}

.faq__answer {
  display: grid;
  grid-template-rows: 1fr;
}

.faq__answer-inner {
  min-height: 0;
}

.faq__text {
  max-width: 66ch;
  padding-bottom: clamp(18px, 2vw, 24px);
  color: var(--home-ink-muted);
  font-size: var(--rrs-fs-body);
  line-height: 1.6;
}

.faq[data-faq-ready] .faq__answer {
  grid-template-rows: 0fr;
  transition: grid-template-rows 340ms var(--rrs-ease);
}

.faq[data-faq-ready] .faq__answer-inner {
  overflow: hidden;
  visibility: hidden;
  /* visibility ждёт конца анимации: иначе текст исчезает раньше створки */
  transition: visibility 0s linear 340ms;
}

.faq[data-faq-ready] .faq__item[data-faq-open] .faq__answer {
  grid-template-rows: 1fr;
}

.faq[data-faq-ready] .faq__item[data-faq-open] .faq__answer-inner {
  visibility: visible;
  transition-delay: 0s;
}

@media (hover: hover) and (pointer: fine) {
  .faq__q:hover .faq__mark {
    border-color: var(--home-line-strong);
    color: var(--home-ink);
  }

  .faq__item[data-faq-open] .faq__q:hover .faq__mark {
    border-color: var(--home-accent);
    color: var(--home-accent);
  }
}

@media (prefers-reduced-motion: reduce) {
  .faq[data-faq-ready] .faq__answer-inner {
    transition-delay: 0s;
  }
}

/* --------------------------------------------------------------------------
   10. Секция #works — горизонтальная лента работ
   Обычная прокрутка на всех разрешениях: своей прокруткой страницы лента
   не управляет и её не перехватывает (ни wheel, ни touchmove, ни sticky-
   залипание). Навигация — свайп/прокрутка ленты или стрелки data-works-prev/-next.
   -------------------------------------------------------------------------- */

.works {
  --works-gap: clamp(10px, 1.2vw, 18px);
  --works-progress: 0;

  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(16px, 2.2vw, 24px);
}

.works__frame {
  position: relative;
  min-width: 0;
}

/* Отрицательный margin уводит ленту к краю экрана, padding возвращает
   отступ первой и последней карточке. Свой скролл-индикатор — .works__rail
   под лентой, родной скроллбар браузера скрыт, чтобы не дублировать его. */
.works__viewport {
  margin-inline: calc(var(--rrs-container-pad) * -1);
  padding-inline: var(--rrs-container-pad);
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
}

.works__viewport::-webkit-scrollbar {
  display: none;
}

.works__viewport:focus-visible {
  outline: 2px solid var(--home-accent);
  outline-offset: 2px;
}

.works__strip {
  display: flex;
  gap: var(--works-gap);
  margin: 0;
  padding: 0;
  list-style: none;
}

.works__item {
  flex: 0 0 auto;
  width: min(76vw, 340px);
  scroll-snap-align: center;
}

.works__card {
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  gap: 10px;
  height: 100%;
  margin: 0;
}

.works__img {
  overflow: hidden;
  aspect-ratio: 4 / 3;
  border: 1px solid var(--home-line);
  border-radius: var(--home-radius);
  background-color: var(--home-surface);
  transition: border-color var(--rrs-dur) var(--rrs-ease);
}

.works__img img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--rrs-dur-slow) var(--rrs-ease);
}

.works__caption {
  display: flex;
  align-items: baseline;
  min-height: 18px;
}

.works__label {
  color: var(--home-ink);
  font-size: var(--rrs-fs-small);
  font-weight: 600;
  line-height: 1.4;
}

/* --- стрелки навигации ------------------------------------------------- */

.works__arrow {
  position: absolute;
  top: 50%;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid var(--home-line-strong);
  border-radius: calc(var(--home-radius) - 6px);
  background-color: var(--home-surface);
  color: var(--home-ink);
  cursor: pointer;
  transform: translateY(-50%);
  transition: border-color var(--rrs-dur) var(--rrs-ease),
              background-color var(--rrs-dur) var(--rrs-ease),
              color var(--rrs-dur) var(--rrs-ease),
              opacity var(--rrs-dur) var(--rrs-ease);
}

.works__arrow--prev {
  left: 8px;
}

.works__arrow--next {
  right: 8px;
}

.works__arrow:disabled {
  border-color: var(--home-line);
  color: var(--home-ink-dim);
  opacity: .5;
  cursor: default;
}

.works__arrow:focus-visible {
  outline: 2px solid var(--home-accent);
  outline-offset: 2px;
}

.works__arrow-icon {
  display: flex;
}

.works__arrow-icon svg {
  width: 17px;
  height: 17px;
}

/* --- хвост ленты: выход на портфолио -------------------------------------- */

.works__end {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 10px;
  height: 100%;
  padding: clamp(20px, 3vw, 32px);
  border: 1px solid var(--home-line-strong);
  border-radius: var(--home-radius);
  background-color: var(--home-surface);
}

.works__end-title {
  font-size: clamp(19px, 2vw, 24px);
  line-height: 1.1;
  letter-spacing: -.02em;
  text-wrap: balance;
}

.works__end-text {
  max-width: 32ch;
  color: var(--home-ink-muted);
  font-size: var(--rrs-fs-small);
  line-height: 1.5;
}

.works__end-link {
  margin-top: var(--rrs-space-2);
  align-self: start;
}

/* --- строка положения ----------------------------------------------------- */

.works__bar {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: clamp(12px, 1.6vw, 20px);
}

.works__count {
  display: flex;
  align-items: baseline;
  gap: 5px;
  color: var(--home-ink-dim);
  font-family: var(--rrs-font-heading);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
}

.works__count-now {
  color: var(--home-ink);
}

.works__rail {
  position: relative;
  overflow: hidden;
  height: 2px;
  border-radius: 2px;
  background-color: var(--home-line);
}

.works__rail-fill {
  position: absolute;
  inset: 0;
  transform: scaleX(var(--works-progress, 0));
  transform-origin: left center;
  background-color: var(--home-accent);
  will-change: transform;
}

.works__hint {
  grid-column: 1 / -1;
  color: var(--home-ink-dim);
  font-size: var(--rrs-fs-small);
}

@media (hover: hover) and (pointer: fine) {
  .works__arrow:not(:disabled):hover {
    border-color: var(--home-accent);
    color: var(--home-accent);
  }

  .works__card:hover .works__img {
    border-color: var(--home-line-strong);
  }

  .works__card:hover .works__img img {
    transform: scale(1.04);
  }
}

@media (min-width: 560px) {
  .works__item { width: min(56vw, 380px); }
}

@media (min-width: 900px) {
  .works__bar {
    grid-template-columns: auto minmax(0, 1fr) auto;
  }

  .works__hint {
    grid-column: auto;
  }
}

/* --------------------------------------------------------------------------
   11. Секция #calc — подбор параметров изделия
   Цен в секции нет: сумму называет менеджер после замера.
   Каркас в разметке пустой — переключатели, списки и строки подбора собирает
   js/home.js из таблицы направлений; до этого виден .calc__fallback,
   переключает их флаг data-calc-ready на корне секции.
   -------------------------------------------------------------------------- */

.calc__fallback {
  display: grid;
  justify-items: start;
  gap: var(--rrs-space-3);
  max-width: 62ch;
}

.calc__fallback-text {
  color: var(--home-ink-muted);
  font-size: var(--rrs-fs-body-lg);
  line-height: 1.55;
}

.calc__live {
  display: none;
}

.calc[data-calc-ready] .calc__fallback {
  display: none;
}

.calc[data-calc-ready] .calc__live {
  display: grid;
  gap: var(--home-gap);
  align-items: stretch;
}

.calc__form {
  display: grid;
  /* minmax(0, 1fr), а не авто-колонка: у <select> с длинными вариантами
     своя минимальная ширина больше экрана, и авто-колонка её вмещает —
     страница едет вбок. Нулевой минимум это запрещает. */
  grid-template-columns: minmax(0, 1fr);
  gap: var(--home-gap);
  min-width: 0;
}

.calc__params {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--home-gap);
  min-width: 0;
}

/* Правило явное, иначе padding и рамка .calc-field спорят с [hidden]. */
.calc-field[hidden] {
  display: none;
}

.calc-facts {
  display: grid;
  gap: 10px;
  padding: clamp(16px, 2vw, 22px);
  border: 1px solid var(--home-line);
  border-radius: var(--home-radius);
  background-color: var(--home-surface);
}

.calc-facts__item {
  display: flex;
  gap: 12px;
  color: var(--home-ink-muted);
  font-size: var(--rrs-fs-small);
  line-height: 1.5;
}

.calc-facts__item::before {
  content: "";
  flex: 0 0 auto;
  width: 14px;
  height: 1px;
  margin-top: .7em;
  background-color: var(--home-accent);
}

/* --- поле ---------------------------------------------------------------- */

/* Блок, а не grid: <legend> в grid-контейнере ведёт себя по-разному
   от браузера к браузеру, вплоть до потери рамки. */
.calc-field {
  min-width: 0;
  padding: clamp(16px, 2vw, 22px);
  border: 1px solid var(--home-line);
  border-radius: var(--home-radius);
  background-color: var(--home-surface);
}

.calc-field > * + * {
  margin-top: 12px;
}

.calc-field__legend {
  float: left;
  width: 100%;
  margin-bottom: 12px;
  padding: 0;
  color: var(--home-ink-dim);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: var(--rrs-ls-label);
  text-transform: uppercase;
}

/* float у legend оставляет за собой поток — снимаем его следующим блоком */
.calc-field__legend + * {
  clear: both;
  margin-top: 0;
}

.calc-field__hint {
  color: var(--home-ink-dim);
  font-size: 13px;
  line-height: 1.45;
}

.calc-field__error {
  color: var(--home-danger);
  font-size: 13px;
  font-weight: 500;
  line-height: 1.45;
}

.calc-field__error[hidden] {
  display: none;
}

/* --- направление --------------------------------------------------------- */

.calc-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.calc-chip {
  position: relative;
  display: inline-flex;
  min-width: 0;
}

/* Радиокнопка остаётся настоящей: клавиатура, роль и группировка по name. */
.calc-chip__input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  opacity: 0;
  pointer-events: none;
}

.calc-chip__face {
  display: block;
  padding: 10px 16px;
  border: 1px solid var(--home-line-strong);
  border-radius: var(--rrs-radius-pill);
  color: var(--home-ink-muted);
  font-size: 14px;
  font-weight: 600;
  line-height: 1.2;
  cursor: pointer;
  transition: border-color var(--rrs-dur) var(--rrs-ease),
              background-color var(--rrs-dur) var(--rrs-ease),
              color var(--rrs-dur) var(--rrs-ease);
}

.calc-chip__input:checked + .calc-chip__face {
  border-color: var(--home-accent);
  background-color: var(--rrs-accent-soft);
  color: var(--home-ink);
}

.calc-chip__input:focus-visible + .calc-chip__face {
  outline: 2px solid var(--home-accent);
  outline-offset: 3px;
}

@media (hover: hover) and (pointer: fine) {
  .calc-chip__face:hover {
    border-color: var(--home-ink-muted);
    color: var(--home-ink);
  }

  .calc-chip__input:checked + .calc-chip__face:hover {
    border-color: var(--home-accent);
  }
}

/* --- списки и поля ввода -------------------------------------------------- */

.calc-select {
  position: relative;
  /* Обёртка не передаёт наверх собственную ширину <select>: min/max-width
     у самого элемента мобильным браузерам мало, обрезка обязательна. */
  min-width: 0;
  overflow: hidden;
}

.calc-select::after {
  content: "";
  position: absolute;
  top: 50%;
  right: 18px;
  width: 7px;
  height: 7px;
  border-right: 1.5px solid var(--home-ink-dim);
  border-bottom: 1.5px solid var(--home-ink-dim);
  transform: translateY(-70%) rotate(45deg);
  pointer-events: none;
}

.calc-select__control,
.calc-opening__input,
.calc-quiz__input {
  width: 100%;
  padding: 13px 14px;
  border: 1px solid var(--home-line-strong);
  border-radius: calc(var(--home-radius) - 2px);
  background-color: var(--home-bg);
  color: var(--home-ink);
  font-family: inherit;
  font-size: 15px;
  line-height: 1.25;
  transition: border-color var(--rrs-dur) var(--rrs-ease),
              background-color var(--rrs-dur) var(--rrs-ease);
}

.calc-select__control {
  appearance: none;
  padding-right: 40px;
  cursor: pointer;
  /* Ширину <select> задаёт самый длинный <option>; text-overflow режет
     только отрисовку, ширину держат min-width и max-width. Без них
     мобильные браузеры уводят всю страницу вбок. */
  min-width: 0;
  max-width: 100%;
  text-overflow: ellipsis;
}

/* Выпадающий список рисует ОС: без явных цветов он приезжает белым. */
.calc-select__control option,
.calc-select__control optgroup {
  background-color: var(--home-surface);
  color: var(--home-ink);
}

.calc-select__control:focus-visible,
.calc-opening__input:focus-visible,
.calc-quiz__input:focus-visible {
  outline: 2px solid var(--home-accent);
  outline-offset: 2px;
}

@media (hover: hover) and (pointer: fine) {
  .calc-select__control:hover,
  .calc-opening__input:hover,
  .calc-quiz__input:hover {
    border-color: var(--home-ink-muted);
  }
}

/* --- список проёмов ------------------------------------------------------- */

/* Разметка всех строк одинакова буква в букву: номер печатает счётчик,
   а различия единственной строки держит :only-child, не модификатор в HTML. */
.calc-openings {
  counter-reset: opening;
  list-style: none;
}

.calc-opening {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 8px 10px;
  align-items: center;
  counter-increment: opening;
}

.calc-opening + .calc-opening {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--home-line);
}

/* Номер печатает счётчик — числа в разметке нет. */
.calc-opening__num {
  grid-column: 1;
  grid-row: 1;
  color: var(--home-ink-dim);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: var(--rrs-ls-label);
  text-transform: uppercase;
}

.calc-opening__num::before {
  content: "Проём " counter(opening);
}

.calc-opening:only-child .calc-opening__num,
.calc-opening:only-child .calc-opening__remove {
  display: none;
}

.calc-opening__grid {
  display: grid;
  grid-column: 1 / -1;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}

.calc-opening__cell {
  display: grid;
  gap: 6px;
  min-width: 0;
}

.calc-opening__cell:last-child {
  grid-column: 1 / -1;
}

.calc-opening__label {
  color: var(--home-ink-dim);
  font-size: 12px;
  line-height: 1.2;
}

.calc-opening__input {
  font-variant-numeric: tabular-nums;
}

.calc-opening__input.is-invalid {
  border-color: var(--home-danger);
}

.calc-opening__error {
  grid-column: 1 / -1;
  color: var(--home-danger);
  font-size: 13px;
  font-weight: 500;
  line-height: 1.45;
}

.calc-opening__error[hidden] {
  display: none;
}

/* Цель нажатия 36×36 при знаке 12px: минимум доступности 24×24 взят
   с запасом — рядом поля ввода, и промах стоил бы удалённой строки. */
.calc-opening__remove {
  position: relative;
  grid-column: 2;
  grid-row: 1;
  justify-self: end;
  width: 36px;
  height: 36px;
  padding: 0;
  border: 1px solid var(--home-line-strong);
  border-radius: calc(var(--home-radius) - 4px);
  background-color: transparent;
  color: var(--home-ink-dim);
  cursor: pointer;
  transition: border-color var(--rrs-dur) var(--rrs-ease),
              color var(--rrs-dur) var(--rrs-ease),
              background-color var(--rrs-dur) var(--rrs-ease);
}

/* Крестик нарисован CSS: строки появляются после прохода lucide. */
.calc-opening__remove-sign,
.calc-opening__remove-sign::before {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 13px;
  height: 1.5px;
  background-color: currentColor;
}

.calc-opening__remove-sign {
  margin: -.75px 0 0 -6.5px;
  transform: rotate(45deg);
}

.calc-opening__remove-sign::before {
  content: "";
  margin: -.75px 0 0 -6.5px;
  transform: rotate(90deg);
}

.calc-opening__remove:focus-visible {
  outline: 2px solid var(--home-accent);
  outline-offset: 2px;
}

@media (hover: hover) and (pointer: fine) {
  .calc-opening__remove:hover {
    border-color: var(--home-danger);
    color: var(--home-danger);
  }
}

.calc-openings__add {
  display: inline-flex;
  gap: 8px;
  align-items: center;
  min-height: 40px;
  padding: 8px 16px;
  border: 1px dashed var(--home-line-strong);
  border-radius: var(--rrs-radius-pill);
  background-color: transparent;
  color: var(--home-ink-muted);
  font-family: inherit;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.2;
  cursor: pointer;
  transition: border-color var(--rrs-dur) var(--rrs-ease),
              color var(--rrs-dur) var(--rrs-ease),
              opacity var(--rrs-dur) var(--rrs-ease);
}

.calc-openings__add-sign {
  font-size: 17px;
  line-height: 1;
}

/* На пределе строк кнопка гаснет, но остаётся: доступное имя меняет home.js. */
.calc-openings__add:disabled {
  opacity: .45;
  cursor: not-allowed;
}

.calc-openings__add:focus-visible {
  outline: 2px solid var(--home-accent);
  outline-offset: 2px;
}

@media (hover: hover) and (pointer: fine) {
  .calc-openings__add:not(:disabled):hover {
    border-color: var(--home-accent);
    color: var(--home-ink);
  }
}

/* --- уточнения ------------------------------------------------------------ */

.calc-quiz {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 12px;
}

.calc-quiz__cell {
  display: grid;
  gap: 6px;
  /* Нулевой минимум по всей цепочке от .calc__form: иначе <select>
     с длинной подписью уводит страницу вбок на телефоне. */
  min-width: 0;
  align-content: start;
}

.calc-quiz__cell[hidden] {
  display: none;
}

.calc-quiz__label {
  color: var(--home-ink-dim);
  font-size: 12px;
  line-height: 1.25;
}

@media (min-width: 560px) {
  .calc-quiz {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 480px) {
  .calc-opening__grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .calc-opening__cell:last-child {
    grid-column: auto;
  }
}

/* --- панель подбора ------------------------------------------------------- */

/* Колонка, а не сетка: только во flex-потоке margin-top: auto у подвала
   забирает запас высоты и прижимает кнопку к низу. */
.calc-panel {
  display: flex;
  flex-direction: column;
  gap: var(--rrs-space-2);
  min-width: 0;
  padding: clamp(20px, 2.4vw, 28px);
  border: 1px solid var(--home-line-strong);
  border-radius: var(--home-radius);
  background-color: var(--home-surface-hi);
}

.calc-panel__state {
  display: flex;
  flex-direction: column;
  gap: var(--rrs-space-2);
}

@keyframes calc-state-in {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
}

/* Класс ставит и снимает js/home.js — только на смене направления. */
.calc-panel__state.is-entering {
  animation: calc-state-in 260ms var(--rrs-ease) both;
}

.calc-panel__label {
  color: var(--home-accent);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: var(--rrs-ls-label);
  text-transform: uppercase;
}

.calc-panel__caveat {
  max-width: 46ch;
  color: var(--home-ink-muted);
  font-size: 13px;
  line-height: 1.5;
}

.calc-panel__title {
  font-family: var(--rrs-font-heading);
  font-size: clamp(19px, 2.2vw, 25px);
  font-weight: 700;
  line-height: 1.14;
  letter-spacing: -.03em;
  text-wrap: balance;
}

/* Эти же строки уезжают в заявку — см. renderPicks в js/home.js. */
.calc-panel__rows {
  border-top: 1px solid var(--home-line);
}

.calc-panel__row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 0;
  border-bottom: 1px solid var(--home-line);
}

.calc-panel__row-head {
  display: grid;
  gap: 2px;
  min-width: 0;
}

.calc-panel__row-title {
  color: var(--home-ink-muted);
  font-size: 13px;
  line-height: 1.3;
}

/* Значение переносится по словам: здесь длинные названия направлений,
   и nowrap раздул бы панель шире экрана на 360px. */
.calc-panel__row-value {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 14px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  text-align: right;
  overflow-wrap: break-word;
}

/* margin-top: auto работает, если панель окажется в растянутой ячейке:
   кнопка тогда уходит к низу, как у карточек страницы. */
.calc-panel__foot {
  display: grid;
  gap: 10px;
  margin-top: auto;
}

.calc-panel__foot-note {
  color: var(--home-ink-dim);
  font-size: 12px;
  line-height: 1.4;
}

@media (min-width: 900px) {
  .calc[data-calc-ready] .calc__live {
    grid-template-columns: minmax(0, 1.1fr) minmax(0, .9fr);
  }

  /* Высота по содержимому, а не по колонке с полями: растянутая панель
     оставляла между оговоркой и кнопкой пустую четверть экрана. */
  .calc-panel {
    align-self: start;
  }
}

/* --- сводка подбора в модалке заявки -------------------------------------- */

/* Живёт внутри общей модалки, но принадлежит секции подбора. */
.calc-summary {
  display: grid;
  gap: 8px;
  padding: 14px 16px;
  border: 1px solid var(--home-line);
  border-radius: calc(var(--home-radius) - 2px);
  background-color: var(--home-bg);
}

.calc-summary[hidden] {
  display: none;
}

.calc-summary__title {
  color: var(--home-ink-dim);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: var(--rrs-ls-label);
  text-transform: uppercase;
}

.calc-summary__list {
  display: grid;
  gap: 6px;
}

.calc-summary__row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}

.calc-summary__key {
  color: var(--home-ink-dim);
  font-size: 12px;
}

.calc-summary__value {
  color: var(--home-ink);
  font-size: 13px;
  font-weight: 600;
  text-align: right;
}

/* --------------------------------------------------------------------------
   12. Секция #reviews
   Настоящих отзывов нет: .review-card--slot — место под будущий текст
   с той же анатомией, что у заполненной карточки.
   Лента на Swiper (инициализирует js/home.js). Базовые правила описывают
   обычную горизонтальную прокрутку; в слайдер её переводит только
   .reviews__slider--initialized, поэтому без CDN и без JS всё листается.
   -------------------------------------------------------------------------- */

.reviews {
  display: grid;
  /* minmax(0, 1fr), а не auto: колонка с лентой иначе растягивается
     по max-content содержимого, и секция выезжает за край экрана. */
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(24px, 3vw, 36px);
}

/* Та же причина: обёртка ленты обязана уметь сжаться до нуля. */
.reviews__track {
  min-width: 0;
}

/* --- левая колонка: то, что можно проверить -------------------------------- */

.reviews__proof {
  display: grid;
  gap: var(--rrs-space-3);
  align-content: start;
}

.reviews__count {
  display: grid;
  gap: 6px;
}

.reviews__count-value {
  color: var(--home-accent);
  font-family: var(--rrs-font-heading);
  font-size: clamp(22px, 2.6vw, 28px);
  line-height: 1.1;
  letter-spacing: -.02em;
}

.reviews__count-label {
  max-width: 24ch;
  color: var(--home-ink-muted);
  font-size: var(--rrs-fs-small);
  line-height: 1.45;
}

/* --- лента ---------------------------------------------------------------- */

.reviews__slider {
  position: relative;
  /* Отрицательный margin уводит ленту к краю экрана, padding возвращает
     отступ первой карточке; Swiper вычитает его из своей ширины сам. */
  margin-inline: calc(var(--rrs-container-pad) * -1);
  padding-inline: var(--rrs-container-pad);
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-x: contain;
  scrollbar-width: thin;
  scrollbar-color: var(--home-line-strong) transparent;
}

/* Нужен только в резервном состоянии: подняв слайдер, скрипт снимает tabindex. */
.reviews__slider:focus-visible {
  outline: 2px solid var(--home-accent);
  outline-offset: 2px;
}

.reviews__strip {
  display: flex;
  gap: var(--home-gap);
  align-items: stretch;
  padding-block: 2px;
}

.reviews__item {
  display: flex;
  flex: 0 0 auto;
  width: min(78vw, 320px);
}

/* --- то же самое, когда Swiper поднялся ------------------------------------ */

/* Нативная прокрутка уходит: позицию ведёт transform, два механизма
   на одном контейнере дали бы двойной сдвиг. */
.reviews__slider--initialized {
  overflow: hidden;
  /* Swiper ставит курсор не всегда — держим в стилях */
  cursor: grab;
}

.reviews__slider--initialized:active {
  cursor: grabbing;
}

/* Вертикальную прокрутку страницы жест по ленте забирать не должен. */
.reviews__slider--horizontal {
  touch-action: pan-y;
}

/* Зазор ведёт spaceBetween Swiper (js/home.js читает его отсюда):
   оставленный CSS-gap даёт расползание, растущее со слайдами. */
.reviews__slider--initialized .reviews__strip {
  gap: 0;
  transition-property: transform;
}

/* --- стрелки и пагинация --------------------------------------------------- */

/* До инициализации и на заблокированной (всё влезло) ленте управления нет. */
.reviews__controls {
  display: none;
  align-items: center;
  justify-content: space-between;
  gap: var(--rrs-space-3);
  margin-top: var(--rrs-space-3);
}

.reviews__track[data-reviews-ready] .reviews__controls {
  display: flex;
}

.reviews__track[data-reviews-lock] .reviews__controls {
  display: none;
}

.reviews__pages {
  display: flex;
  flex: 1 1 auto;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  min-width: 0;
}

.reviews__arrows {
  flex: 0 0 auto;
}

/* Высота 24px — минимум цели касания; видна только полоска в 4px.
   Активная растёт масштабом, а не шириной: ширина двигала бы соседей. */
.reviews__page {
  display: grid;
  align-items: center;
  width: 40px;
  height: 24px;
  padding: 0;
  border: 0;
  background-color: transparent;
  cursor: pointer;
}

.reviews__page-bar {
  height: 4px;
  background-color: var(--home-line-strong);
  transform: scaleX(.5);
  transform-origin: left center;
  transition: transform var(--rrs-dur) var(--rrs-ease),
              background-color var(--rrs-dur) var(--rrs-ease);
}

.reviews__page--active .reviews__page-bar {
  background-color: var(--home-accent);
  transform: scaleX(1);
}

.reviews__page:focus-visible {
  outline: 2px solid var(--home-accent);
  outline-offset: 2px;
}

.reviews__arrows {
  display: flex;
  gap: 8px;
}

@media (max-width: 399px) {
  .reviews__page {
    width: 26px;
  }
}

.reviews__arrow {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid var(--home-line-strong);
  border-radius: calc(var(--home-radius) - 6px);
  background-color: transparent;
  color: var(--home-ink);
  cursor: pointer;
  transition: border-color var(--rrs-dur) var(--rrs-ease),
              background-color var(--rrs-dur) var(--rrs-ease),
              color var(--rrs-dur) var(--rrs-ease),
              opacity var(--rrs-dur) var(--rrs-ease);
}

/* На краю кнопка гаснет; из мыши и табуляции её убирает настоящий disabled,
   который ставит Swiper — стрелки размечены тегом <button>. */
.reviews__arrow--off,
.reviews__arrow:disabled {
  border-color: var(--home-line);
  color: var(--home-ink-dim);
  opacity: .5;
  cursor: default;
}

.reviews__arrow:focus-visible {
  outline: 2px solid var(--home-accent);
  outline-offset: 2px;
}

.reviews__arrow-icon {
  display: flex;
}

.reviews__arrow-icon svg {
  width: 17px;
  height: 17px;
}

/* --- карточка отзыва ------------------------------------------------------- */

.review-card {
  display: flex;
  flex-direction: column;
  gap: 12px;
  width: 100%;
  padding: var(--home-card-pad);
  border: 1px solid var(--home-line);
  border-radius: var(--home-radius);
  background-color: var(--home-surface);
  transition: border-color var(--rrs-dur) var(--rrs-ease),
              background-color var(--rrs-dur) var(--rrs-ease);
}

.review-card__title {
  font-size: 17px;
  line-height: 1.2;
  letter-spacing: -.02em;
}

.review-card__text {
  color: var(--home-ink-muted);
  font-size: var(--rrs-fs-small);
  line-height: 1.55;
}

.review-card__head {
  display: grid;
  gap: 2px;
}

.review-card__name {
  font-weight: 600;
}

.review-card__meta,
.review-card__source {
  color: var(--home-ink-dim);
  font-size: 12px;
}

.review-card__source {
  margin-top: auto;
  padding-top: var(--rrs-space-1);
}

/* Место под будущий отзыв: пунктир не даёт принять слот за отзыв.
   Заполняется снятием модификатора. */
.review-card--slot {
  border-style: dashed;
  background-color: transparent;
}

.review-card--slot .review-card__name,
.review-card--slot .review-card__text {
  color: var(--home-ink-dim);
}

.review-card--slot .review-card__name {
  font-weight: 500;
}

/* Акцент только на контуре: в наборе на этой подложке он даёт 4.2:1
   при требуемых 4.5:1. */
.review-card--note {
  border-color: var(--rrs-accent-border);
  background-color: var(--home-surface-hi);
}

.review-card--cta {
  background-color: var(--home-surface-hi);
}

.review-card__foot {
  margin-top: auto;
  padding-top: var(--rrs-space-2);
}

.review-card__foot .btn {
  width: 100%;
}

@media (min-width: 560px) {
  .reviews__item {
    width: 320px;
  }
}

@media (min-width: 1100px) {
  .reviews {
    grid-template-columns: minmax(0, 300px) minmax(0, 1fr);
    align-items: start;
    gap: clamp(28px, 3vw, 48px);
  }

  .reviews__slider {
    margin-left: 0;
    padding-left: 0;
  }
}

@media (hover: hover) and (pointer: fine) {
  .review-card--slot:hover,
  .review-card--cta:hover {
    border-color: var(--home-line-strong);
  }

  .reviews__arrow:not(.reviews__arrow--off):hover {
    border-color: var(--home-accent);
    background-color: var(--home-surface-hi);
  }

  .reviews__page:not(.reviews__page--active):hover .reviews__page-bar {
    background-color: var(--home-ink-dim);
  }
}

/* --------------------------------------------------------------------------
   13. Секция #request — финальная заявка со свечением контуров
   Ячейки размечены data-glow-cell внутри data-glow-grid: кольцо-блик рисует
   css/styles.css (раздел 6), координаты приносит glow.js. Своей отрисовки
   свечения здесь нет.
   -------------------------------------------------------------------------- */

.request {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--home-gap);
}

/* position: relative обязателен — на нём стоит кольцо-блик (::after
   у data-glow-cell), иначе слой отсчитается от страницы. */
.request__cell {
  position: relative;
  padding: clamp(20px, 2.4vw, 32px);
  border: 1px solid var(--home-line);
  border-radius: var(--home-radius);
  background-color: var(--home-surface);
}

.request__panel {
  display: grid;
}

/* --- форма ---------------------------------------------------------------- */

.request-form {
  display: grid;
  gap: clamp(18px, 2vw, 26px);
}

.request-form__fields {
  display: grid;
  gap: var(--rrs-space-2);
}

.request-form__field {
  display: grid;
  gap: 6px;
  align-content: start;
}

.request-form__label {
  color: var(--home-ink-dim);
  font-size: var(--rrs-fs-label);
}

/* Те же токены, что у модалки: две формы страницы обязаны выглядеть одной. */
.request-form__input {
  width: 100%;
  padding: 13px 16px;
  border: 1px solid var(--rrs-modal-field-border);
  border-radius: var(--rrs-radius-pill);
  background-color: var(--rrs-modal-field-bg);
  color: var(--rrs-modal-field-ink);
  font-family: inherit;
  font-size: var(--rrs-fs-body);
  transition: border-color var(--rrs-dur) var(--rrs-ease),
              box-shadow var(--rrs-dur) var(--rrs-ease);
}

.request-form__input--area {
  min-height: 96px;
  border-radius: calc(var(--home-radius) + 6px);
  line-height: 1.45;
  resize: vertical;
}

.request-form__input::placeholder {
  color: var(--rrs-modal-placeholder);
}

.request-form__input:focus {
  outline: none;
  border-color: var(--home-accent);
  box-shadow: 0 0 0 3px var(--rrs-modal-focus-ring);
}

/* Ошибка держится и в фокусе; янтарь, а не красный — акцент сам красный. */
.request-form__field--invalid .request-form__input,
.request-form__field--invalid .request-form__input:focus {
  border-color: var(--home-danger);
  box-shadow: 0 0 0 3px var(--rrs-modal-danger-ring);
}

.request-form__error {
  display: none;
  color: var(--home-danger);
  font-size: var(--rrs-fs-label);
  font-weight: 600;
}

.request-form__field--invalid .request-form__error {
  display: block;
}

.request-form__foot {
  display: grid;
  gap: 12px;
  align-content: end;
  justify-items: start;
}

.request-form__note {
  color: var(--home-ink-dim);
  font-size: 12px;
  line-height: 1.45;
}

/* --- подтверждение отправки ------------------------------------------------ */

.request-form__success {
  display: grid;
  gap: 10px;
  justify-items: start;
  align-content: center;
}

.request-form__success[hidden] {
  display: none;
}

.request-form__success-icon {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: var(--rrs-radius-pill);
  background-color: var(--home-accent);
  color: var(--rrs-accent-ink);
}

/* Элемент — <p>: сквозной экран успеха в форме заявки не должен быть
   заголовком в контуре страницы, но вид h3 держит сам, без правила h3,h4. */
.request-form__success-title {
  font-family: var(--rrs-font-body);
  font-size: var(--rrs-fs-h3);
  font-weight: 700;
  line-height: var(--rrs-lh-h2);
  letter-spacing: -.01em;
}

.request-form__success-title:focus-visible {
  outline: 2px solid var(--home-accent);
  outline-offset: 4px;
}

.request-form__success-text {
  max-width: 42ch;
  color: var(--home-ink-muted);
  font-size: var(--rrs-fs-small);
  line-height: 1.55;
}

.request-form__success-text a {
  color: var(--home-ink);
  text-decoration: underline;
  text-underline-offset: 3px;
  transition: color var(--rrs-dur) var(--rrs-ease);
}

.request-form__success-text a:hover {
  color: var(--home-accent);
}

/* --- боковые ячейки -------------------------------------------------------- */

.request__side {
  display: grid;
  gap: var(--home-gap);
  align-content: start;
}

.request__aside {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.request__aside-title {
  color: var(--home-ink-dim);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: var(--rrs-ls-label);
  text-transform: uppercase;
}

.request__phone {
  color: var(--home-ink);
  font-family: var(--rrs-font-heading);
  font-size: clamp(20px, 2.2vw, 26px);
  letter-spacing: -.02em;
  transition: color var(--rrs-dur) var(--rrs-ease);
}

.request__phone:hover {
  color: var(--home-accent);
}

.request__aside-text {
  color: var(--home-ink-muted);
  font-size: var(--rrs-fs-small);
  line-height: 1.5;
}

/* Кнопка прижата к низу ячейки — правило карточек проекта. */
.request__aside-foot {
  margin-top: auto;
  padding-top: var(--rrs-space-2);
}

/* Нумерация — счётчиком: цифр в разметке нет. */
.request__steps {
  display: grid;
  gap: 10px;
  counter-reset: request-step;
}

.request__step {
  display: grid;
  grid-template-columns: 22px minmax(0, 1fr);
  gap: 10px;
  color: var(--home-ink-muted);
  font-size: var(--rrs-fs-small);
  line-height: 1.5;
}

.request__step::before {
  counter-increment: request-step;
  content: counter(request-step);
  color: var(--home-accent);
  font-family: var(--rrs-font-heading);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}

@media (min-width: 720px) {
  /* Запас высоты забирает поле комментария, а не дыра перед кнопкой. */
  .request-form {
    grid-template-rows: minmax(0, 1fr) auto;
  }

  .request-form__fields {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-template-rows: auto minmax(110px, 1fr);
  }

  .request-form__field--wide {
    grid-column: 1 / -1;
    grid-template-rows: auto minmax(0, 1fr);
  }

  .request-form__input--area {
    height: 100%;
  }

  .request-form__foot {
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    gap: var(--rrs-space-3);
  }

  .request-form__note {
    max-width: 44ch;
  }
}

@media (min-width: 1000px) {
  .request {
    grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
    align-items: stretch;
  }
}

/* Правило явное: своё display: grid иначе перебивает [hidden]. */
.request-form[hidden] {
  display: none;
}

/* --------------------------------------------------------------------------
   14. Футер #contacts
   Карта — ссылка, а не встроенный виджет: чужой скрипт стоит секунд загрузки.
   Заглушки будущих страниц (.footer__link--soon) размечены <span>, а не
   ссылкой без href: ссылка без адреса не должна притворяться кнопкой.
   -------------------------------------------------------------------------- */

.footer {
  display: grid;
  gap: clamp(24px, 3vw, 40px);
}

.footer__col {
  display: grid;
  gap: 14px;
  align-content: start;
  min-width: 0;
}

.footer__col-title {
  color: var(--home-ink-dim);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: var(--rrs-ls-label);
  text-transform: uppercase;
}

.footer__address {
  display: grid;
  gap: 8px;
  font-style: normal;
}

.footer__phone {
  color: var(--home-ink);
  font-family: var(--rrs-font-heading);
  font-size: clamp(21px, 2.3vw, 27px);
  letter-spacing: -.02em;
  transition: color var(--rrs-dur) var(--rrs-ease);
}

.footer__phone:hover {
  color: var(--home-accent);
}

.footer__mail {
  color: var(--home-ink-muted);
  font-size: var(--rrs-fs-small);
  transition: color var(--rrs-dur) var(--rrs-ease);
}

.footer__mail:hover {
  color: var(--home-ink);
}

/* --- строка адреса --------------------------------------------------------- */

.footer__line {
  display: grid;
  grid-template-columns: 18px minmax(0, 1fr);
  gap: 10px;
  color: var(--home-ink-muted);
  font-size: var(--rrs-fs-small);
  line-height: 1.5;
}

.footer__line-icon {
  display: grid;
  place-items: center;
  height: 1.5em;
  color: var(--home-ink-dim);
}

.footer__line-icon svg {
  width: 15px;
  height: 15px;
}

/* --- мессенджеры ----------------------------------------------------------- */

.footer__messengers {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.footer__messenger {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 7px 14px 7px 8px;
  border: 1px solid var(--home-line);
  border-radius: var(--rrs-radius-pill);
  color: var(--home-ink-muted);
  font-size: 13px;
  font-weight: 600;
  transition: border-color var(--rrs-dur) var(--rrs-ease),
              color var(--rrs-dur) var(--rrs-ease),
              background-color var(--rrs-dur) var(--rrs-ease);
}

.footer__messenger-icon {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: var(--rrs-radius-pill);
  background-color: var(--rrs-modal-wash);
  color: var(--home-accent);
  transition: background-color var(--rrs-dur) var(--rrs-ease),
              color var(--rrs-dur) var(--rrs-ease);
}

.footer__messenger-icon svg {
  width: 14px;
  height: 14px;
}

.footer__messenger:hover {
  border-color: var(--home-line-strong);
  color: var(--home-ink);
  background-color: var(--home-surface);
}

.footer__messenger:hover .footer__messenger-icon {
  background-color: var(--home-accent);
  color: var(--rrs-accent-ink);
}

/* --- карта ----------------------------------------------------------------- */

.footer__map {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  border: 1px solid var(--home-line);
  border-radius: var(--home-radius);
  background-color: var(--home-surface);
  color: var(--home-ink);
  transition: border-color var(--rrs-dur) var(--rrs-ease),
              background-color var(--rrs-dur) var(--rrs-ease),
              transform var(--rrs-dur) var(--rrs-ease);
}

.footer__map-icon {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 34px;
  height: 34px;
  border-radius: var(--rrs-radius-pill);
  background-color: var(--rrs-modal-wash);
  color: var(--home-accent);
  transition: background-color var(--rrs-dur) var(--rrs-ease);
}

.footer__map-icon svg {
  width: 17px;
  height: 17px;
}

.footer__map-text {
  display: grid;
  gap: 2px;
}

.footer__map-title {
  font-size: var(--rrs-fs-small);
  font-weight: 600;
}

.footer__map-note {
  color: var(--home-ink-dim);
  font-size: 12px;
}

.footer__map:hover {
  border-color: var(--home-line-strong);
  background-color: var(--home-surface-hi);
}

/* --- списки ссылок --------------------------------------------------------- */

.footer__links {
  display: grid;
  gap: 8px;
}

.footer__link {
  display: inline-block;
  color: var(--home-ink-muted);
  font-size: var(--rrs-fs-small);
  transition: color var(--rrs-dur) var(--rrs-ease),
              transform var(--rrs-dur) var(--rrs-ease);
}

a.footer__link:hover {
  color: var(--home-ink);
  transform: translateX(2px);
}

/* Страницы ещё нет: приглушённый текст с точкой-меткой вместо ссылки. */
.footer__link--soon {
  color: var(--home-ink-dim);
  cursor: default;
}

.footer__link--soon::after {
  content: "";
  display: inline-block;
  width: 4px;
  height: 4px;
  margin-left: 8px;
  border-radius: var(--rrs-radius-pill);
  background-color: var(--home-line-strong);
  vertical-align: middle;
}

/* --- нижняя строка ---------------------------------------------------------- */

.footer__bottom {
  display: grid;
  gap: 10px;
  margin-top: clamp(28px, 4vw, 44px);
  padding-top: var(--rrs-space-3);
  border-top: 1px solid var(--home-line);
}

.footer__copy {
  color: var(--home-ink-dim);
  font-size: 12px;
  line-height: 1.5;
}

.footer__legal {
  color: var(--home-ink-dim);
  font-size: 14px;
  line-height: 1.5;
}

@media (min-width: 620px) {
  .footer {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .footer__bottom {
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: var(--rrs-space-3);
  }
}

@media (min-width: 1000px) {
  .footer {
    grid-template-columns: minmax(0, 1.2fr) minmax(0, 1.2fr) minmax(0, .8fr) minmax(0, .8fr);
    gap: clamp(24px, 3vw, 48px);
  }
}

@media (hover: hover) and (pointer: fine) {
  .footer__map:hover {
    transform: translateY(-2px);
  }
}

/* --------------------------------------------------------------------------
   15. Страница «Рольставни» — intro направления, карточки .home-card,
       заглушка акций.
   -------------------------------------------------------------------------- */

.home-card__title {
  font-family: var(--rrs-font-heading);
  font-size: clamp(17px, 1.8vw, 21px);
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -.02em;
  text-wrap: balance;
}

.home-card__text {
  color: var(--home-ink-muted);
  font-size: var(--rrs-fs-small);
  line-height: 1.55;
}

/* Пунктир отличает карточку «раздел готовится» от карточек с фактами. */
.home-card--placeholder {
  border-style: dashed;
}

.home-card--placeholder .home-card__text {
  color: var(--home-ink-dim);
}

/* --- intro направления ------------------------------------------------ */

/* Верхний отступ — как у первого экрана главной (24px, .hero-bento);
   низ секции живёт по общему ритму --tight. */
.product-intro {
  padding-top: 24px;
}

/* Фон и рамка — у двух ОТДЕЛЬНЫХ .home-card внутри (__body и __media),
   а не у layout: это соседние карточки, а не картинка в чужой рамке. */
.product-intro__layout {
  display: grid;
  gap: var(--home-gap);
}

/* Своё значение вместо --home-card-pad — только у этой карточки. */
.product-intro__media {
  padding: 16px;
}

.product-intro__caption {
  padding-top: var(--rrs-space-1);
  color: var(--home-ink-dim);
  font-size: var(--rrs-fs-small);
  line-height: 1.4;
}

.product-intro__title {
  max-width: 18ch;
  margin-top: var(--rrs-space-1);
  font-family: var(--rrs-font-heading);
  font-size: clamp(21px, 3vw, 33px);
  line-height: 1.05;
  letter-spacing: -.03em;
  text-wrap: balance;
}

.product-intro__lead {
  max-width: 54ch;
  margin-top: var(--rrs-space-2);
  color: var(--home-ink-muted);
  font-size: var(--rrs-fs-body-lg);
  line-height: 1.5;
}

.product-intro__facts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--rrs-space-1);
  margin-top: var(--rrs-space-3);
}

.product-intro__fact {
  padding: 8px 14px;
  border: 1px solid var(--home-line);
  border-radius: var(--rrs-radius-pill);
  color: var(--home-ink-muted);
  font-size: var(--rrs-fs-small);
}

.product-intro__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--rrs-space-2);
  /* Сверху 24px + 8px flex-gap родителя = 32px, снизу те же 32px
     без добавки гапа: padding в него не входит. */
  margin-top: var(--rrs-space-3);
  padding-top: var(--rrs-space-4);
  border-top: 1px solid var(--home-line);
}

/* Кнопки и факты на всю ширину узкого экрана; порог 559px тот же,
   что у .hero-bento__actions на главной. */
@media (max-width: 559px) {
  .product-intro__actions .btn {
    flex: 1 1 100%;
    justify-content: center;
  }

  .product-intro__fact {
    flex: 1 1 100%;
  }
}

.product-intro__img {
  overflow: hidden;
  border-radius: var(--home-radius);
  background-color: var(--home-surface-hi);
  aspect-ratio: 2 / 1;
}

.product-intro__img img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Заглушка фото направления: собственного кадра ещё нет.
   border задан явно — без ширины пунктир взял бы браузерный default
   (~3px) вместо 1px, как у остальных рамок. */
.product-intro__img--empty {
  position: relative;
  border: 1px dashed var(--home-line-strong);
  background-color: var(--home-bg-tint);
}

@media (min-width: 900px) {
  .product-intro__layout {
    grid-template-columns: minmax(0, 1.3fr) minmax(0, .7fr);
    /* stretch, не center: обе карточки одной высоты */
    align-items: stretch;
    gap: var(--home-gap);
  }

  .product-intro__media {
    justify-content: center;
  }

  .product-intro__img {
    aspect-ratio: 4 / 5;
  }
}

/* --- заглушка «Акции и скидки» ----------------------------------------- */

/* Подтверждённой акции на это направление нет: вместо цифры — призыв
   уточнить. Состояние помечено data-todo="promo-rolstavni" в разметке. */
.promo-note {
  display: flex;
  flex-direction: column;
  align-items: start;
  gap: var(--rrs-space-3);
  max-width: 62ch;
  padding: var(--home-card-pad);
  border: 1px dashed var(--home-line-strong);
  border-radius: var(--home-radius);
  background-color: var(--home-surface);
}

.promo-note__text {
  color: var(--home-ink-muted);
  font-size: var(--rrs-fs-body);
  line-height: 1.55;
}

/* --------------------------------------------------------------------------
   16. Страница «Примеры работ» (raboty.html) — сетка снимков и правки
       просмотрщика GLightbox.
   Ни одного места, где ширина содержимого может превысить колонку:
   minmax(0, 1fr) у сеток, max-width: 100% у картинок, обрезка локально
   на обёртке снимка. Щита overflow-x на body/html нет и быть не должно.
   -------------------------------------------------------------------------- */

/* --- сетка снимков ------------------------------------------------------ */

/* minmax(0, 1fr) вместо 1fr — защита от переполнения: авто-колонка
   растёт по внутренней ширине содержимого. */
.gallery-grid {
  display: grid;
  gap: var(--home-gap);
  grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 560px) {
  .gallery-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 900px) {
  .gallery-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.gallery-shot {
  min-width: 0;
}

.gallery-shot__link {
  position: relative;
  display: block;
  min-width: 0;
  border-radius: var(--home-radius);
  /* Обрезка строго локальная: на карточке снимка, не на секции и не на body */
  overflow: hidden;
  transition: transform var(--rrs-dur) var(--rrs-ease);
}

.gallery-shot__img {
  overflow: hidden;
  max-width: 100%;
  border: 1px solid var(--home-line);
  border-radius: var(--home-radius);
  background-color: var(--home-surface-hi);
  aspect-ratio: 4 / 3;
  transition: border-color var(--rrs-dur) var(--rrs-ease);
}

.gallery-shot__img img {
  display: block;
  width: 100%;
  max-width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--rrs-dur-slow) var(--rrs-ease);
}

/* Значок декоративный (aria-hidden): имя ссылки даёт alt снимка. */
.gallery-shot__zoom {
  position: absolute;
  right: 10px;
  bottom: 10px;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: var(--rrs-radius-pill);
  background-color: color-mix(in srgb, var(--home-bg) 72%, transparent);
  color: var(--home-ink);
  transition: background-color var(--rrs-dur) var(--rrs-ease);
}

.gallery-shot__zoom svg {
  width: 16px;
  height: 16px;
}

@media (hover: hover) and (pointer: fine) {
  .gallery-shot__link:hover .gallery-shot__img {
    border-color: var(--home-line-strong);
  }

  .gallery-shot__link:hover .gallery-shot__img img {
    transform: scale(1.04);
  }

  .gallery-shot__link:hover .gallery-shot__zoom {
    background-color: var(--home-accent);
    color: var(--rrs-accent-ink);
  }
}

/* --- просмотрщик GLightbox --------------------------------------------- */

/* Только подложка и видимый фокус: стили GLightbox подключены в <head>
   ДО этого файла, поэтому правки перебивают библиотеку без !important. */
.goverlay {
  background-color: color-mix(in srgb, var(--home-bg) 94%, #000);
}

.gbtn:focus-visible,
.gclose:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 3px;
}

/* --------------------------------------------------------------------------
   17. Страница «О компании» (o-kompanii.html) — слайдер сканов сертификатов.
   Свой блок, а не .gallery-*: там альбомные кадры 4/3, здесь портретные
   сканы 2/3, и подпись обязательна — она под кадром, а не в оверлее.
   Слайдер, а не статичная сетка: .cert-slider__track — Swiper wrapperClass,
   .cert-card — одновременно и карточка, и slideClass (без лишней обёртки).
   -------------------------------------------------------------------------- */

.cert-slider {
  display: flex;
  flex-direction: column;
  gap: var(--rrs-space-3);
}

/* Базовое состояние — обычная горизонтальная прокрутка: без CDN и без JS
   лента всё равно листается. Swiper переводит на transform только после
   инициализации, добавляя cert-slider__viewport--initialized сам
   (containerModifierClass в скрипте) — тот же приём, что у .reviews__slider. */
.cert-slider__viewport {
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-x: contain;
  scrollbar-width: thin;
  scrollbar-color: var(--home-line-strong) transparent;
}

.cert-slider__viewport:focus-visible {
  outline: 2px solid var(--home-accent);
  outline-offset: 2px;
}

.cert-slider__viewport--initialized {
  overflow: hidden;
  cursor: grab;
}

.cert-slider__viewport--initialized:active {
  cursor: grabbing;
}

.cert-slider__track {
  display: flex;
  align-items: flex-start;
  gap: var(--home-gap);
}

/* Зазор после инициализации ведёт spaceBetween Swiper, не CSS-gap —
   иначе расхождение растёт со слайдами (тот же приём у .reviews__strip). */
.cert-slider__viewport--initialized .cert-slider__track {
  gap: 0;
}

/* До готовности управление не показываем — кнопки и точки ничего не делают,
   пока Swiper не поднялся (тот же приём, что .reviews__controls). */
.cert-slider__controls {
  display: none;
}

[data-cert-slider][data-cert-ready] .cert-slider__controls {
  display: flex;
}

.cert-card {
  display: flex;
  flex-direction: column;
  flex: 0 0 auto;
  gap: var(--rrs-space-2);
  width: calc(100% - 32px);
  min-width: 0;
}

@media (min-width: 560px) {
  .cert-card { width: calc(50% - var(--home-gap) / 2 - 16px); }
}

@media (min-width: 900px) {
  .cert-card { width: calc(33.333% - var(--home-gap) * 2 / 3); }
}

@media (min-width: 1180px) {
  .cert-card { width: calc(25% - var(--home-gap) * 3 / 4); }
}

.cert-slider__controls {
  align-items: center;
  justify-content: center;
  gap: var(--rrs-space-2);
}

.cert-slider__arrow {
  display: grid;
  flex: none;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid var(--home-line-strong);
  border-radius: calc(var(--home-radius) - 6px);
  background-color: transparent;
  color: var(--home-ink);
  cursor: pointer;
  transition: border-color var(--rrs-dur) var(--rrs-ease),
              background-color var(--rrs-dur) var(--rrs-ease),
              color var(--rrs-dur) var(--rrs-ease),
              opacity var(--rrs-dur) var(--rrs-ease);
}

.cert-slider__arrow--off,
.cert-slider__arrow:disabled {
  border-color: var(--home-line);
  color: var(--home-ink-dim);
  opacity: .5;
  cursor: default;
}

.cert-slider__arrow:focus-visible {
  outline: 2px solid var(--home-accent);
  outline-offset: 2px;
}

.cert-slider__arrow-icon {
  display: flex;
}

.cert-slider__arrow-icon svg {
  width: 17px;
  height: 17px;
}

@media (hover: hover) and (pointer: fine) {
  .cert-slider__arrow:not(.cert-slider__arrow--off):not(:disabled):hover {
    border-color: var(--home-accent);
    color: var(--home-accent);
  }
}

.cert-slider__pagination {
  display: flex;
  gap: 8px;
}

.cert-slider__page {
  display: grid;
  align-items: center;
  width: 32px;
  height: 24px;
  padding: 0;
  border: 0;
  background-color: transparent;
  cursor: pointer;
}

.cert-slider__page-bar {
  height: 4px;
  background-color: var(--home-line-strong);
  transform: scaleX(.5);
  transform-origin: left center;
  transition: transform var(--rrs-dur) var(--rrs-ease),
              background-color var(--rrs-dur) var(--rrs-ease);
}

.cert-slider__page--active .cert-slider__page-bar {
  background-color: var(--home-accent);
  transform: scaleX(1);
}

.cert-slider__page:focus-visible {
  outline: 2px solid var(--home-accent);
  outline-offset: 2px;
}

.cert-card {
  display: flex;
  flex-direction: column;
  gap: var(--rrs-space-2);
  min-width: 0;
}

.cert-card__link {
  position: relative;
  display: block;
  min-width: 0;
  padding: 15px;
  border: 1px solid var(--home-line);
  border-radius: var(--home-radius);
  overflow: hidden;
  transition: border-color var(--rrs-dur) var(--rrs-ease),
              transform var(--rrs-dur) var(--rrs-ease);
}

.cert-card__img {
  overflow: hidden;
  max-width: 100%;
  border-radius: calc(var(--home-radius) - 4px);
  background-color: var(--home-surface-hi);
  /* 400×600 — портретные сканы, соотношение сторон 2:3. */
  aspect-ratio: 2 / 3;
  transition: border-color var(--rrs-dur) var(--rrs-ease);
}

.cert-card__img img {
  display: block;
  width: 100%;
  max-width: 100%;
  height: 100%;
  object-fit: contain;
  border-radius: calc(var(--home-radius) - 4px);
}

.cert-card__zoom {
  position: absolute;
  right: 10px;
  bottom: 10px;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: var(--rrs-radius-pill);
  background-color: color-mix(in srgb, var(--home-bg) 72%, transparent);
  color: var(--home-ink);
  transition: background-color var(--rrs-dur) var(--rrs-ease);
}

.cert-card__zoom svg {
  width: 16px;
  height: 16px;
}

@media (hover: hover) and (pointer: fine) {
  .cert-card__link:hover {
    border-color: var(--home-accent);
  }

  .cert-card__link:hover .cert-card__zoom {
    background-color: var(--home-accent);
    color: var(--rrs-accent-ink);
  }
}

/* Подпись из трёх частей: что подтверждает, кому выдан, срок действия.
   Срок не приглушён — он единственный говорит, что документ просрочен
   и выдан не заказчику; приглушать его нельзя. */
.cert-card__caption {
  display: flex;
  flex-direction: column;
  gap: var(--rrs-space-1);
  font-size: var(--rrs-fs-small);
  line-height: 1.45;
}

.cert-card__what,
.cert-card__who {
  color: var(--home-ink-muted);
}

.cert-card__term {
  color: var(--home-ink);
  font-weight: 600;
}

/* --------------------------------------------------------------------------
   18. Секция #profiles — производители профильных систем

   Логотипов Alutech и Doorhan в проекте нет, поэтому марку держит
   типографика: имя набрано заголовочным шрифтом во всю плашку. Плашки
   одинаковы и по разметке, и по правилам — отличается только текст.
   -------------------------------------------------------------------------- */

.profiles {
  display: grid;
  gap: var(--home-gap);
}

.profiles__item {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--rrs-space-2);
  padding: clamp(22px, 2.6vw, 34px);
  border: 1px solid var(--home-line);
  border-radius: var(--home-radius);
  background-color: var(--home-surface);
}

/* Короткая засечка акцента в углу плашки — тот же приём, что у ::before
   у .home-section__label: марку ведёт линия, а не рамка целиком. */
.profiles__item::before {
  content: "";
  position: absolute;
  top: -1px;
  left: clamp(22px, 2.6vw, 34px);
  width: 36px;
  height: 2px;
  background-color: var(--home-accent);
}

.profiles__name {
  font-family: var(--rrs-font-heading);
  font-size: clamp(30px, 4.4vw, 46px);
  font-weight: 700;
  line-height: 1;
  letter-spacing: -.045em;
}

.profiles__status {
  padding-top: var(--rrs-space-2);
  border-top: 1px solid var(--home-line);
  color: var(--home-ink-dim);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: var(--rrs-ls-label);
  text-transform: uppercase;
}

.profiles__text {
  color: var(--home-ink-muted);
  font-size: var(--rrs-fs-body);
  line-height: 1.6;
}

@media (min-width: 760px) {
  .profiles {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* --------------------------------------------------------------------------
   19. Секция #clients (index.html и все шесть страниц направлений) —
   логотипы компаний, с которыми работали. У самих PNG — непрозрачный белый
   фон, впечённый в файл (не прозрачность): карточка вокруг него тёмная,
   с рамкой, читается как кадр вокруг логотипа, а не подложка под ним.
   -------------------------------------------------------------------------- */

.clients__grid {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-start;
  gap: var(--home-gap);
}

.clients__logo {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 210px;
  height: 118px;
  padding: 18px 26px;
  border: 1px solid var(--home-line);
  border-radius: calc(var(--home-radius) - 4px);
  background-color: var(--home-surface);
  transition: border-color var(--rrs-dur) var(--rrs-ease),
              transform var(--rrs-dur) var(--rrs-ease);
}

.clients__logo-img {
  display: flex;
  width: 100%;
  height: 100%;
}

.clients__logo-img img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

@media (hover: hover) and (pointer: fine) {
  .clients__logo:hover {
    transform: translateY(-3px);
  }
}
