/* rentvk.pro — аренда выставочных конструкций.
   Драматургия страницы: тёмная сцена северного сияния → светлый «воздушный» акт
   каталога (рендеры сняты в светлой студии, поэтому им нужен светлый фон) →
   тёмное закрытие. Палитра и шрифт — из брендбука АСП, см. shared/css/tokens.css. */

/* ══ Шапка ═══════════════════════════════════════════════════════════════════ */

.topbar {
  position: fixed;
  inset: 0 0 auto;
  z-index: var(--z-header);
  transition: background var(--dur-slow) var(--ease-out-quart),
    border-color var(--dur-slow) var(--ease-out-quart);
  border-bottom: 1px solid transparent;
}

/* Стекло включаем только когда под шапкой действительно едет контент. */
.topbar[data-scrolled] {
  background: rgb(19 26 45 / 72%);
  backdrop-filter: blur(var(--glass-blur)) saturate(140%);
  border-bottom-color: var(--line);
}

.topbar__inner {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 3vw, 2.5rem);
  padding-block: 0.875rem;
}

.topbar__brand {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  text-decoration: none;
  flex-shrink: 0;
}

.topbar__brand img {
  width: 132px;
  height: auto;
}

.topbar__dept {
  font-size: var(--fs-xs);
  color: var(--ink-muted);
  border-left: 1px solid var(--line-strong);
  padding-left: 0.625rem;
  line-height: 1.2;
  max-width: 6rem;
}

.topbar__nav {
  display: flex;
  gap: clamp(1rem, 2.2vw, 1.75rem);
  margin-left: auto;
  font-size: var(--fs-sm);
}

.topbar__nav a {
  text-decoration: none;
  color: var(--ink-2);
  transition: color var(--dur) var(--ease-out-quart);
}

.topbar__nav a:hover {
  color: var(--asp-teal);
}

/* Текущий раздел. Не только цветом: цвет один и тот же у наведения,
   и по нему не отличить «здесь я сейчас» от «сюда я навёл мышь».
   Черта снизу остаётся, когда курсор ушёл. */
.topbar__nav a[aria-current] {
  color: var(--ink);
  font-weight: 600;
}

.topbar__nav a[aria-current]::after {
  content: '';
  display: block;
  height: 2px;
  margin-top: 0.3125rem;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--asp-teal), var(--asp-blue));
}

/* Место под черту держим всегда: без него пункт подпрыгивает в момент,
   когда становится текущим, и всё меню дёргается вслед за прокруткой. */
.topbar__nav a::after {
  content: '';
  display: block;
  height: 2px;
  margin-top: 0.3125rem;
}

.topbar__actions {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.topbar__phone {
  text-decoration: none;
  font-weight: 600;
  white-space: nowrap;
  font-size: var(--fs-sm);
}

/* Кнопка-значок в шапке: круглая цель в 44 px, без подписи. */
.topbar__max {
  flex: none;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1px solid var(--line-strong);
  color: var(--ink-2);
  transition: border-color var(--dur) var(--ease-out-quart),
    color var(--dur) var(--ease-out-quart);
}

.topbar__max svg {
  width: 1.125rem;
  height: 1.125rem;
}

.topbar__max:hover,
.topbar__max:focus-visible {
  border-color: var(--asp-teal);
  color: var(--asp-teal);
}

.btn--sm {
  padding: 0.625rem 1.125rem;
  font-size: var(--fs-sm);
}

/* Полоса, где меню уже показано, а места ещё мало: с 901 px до 1150 px
   в строку встают шесть пунктов, телефон и кнопка. Подпись направления
   уступает им место — иначе кнопка брони уезжает за край экрана. */
/* Подпись направления уступает место кнопке брони раньше всех: она
   объясняет, но не ведёт. Запас до 1250 px, а не впритык — иначе шрифт
   чуть шире у другого рендерера, и кнопка снова за краем. */
@media (max-width: 1340px) {
  .topbar__dept {
    display: none;
  }

  .topbar__nav {
    gap: 1rem;
  }
}

/* Ещё уже — уходят два второстепенных пункта. Помечены в разметке,
   а не выбраны по порядку: перестановка пунктов не должна тихо менять
   то, что прячется. */
@media (max-width: 1200px) {
  .topbar__nav a[data-tight] {
    display: none;
  }
}

/* Самая узкая полоса с меню: промежутки поджимаем, кегль не трогаем —
   уменьшать его дальше некуда, там и так мелкий текст. */
@media (max-width: 980px) {
  .topbar__inner {
    gap: 1rem;
  }

  .topbar__nav {
    gap: 0.75rem;
  }

  .topbar__actions {
    gap: 0.625rem;
  }
}

@media (max-width: 900px) {
  .topbar__nav {
    display: none;
  }
}

/* На телефоне звонок важнее прокрутки к форме, поэтому главным действием
   в шапке становится сам номер, а кнопка уступает ему место. */
@media (max-width: 560px) {
  .topbar__actions .btn {
    display: none;
  }
  .topbar__phone {
    padding: 0.5rem 0.875rem;
    border-radius: var(--radius-pill);
    background: var(--asp-blue-deep);
    color: #fff;
  }
}

/* ══ Первый экран: сборка, облёт и выход парка одной липкой сценой ═══════════
   Всё живёт в одной секции, а не в нескольких подряд: на стыке было видно,
   как одна липкая область кончается и начинается следующая. */

/* Фон сцены теперь свой, а не из кадров: конструкция вырезана и лежит
   поверх. Отсюда и свобода — её можно двигать, не упираясь в края кадра. */
.hero-v {
  position: relative;
  background: var(--asp-navy);
}

/* Свечение живёт на липкой части, а не на всей высокой секции: иначе оно
   уезжает вместе с прокруткой и перестаёт быть подсветкой сцены.
   --glow-x двигает его вслед за конструкцией — скрипт меняет эту переменную,
   когда конструкция переезжает на другую сторону. Свет должен оставаться
   за ней, а не светить в опустевшую половину экрана. */
.hero-v__sticky {
  --glow-x: 68%;
  background:
    radial-gradient(70rem 52rem at var(--glow-x) 44%, rgb(41 121 255 / 24%), transparent 66%),
    radial-gradient(46rem 38rem at calc(var(--glow-x) + 16%) 78%, rgb(29 233 182 / 13%), transparent 70%),
    radial-gradient(120% 90% at 50% 120%, #1b2540 0%, var(--asp-navy) 58%);
}

/* Фирменный узор «северное сияние» — тот же, что на тёмных актах страницы. */
.hero-v__aurora {
  position: absolute;
  inset: 0;
  z-index: var(--z-base);
  background: url('/shared/img/aurora-light.svg') var(--glow-x, 68%) center / cover no-repeat;
  opacity: 0.09;
  /* Маска идёт за свечением: узор виден там, где светло, и гаснет по краям. */
  mask-image: radial-gradient(58% 58% at var(--glow-x, 68%) 44%, #000 5%, transparent 74%);
  pointer-events: none;
}

/* Базовое состояние — обычный экран. Высокую липкую прокрутку включает
   только скрипт, поэтому без него первый экран остаётся нормальным. */
.hero-v__sticky {
  position: relative;
  display: flex;
  align-items: center;
  min-height: 100svh;
  /* Отступ текстовой колонки от края кадра. Общий для контейнера и для
     абсолютно позиционированных актов, чтобы они стояли на одной линии. */
  --edge: clamp(1.25rem, 5vw, 7.5rem);
  /* Сверху больше, чем снизу: шапка перекрывает верхние ~70px, и без этого
     текст оказывается оптически выше центра видимой части экрана.
     Держим отступы в переменных: слой актов вынесен из потока и повторяет их
     вручную — иначе он лёг бы под шапку и вплотную к нижнему краю. */
  --pad-t: clamp(6rem, 13vh, 9rem);
  --pad-b: clamp(3rem, 8vh, 5rem);
  padding-block: var(--pad-t) var(--pad-b);
  overflow: hidden;
}

/* Высота на всю сцену сразу: сборка, поворот и выход площадки идут одной
   липкой прокруткой. Три акта — примерно по 215vh на каждый; меньше — и текст
   не успевает прочитаться, больше — прокрутка вязнет.

   Высота подобрана под хореографию, а не наоборот: сцена заканчивается почти
   у нижней границы секции, и сразу за ней идёт каталог. Прежние 740vh
   оставляли после собранной площадки почти экран пустого хода. */
[data-motion='on'] .hero-v {
  height: var(--hero-len, 650vh);
}

[data-motion='on'] .hero-v__sticky {
  position: sticky;
  top: 0;
  height: 100svh;
  min-height: 0;
}

/* Кадры прозрачные, поэтому вписываем целиком, а не обрезаем: конструкция
   должна помещаться в блок вся, без подгонки масштабом. */
.hero-v__media {
  position: absolute;
  inset: 0;
  z-index: var(--z-raised);
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: 74% 50%;
}

/* Канвасов два — сборка и облёт, они лежат друг на друге, и прозрачностью
   между ними управляет скрипт. Пока кадры не загружены, виден постер;
   скрипт гасит его, когда канвас готов рисовать. */
.hero-v__still {
  transition: opacity 240ms var(--ease-out-quart);
}

/* Пока сцена не запущена — узкий экран или отключённое движение — постер
   остаётся единственным фоном, и весь текст первого экрана ложится прямо
   на него. Кадр светлый, белый текст на нём не читается: замер показал
   2,13:1 на светлых участках при норме 4,5.

   Приглушаем сам кадр, а не порядок слоёв: затемняющий слой лежит ниже
   постера, и поднимать его значит менять вид работающей сцены на десктопе
   ради случая, где сцены нет. */
:root:not([data-motion='on']) .hero-v__still {
  filter: brightness(0.42) saturate(0.9);
}

/* Лёгкая подложка слева. Плотная больше не нужна: фон свой и ровный, а от
   яркого полотна текст теперь отделён расстоянием, а не затемнением. */
/* Подложка теперь НИЖЕ конструкции: она затемняет фон под текстом, а сам
   объект вырезан и затемнять его незачем. Раньше он был частью фона и гасился
   вместе с ним. */
.hero-v__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(
    100deg,
    rgb(10 15 28 / 78%) 0%,
    rgb(10 15 28 / 46%) 34%,
    transparent 62%
  );
}

/* Первый экран полноэкранный, поэтому текст стоит не в общей колонке страницы,
   а ближе к краю кадра — иначе он спорит с конструкцией в центре. */
.hero-v__copy {
  position: relative;
  z-index: var(--z-sticky);
  max-width: none;
  padding-inline: var(--edge);
}

.hero-v__copy h1 {
  max-width: 16ch;
  margin-bottom: var(--space-4);
}

.hero-v__copy .lead {
  max-width: 44ch;
  margin-bottom: var(--space-5);
}

/* Цена — главное, ради чего сюда приходят, поэтому она стоит прямо под
   подзаголовком на любой ширине. Стеклянная панель справа её не заменяет:
   панель — спецификация одной модели, а это строка про входную цену
   и бесплатную доставку. Ниже 1101 px панель вообще скрыта. */
.hero-v__price {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.375rem 0.75rem;
  margin: 0 0 var(--space-5);
}

.hero-v__price b {
  font-size: clamp(1.5rem, 1.2rem + 1.4vw, 2rem);
  font-weight: 600;
  line-height: 1.05;
  letter-spacing: -0.01em;
  color: var(--ink);
}

.hero-v__price span {
  font-size: var(--fs-sm);
  color: var(--ink-muted);
}


.hero-v__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin: 0;
}

@media (max-width: 720px) {
  .hero-v__sticky {
    align-items: flex-start;
    padding-top: clamp(5rem, 14vh, 8rem);
  }
  .hero-v__actions {
    flex-direction: column;
    align-items: stretch;
    max-width: 20rem;
  }
}

/* ══ Акты: пачки текста, проходящие снизу вверх ══════════════════════════════
   Базовое состояние — обычный поток, все акты видны подряд. Наложение
   и движение включает только скрипт, поэтому без него и в headless-рендере
   содержание остаётся на месте. */

.act-step {
  margin-bottom: var(--space-8);
}

.act-step:last-child {
  margin-bottom: 0;
}

.act-step h2 {
  font-size: clamp(1.75rem, 1.1rem + 2.4vw, 2.75rem);
  margin-bottom: var(--space-6);
}

/* Слой актов занимает всю видимую высоту сцены, а не коробку в 22rem.
   Актам, выключенным по центру, это ничего не меняет — они как были, так и
   остаются посреди экрана. А финальному, который прижат к низу, нужен
   настоящий низ экрана: в короткой коробке он упирался в её край
   и ложился прямо на конструкции. */
[data-motion='on'] .acts {
  position: absolute;
  inset: var(--pad-t) 0 var(--pad-b);
  padding-inline: 0;
}

/* Отступ повторяется на самом акте: абсолютно позиционированный элемент
   отсчитывается от padding-box родителя, поэтому его padding текст не сдвинет. */
[data-motion='on'] .act-step {
  position: absolute;
  inset: 0;
  margin: 0;
  padding-inline: var(--edge);
  display: flex;
  flex-direction: column;
  justify-content: center;
  opacity: var(--o, 0);
  /* Акт проходит снизу вверх, а не проявляется на месте: именно это движение
     и читается как кинематографичный переход. */
  transform: translate3d(0, var(--y, 0px), 0);
  will-change: opacity, transform;
}

/* Акт, который стоит у правого края: конструкция в этот момент переезжает
   влево, и текст занимает освободившуюся половину. Внутри плашек выключка
   остаётся левой — иначе текст начинает «рваться» по правому краю. */
[data-motion='on'] .act-step[data-side='right'] {
  align-items: flex-end;
}

[data-motion='on'] .act-step[data-side='right'] > * {
  text-align: left;
}

/* Ниже 1200 px менять стороны негде: конструкция и колонка плашек не
   помещаются рядом. Текст остаётся слева, конструкция — справа. */
@media (max-width: 1199px) {
  [data-motion='on'] .act-step[data-side='right'] {
    align-items: flex-start;
  }
}


/* ── Плашки ────────────────────────────────────────────────────────────────── */

.tiles {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: clamp(0.625rem, 1.2vw, 1rem);
  grid-template-columns: repeat(2, minmax(0, 1fr));
  width: min(100%, 38rem);
}

.tiles--rich {
  width: min(100%, 44rem);
}

/* Плашка непрозрачная, а не стеклянная: она заезжает на яркое полотно,
   и на просвет текст в ней терялся. Собственная тёмная подложка держит
   контраст независимо от того, что оказалось за ней. */
.tile {
  padding: clamp(0.875rem, 1.4vw, 1.25rem);
  border-radius: var(--radius);
  background: rgb(11 17 31 / 82%);
  border: 1px solid var(--glass-line);
  backdrop-filter: blur(14px) saturate(120%);
}

.tile__icon {
  width: 1.5rem;
  height: 1.5rem;
  margin-bottom: 0.625rem;
  color: var(--asp-teal);
}

.tile h3 {
  font-size: var(--fs-base);
  margin-bottom: 0.25rem;
}

.tile p {
  margin: 0;
  font-size: var(--fs-sm);
  line-height: 1.45;
  color: var(--ink-2);
}

.tiles--rich .tile p {
  color: var(--ink-2);
}

/* Ниже 1200 px конструкция стоит рядом с текстом, а не напротив: широкая
   колонка плашек на неё наезжает, поэтому здесь она уже.
   Правило стоит после основного: у них одинаковый вес, решает порядок. */
@media (max-width: 1199px) {
  .tiles--rich {
    width: min(100%, 32rem);
  }
}

@media (max-width: 640px) {
  .tiles {
    grid-template-columns: 1fr;
  }
}

/* ── Режим секвенции: включается скриптом ──────────────────────────────────── */
@media (max-width: 900px) {
}

/* Стеклянная панель уместна здесь: под ней реально движется 3D-сцена. */
.spec {
  position: absolute;
  right: clamp(1.25rem, 4vw, 2.5rem);
  top: 50%;
  z-index: var(--z-sticky);
  width: 15rem;
  margin-top: -6rem;
  padding: 1.25rem;
  border-radius: var(--radius-lg);
  background: var(--glass-bg);
  border: 1px solid var(--glass-line);
  backdrop-filter: blur(var(--glass-blur)) saturate(130%);
  opacity: calc(1 - var(--e, 0) * 1.2);
}

.spec__name {
  margin: 0 0 0.25rem;
  font-size: var(--fs-sm);
  color: var(--ink-muted);
}

.spec__price {
  margin: 0 0 0.875rem;
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
}

.spec__price b {
  font-size: 1.75rem;
  font-weight: 800;
  letter-spacing: -0.02em;
}

.spec__price span {
  font-size: var(--fs-xs);
  color: var(--ink-muted);
}

.spec__list {
  margin: 0;
  display: grid;
  gap: 0.5rem;
  font-size: var(--fs-sm);
}

.spec__list > div {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding-top: 0.5rem;
  border-top: 1px solid var(--line);
}

.spec__list dt {
  color: var(--ink-muted);
}

.spec__list dd {
  margin: 0;
  font-weight: 600;
}

.scrollhint {
  position: absolute;
  left: 50%;
  bottom: 1.25rem;
  z-index: var(--z-sticky);
  transform: translateX(-50%);
  margin: 0;
  font-size: var(--fs-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-muted);
  opacity: calc(1 - var(--p, 0) * 6);
}

.scrollhint span {
  display: block;
  animation: hint 2.4s var(--ease-out-quart) infinite;
}

@keyframes hint {
  0%,
  100% {
    transform: translateY(0);
    opacity: 0.5;
  }
  50% {
    transform: translateY(5px);
    opacity: 1;
  }
}

@media (max-width: 1100px) {
  .spec {
    display: none;
  }
}

@media (max-width: 720px) {
  .scrollhint {
    display: none;
  }
}

/* ══ Акты страницы ═══════════════════════════════════════════════════════════ */

.act {
  position: relative;
  padding-block: var(--space-9);
}

.act--light {
  --ink: var(--lt-ink);
  --ink-2: var(--lt-ink-2);
  --ink-muted: var(--lt-ink-muted);
  --line: var(--lt-line);
  --line-strong: var(--lt-line);
  background: var(--lt-bg-2);
  color: var(--ink);
}

.act--tint {
  background: var(--lt-bg);
}

.act--dark {
  background: var(--bg);
  color: var(--ink);
  overflow: hidden;
}

.act__aurora {
  display: none;
}

.act__aurora {
  position: absolute;
  inset: -30% -10% auto;
  height: 70%;
  background: url('/shared/img/aurora-light.svg') center / cover no-repeat;
  opacity: 0.1;
  mask-image: radial-gradient(70% 70% at 50% 30%, #000, transparent 75%);
  pointer-events: none;
}

.act__head {
  margin-bottom: var(--space-7);
}

.act__head .lead {
  margin-bottom: 0;
}

.act__head--narrow {
  margin-bottom: var(--space-6);
}

/* ══ Каталог ═════════════════════════════════════════════════════════════════ */

.cat {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 17.5rem), 1fr));
  gap: clamp(1rem, 2vw, 1.5rem);
}

/* Карточка: метка, кадр, характеристики, ряд с ценой. Прежде фото шло
   в край, а метка лежала на нём — на светлых снимках она держалась на
   подложке. Теперь кадр в своей рамке внутри карточки, и метка стоит над
   ним на фоне самой карточки: читается одинаково при любом снимке. */
.cat__item {
  display: flex;
  flex-direction: column;
  gap: 0.875rem;
  padding: 1rem;
  border: 1px solid var(--lt-line);
  border-radius: var(--radius-lg);
  background: var(--lt-bg-2);
  transition: border-color var(--dur) var(--ease-out-quart),
    transform var(--dur) var(--ease-out-quart);
}

.cat__item:hover {
  border-color: var(--asp-blue);
  transform: translateY(-3px);
}

.cat__tag {
  align-self: flex-start;
  padding: 0.25rem 0.625rem;
  border: 1px solid var(--lt-line);
  border-radius: var(--radius-pill);
  background: var(--lt-bg);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--lt-ink-2);
}

.cat__shot {
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--lt-bg);
}

.cat__shot img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

/* Широкая карточка ломает ровную сетку — иначе каталог читается как обои. */
.cat__item--wide {
  grid-column: span 2;
}

.cat__item--wide .cat__shot img {
  aspect-ratio: 21 / 9;
}

@media (max-width: 47rem) {
  .cat__item--wide {
    grid-column: span 1;
  }
  .cat__item--wide .cat__shot img {
    aspect-ratio: 16 / 9;
  }
}

.cat__body {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  flex: 1;
}

.cat__body h3 {
  margin: 0;
}

/* Характеристики через точку, а не фразой: так их сравнивают между
   карточками, не вчитываясь. */
.cat__spec {
  margin: 0;
  flex: 1;
  font-size: var(--fs-sm);
  line-height: 1.5;
  color: var(--lt-ink-muted);
}

.cat__foot {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-top: 0.375rem;
  padding-top: 0.875rem;
  border-top: 1px solid var(--lt-line);
}

.cat__price {
  margin: 0;
  display: flex;
  flex-direction: column;
  font-size: var(--fs-xs);
  color: var(--lt-ink-muted);
}

.cat__price b {
  font-size: var(--fs-xl);
  font-weight: 800;
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--lt-ink);
  font-variant-numeric: tabular-nums;
}

.cat__price--ask {
  font-size: var(--fs-base);
  color: var(--lt-ink-2);
  font-weight: 600;
}

/* ══ Работы: стена снимков ═══════════════════════════════════════════════════
   Колонки стоят под углом и разворачиваются к зрителю по ходу прокрутки.
   Углы, масштаб и расхождение колонок скрипт отдаёт переменными — сама
   раскладка обычная: четыре колонки, в каждой список снимков.

   Без скрипта, на узком экране и при отключённом движении переменные
   остаются нулями, и раздел превращается в ровную сетку фотографий.
   Ничего специально прятать или подменять для этого не нужно. */

.wall {
  /* Стена шире контейнера: угол съедает края, и в контейнере она читалась бы
     обрезанной по бокам. */
  padding-inline: clamp(1rem, 3vw, 2.5rem);
  overflow: hidden;
  perspective: 1600px;
  perspective-origin: 50% 45%;
}

.wall__stage {
  /* Ширину ограничиваем: на большом мониторе колонки растягивались, и кадры
     выходили крупнее, чем нужно разделу-подтверждению. */
  max-width: 88rem;
  margin-inline: auto;
  display: flex;
  gap: clamp(0.5rem, 1vw, 0.875rem);
  align-items: flex-start;
  transform-style: preserve-3d;
  transform: rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg))
    rotateZ(var(--rz, 0deg)) translateX(var(--tx, 0%)) scale(var(--s, 1));
}

[data-motion='on'] .wall__stage {
  will-change: transform;
}

.wall__col {
  list-style: none;
  margin: 0;
  padding: 0;
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: clamp(0.5rem, 1vw, 0.875rem);
  transform: translateY(var(--y, 0px));
}

.wall img {
  display: block;
  width: 100%;
  aspect-ratio: 3 / 4;
  object-fit: cover;
  border-radius: var(--radius);
  /* На светлом фоне снимку нужна своя граница: без тени кадр со светлым
     потолком или стеной сливается с полем раздела. */
  box-shadow: 0 6px 20px rgb(12 22 44 / 12%);
  /* Снимки сняты в разных залах и при разном свете. Лёгкое приглушение
     сводит их в один ряд, не превращая в чёрно-белую плитку. */
  filter: saturate(0.92) contrast(1.02);
}

/* Ниже 900 px разворот не запускается: угол на узком экране съедает
   половину снимков, а параллакс стоит батареи. Колонки становятся сеткой. */
@media (max-width: 72rem) {
  .wall__stage {
    flex-wrap: wrap;
  }

  /* Пятая колонка на среднем экране делает кадр уже пальца — переносим её
     на вторую строку, а не сжимаем весь ряд. */
  .wall__col {
    flex: 1 1 calc(25% - 0.875rem);
  }
}

@media (max-width: 56rem) {
  .wall__col {
    flex: 1 1 calc(33.333% - 0.875rem);
  }
}

@media (max-width: 34rem) {
  .wall__col {
    flex: 1 1 calc(50% - 0.5rem);
  }
}

/* ══ О компании и заявка ═════════════════════════════════════════════════════ */

/* `clip`, а не `hidden`: `hidden` делает секцию контейнером прокрутки,
   и липкая колонка карточки липнет к ней, а не к экрану — то есть
   не липнет вовсе. `clip` режет так же, контейнером не становится.
   Правило только для этой секции: липкое содержимое есть у неё одной. */
#about {
  overflow: clip;
}

/* Страховка для браузеров без `overflow: clip`: без обрезки сияние
   с горизонтальным вылетом растащило бы страницу вбок. Здесь оно
   в границах секции. */
#about .act__aurora {
  inset: -30% 0 auto;
}

/* Раньше это были две колонки: слева рассказ о соседних направлениях,
   справа узкая форма. Текст кончался задолго до конца формы, и левая
   половина блока стояла пустой. Теперь направления идут своей полосой
   во всю ширину — карточки от этого только выиграли, — а карточка заявки
   под ними делится изнутри. */
.about {
  position: relative;
  z-index: var(--z-raised);
  display: grid;
  gap: clamp(2.5rem, 6vw, 4rem);
}

.about__intro .measure {
  margin-bottom: 0;
}

/* Карточка заявки: слева обещание и проверяемые факты, справа сама форма.
   Форма шире — в ней поля, календарь и список ресурсов. */
.about__lead {
  display: grid;
  gap: clamp(1.5rem, 4vw, 3rem);
}

@media (min-width: 60rem) {
  .about__lead {
    /* Не `1fr`: `minmax(auto, 1fr)` берёт минимумом ширину содержимого,
       а форма Битрикса заявляет 700 px — колонка растягивалась под неё,
       и карточка выходила шире экрана. Страница вбок при этом
       не разъезжалась: секция режет лишнее по `overflow: hidden`,
       то есть правая половина формы просто не существовала. */
    grid-template-columns: minmax(0, 0.85fr) minmax(0, 1fr);
    align-items: start;
  }

  /* Форма втрое длиннее пояснения, и под ним оставалась пустота. Липкая
     колонка едет рядом с полями: вопрос «кому я это отправляю» возникает
     не на первом поле, а на пятом. Отступ сверху — под липкую шапку. */
  .about__pitch {
    position: sticky;
    top: 6.5rem;
  }
}

.about__pitch {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

/* Пояснение стало ведущим абзацем: оно отвечает на «что сейчас произойдёт»
   и потому стоит сразу под заголовком, а не после фактов. */
.about__pitch .lead {
  margin: 0;
  max-width: 38ch;
  font-size: var(--fs-base);
}

.about__form {
  min-width: 0;
}

/* Соседние направления — карточками со снимком, а не текстовыми пилюлями:
   по слову «вывески» не понять, что за ним настоящее производство. */
.about__links {
  list-style: none;
  margin: var(--space-6) 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
  gap: clamp(0.75rem, 2vw, 1.5rem);
}

.about__links a {
  display: flex;
  flex-direction: column;
  gap: 0.625rem;
  text-decoration: none;
  color: var(--ink);
  transition: color var(--dur) var(--ease-out-quart);
}

.about__links img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  transition: border-color var(--dur) var(--ease-out-quart),
    transform var(--dur) var(--ease-out-quart);
}

.about__links span {
  font-size: var(--fs-sm);
  font-weight: 600;
}

/* Стрелка показывает, что это переход на другой сайт, а не якорь. */
.about__links span::after {
  content: ' →';
  color: var(--asp-teal);
}

@media (hover: hover) {
  .about__links a:hover {
    color: var(--asp-teal-light);
  }

  .about__links a:hover img {
    border-color: var(--asp-teal);
    transform: translateY(-2px);
  }
}

.about__links a:focus-visible {
  outline: 2px solid var(--asp-teal);
  outline-offset: 4px;
  border-radius: var(--radius);
}

.about__lead {
  padding: clamp(1.25rem, 3vw, 2.25rem);
  border-radius: var(--radius-lg);
  background: var(--glass-bg);
  border: 1px solid var(--glass-line);
  scroll-margin-top: 6rem;
}

.about__lead h3 {
  margin-bottom: 0;
}

.about__lead .lead-form {
  max-width: none;
}

/* Контакты — своей карточкой: форма не единственный путь, и тот, кто
   форм не любит, должен видеть телефон здесь, а не искать его в подвале. */
.about__direct {
  padding: 1rem 1.125rem;
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius);
}

.about__direct p {
  margin: 0 0 0.75rem;
  font-size: var(--fs-xs);
  color: var(--ink-muted);
}

.about__direct ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 1.25rem;
}

.about__direct a {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  /* 44 px тач-цели: по этим ссылкам звонят с телефона. */
  min-height: 44px;
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--ink);
  text-decoration: none;
  white-space: nowrap;
  transition: color var(--dur) var(--ease-out-quart);
}

.about__ico {
  flex: none;
  display: grid;
  place-items: center;
  width: 1.875rem;
  height: 1.875rem;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: rgb(255 255 255 / 5%);
  color: var(--asp-teal);
  transition: border-color var(--dur) var(--ease-out-quart);
}

.about__ico svg {
  width: 0.9375rem;
  height: 0.9375rem;
}

@media (hover: hover) {
  .about__direct a:hover {
    color: var(--asp-teal-light);
  }

  .about__direct a:hover .about__ico {
    border-color: var(--asp-teal);
  }
}

/* Согласие на обработку данных. Чекбокс с required — браузер сам не даст
   отправить форму без него, отдельная проверка в JS не нужна. */
.consent {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.625rem;
  align-items: start;
  /* Не мельче основного мелкого кегля: согласие должно читаться, а не прятаться. */
  font-size: var(--fs-sm);
  line-height: 1.5;
  color: var(--ink-2);
  cursor: pointer;
}

.consent input {
  width: 1.125rem;
  height: 1.125rem;
  margin: 0.125rem 0 0;
  accent-color: var(--asp-blue-deep);
  cursor: pointer;
}

.consent a {
  color: var(--ink);
}

.consent a:hover {
  color: var(--asp-teal);
}

/* ══ Страница документа (политика обработки данных) ══════════════════════════
   Длинный текст читается с тёмного хуже, поэтому здесь светлый лист. */

.doc-page {
  background: var(--lt-bg);
  color: var(--lt-ink);
  --ink: var(--lt-ink);
  --ink-2: var(--lt-ink-2);
  --ink-muted: var(--lt-ink-muted);
  --line: var(--lt-line);
}

.doc-top {
  border-bottom: 1px solid var(--lt-line);
  background: var(--lt-bg-2);
}

.doc-top__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding-block: var(--space-4);
  font-size: var(--fs-sm);
}

.doc-top__back {
  text-decoration: none;
  font-weight: 600;
}

.doc-top__back:hover {
  color: var(--asp-blue-deep);
}

.doc-top__phone {
  text-decoration: none;
  font-weight: 600;
  white-space: nowrap;
}

.doc {
  padding-block: var(--space-8);
}

.doc__inner {
  max-width: var(--container-narrow);
}

.doc h1 {
  font-size: var(--fs-h2);
  margin-bottom: var(--space-2);
}

.doc h2 {
  font-size: var(--fs-h3);
  margin-top: var(--space-7);
}

.doc__meta {
  margin-bottom: var(--space-7);
}

.doc p,
.doc li {
  max-width: 68ch;
}

.doc li {
  margin-bottom: 0.375rem;
}

.doc a {
  color: var(--asp-navy-calm);
}

/* Таблица в документе. Прокручивается вбок в своей рамке: три колонки
   с длинными формулировками на телефон не помещаются никак, а резать
   юридический текст переносами нельзя. */
.doc__table {
  width: 100%;
  min-width: 34rem;
  border-collapse: collapse;
  font-size: var(--fs-sm);
}

.doc__table th,
.doc__table td {
  padding: 0.75rem 0.875rem;
  border: 1px solid var(--lt-line);
  text-align: left;
  vertical-align: top;
  color: var(--lt-ink-2);
}

.doc__table thead th {
  background: var(--lt-bg);
  color: var(--lt-ink);
  font-weight: 600;
}

.doc .tablewrap {
  margin-block: var(--space-5);
  /* Своя прокрутка вбок: три колонки с юридическими формулировками
     на телефон не помещаются, а резать текст нельзя. tabindex в разметке
     делает рамку доступной с клавиатуры. */
  overflow-x: auto;
  border: 1px solid var(--lt-line);
  border-radius: var(--radius);
}

.doc .tablewrap:focus-visible {
  outline: 2px solid var(--asp-blue-deep);
  outline-offset: 2px;
}

/* Ссылки внутри документа специфичнее кнопки и перекрывали её белый текст:
   синее по синему давало 1,76:1. */
.doc a.btn {
  color: #fff;
}

/* Выходы со страницы 404. Список, а не кнопки в ряд: вариантов три,
   и у каждого нужно пояснение — куда он ведёт. */
.err__links {
  margin: var(--space-5) 0;
  padding-left: 1.25rem;
}

.err__links li {
  margin-bottom: 0.5rem;
}

.doc__file {
  margin-block: var(--space-5);
}

/* Смотрелка PDF: высота от экрана, но не выше него — иначе страница
   превращается в один документ без начала и конца. */
.doc__pdf {
  display: block;
  width: 100%;
  height: min(80vh, 46rem);
  border: 1px solid var(--lt-line);
  border-radius: var(--radius);
  background: var(--lt-bg);
}

@media (max-width: 40rem) {
  /* На телефоне встроенный просмотр PDF почти везде неудобен: мелко,
     без поиска и с двойной прокруткой. Оставляем ссылку. */
  .doc__pdf {
    display: none;
  }
}

.doc-foot {
  border-top: 1px solid var(--lt-line);
  background: var(--lt-bg-2);
  padding-block: var(--space-6);
  font-size: var(--fs-sm);
}

.doc-foot p {
  margin-bottom: 0.5rem;
}

.doc-foot a {
  color: var(--asp-navy-calm);
}

/* ══ Подвал ══════════════════════════════════════════════════════════════════ */

.foot {
  background: var(--bg-deep);
  padding-block: var(--space-8) var(--space-6);
  border-top: 1px solid var(--line);
}

.foot__inner {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) repeat(3, minmax(0, 1fr));
  gap: var(--space-6);
}

@media (max-width: 60rem) {
  .foot__inner {
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr));
  }
}

.foot__brand img {
  width: 168px;
  height: auto;
  margin-bottom: 0.875rem;
}

.foot__col p {
  margin: 0 0 0.375rem;
  font-size: var(--fs-sm);
}

.foot__col a {
  text-decoration: none;
}

.foot__col a:hover {
  color: var(--asp-teal);
}

.foot__label {
  font-weight: 700;
  margin-bottom: 0.625rem !important;
}

.foot__legal {
  margin-top: var(--space-7);
  padding-top: var(--space-5);
  border-top: 1px solid var(--line);
}

.foot__legal p {
  margin: 0;
}

/* Документы в строку, а не столбиком: их три, и столбик в подвале
   выглядел бы как ещё одна колонка меню. */
.foot__docs {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 1.5rem;
}

.foot__docs a {
  display: inline-flex;
  align-items: center;
  /* 44 px тач-цели: в подвале ссылки жмут пальцем. */
  min-height: 44px;
}

/* ══ Появление блоков ════════════════════════════════════════════════════════
   Прячем содержимое только когда JS подтвердил, что умеет его показать.
   Без скрипта и в headless-рендере страница остаётся полностью видимой. */

[data-reveal] .reveal {
  opacity: 0;
  transform: translate3d(0, 18px, 0);
}

[data-reveal] .reveal.is-in {
  opacity: 1;
  transform: none;
  transition: opacity 620ms var(--ease-out-quart),
    transform 620ms var(--ease-out-quart);
  transition-delay: calc(var(--i, 0) * var(--step, 55ms));
}

/* ══ Уважение к prefers-reduced-motion ═══════════════════════════════════════
   Сцена перестаёт быть аттракционом: конструкция замирает в выигрышном ракурсе,
   длинная прокрутка схлопывается, чтобы не гонять пользователя по пустоте. */

@media (prefers-reduced-motion: reduce) {
  .scrollhint span {
    animation: none;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ── Финал сцены: рассказ о компании рядом с собранной площадкой ────────────
   Колонка узкая: справа стоит вся площадка, и текст делит с ней экран
   так же, как в первых двух актах. */

.hero-v__about {
  max-width: 28rem;
}

.hero-v__about h2 {
  margin-bottom: var(--space-4);
}

.hero-v__about p {
  margin-bottom: var(--space-6);
  color: var(--ink-2);
}

/* Плашки с цифрами. Всё оформление, появление и наведение достаются
   от общего .tile — здесь только типографика самих цифр. */
.tiles--facts {
  width: min(100%, 26rem);
}

.tiles--facts b {
  display: block;
  margin-bottom: 0.25rem;
  font-size: clamp(1.375rem, 1.1rem + 1vw, 1.75rem);
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -0.01em;
  color: var(--asp-teal-light);
  font-variant-numeric: tabular-nums;
}

.tiles--facts span {
  display: block;
  font-size: var(--fs-sm);
  line-height: 1.45;
  color: var(--ink-muted);
}


/* ══ Форма Битрикс24 ═════════════════════════════════════════════════════════
   Форма приходит со своими светлыми стилями и рисуется в обычном DOM — значит
   её можно привести к тёмной теме страницы. Без этого белый прямоугольник
   посреди тёмной секции выглядит вставленным по ошибке.

   Темизируем по фактической разметке, снятой с живой формы, а не по догадкам.
   Две ловушки, на которые уже наступили:
     — у полей Битрикса нет атрибута type, поэтому input[type='text'] по ним
       не попадает; поля, плашки услуг и ячейки календаря — это все .b24-form-control
       и calendar-resbook-*, причём среди них есть и input, и label, и div;
     — осветлять текст правилом на голый `label` нельзя: под него попадают
       плашки со светлой подложкой, и надпись становится белым по белому.

   !important вынужденный: правила Битрикса приходят отдельным файлом
   и специфичнее наших. Классы принадлежат ему же и при обновлении могут
   поехать — тогда форма просто вернётся к светлому виду, но останется
   рабочей и читаемой. */

.b24-mount {
  color-scheme: dark;
}

/* Карточку уже нарисовала страница — своя подложка форме не нужна. */
.b24-mount .b24-form,
.b24-mount .b24-form-wrapper,
.b24-mount .b24-form-content,
.b24-mount .b24-form-padding-side,
.b24-mount .b24-form-header-padding {
  background: transparent !important;
  box-shadow: none !important;
}

/* Всё, у чего была светлая подложка: поля, плашки услуг, выбор ресурса,
   ячейки календаря. */
.b24-mount .b24-form-control,
.b24-mount .calendar-resbook-webform-block-input,
.b24-mount .calendar-resbook-webform-block-date-item-inner {
  /* Именно `background-color`, а не сокращённое `background`: сокращённая
     запись сбрасывает и `background-image`, а Битрикс рисует ею стрелку
     раскрывающегося списка у выбора ресурса. Со сброшенной картинкой поле
     выглядело обычным текстовым, и не было видно, что оно раскрывается. */
  background-color: rgb(255 255 255 / 6%) !important;
  border: 1px solid var(--line) !important;
  border-radius: var(--radius) !important;
  color: var(--ink) !important;
}

.b24-mount .b24-form-control::placeholder {
  color: var(--ink-muted) !important;
}

.b24-mount .b24-form-control:focus {
  border-color: var(--asp-teal) !important;
  outline: none !important;
}

/* Подписи — только по своим классам. Цвет обязательной звёздочки не трогаем:
   он несёт смысл, а не оформление. */
.b24-mount .b24-form-control-label,
.b24-mount .b24-form-control-desc,
.b24-mount .b24-form-control-comment,
.b24-mount .b24-form-field-agreement,
.b24-mount .calendar-resbook-webform-block-title,
.b24-mount .calendar-resbook-webform-block-date-month {
  color: var(--ink-2) !important;
}

.b24-mount input[type='checkbox'],
.b24-mount input[type='radio'] {
  accent-color: var(--asp-teal);
}

/* Кнопка отправки — фирменный синий, тот же, что у остальных кнопок сайта. */
.b24-mount button {
  background: var(--asp-blue-deep) !important;
  border-color: var(--asp-blue-deep) !important;
  color: #fff !important;
  border-radius: var(--radius) !important;
  font-weight: 600 !important;
}

/* Onest везде, включая CRM-часть. */
.b24-mount,
.b24-mount input,
.b24-mount textarea,
.b24-mount select,
.b24-mount button {
  font-family: var(--font) !important;
}

/* Список выбора ресурса — та же беда, что и в калькуляторе: у пунктов
   прозрачный фон и белый текст, а раскрытое окно рисует браузер поверх
   страницы. Ставим фон явно. */
.b24-mount select option {
  background: var(--bg-deep) !important;
  color: var(--ink) !important;
}

/* Выбранный день. Собственную подсветку Битрикса тёмная тема съедает, а без
   неё непонятно, какая дата выбрана. Селектор по вхождению «selected»: точное
   имя класса принадлежит Битриксу и может смениться, а подстрока переживёт
   больше обновлений, чем угаданное целиком имя. */
.b24-mount [class*='date-item'][class*='selected'] .calendar-resbook-webform-block-date-item-inner,
.b24-mount .calendar-resbook-webform-block-date-item-inner[class*='selected'],
.b24-mount .calendar-resbook-webform-block-date-item-inner[class*='active'] {
  background: var(--asp-teal-deep) !important;
  border-color: var(--asp-teal-deep) !important;
  color: #06231d !important;
  font-weight: 600 !important;
}

/* Звёздочка обязательного поля. Битрикс красит её чистым красным — на светлом
   фоне это нормально, на нашем тёмном даёт 4,33:1 и не проходит AA. Оттенок
   оставляем красным: он несёт смысл, — но осветляем до проходного. */
.b24-mount .b24-form-control-required {
  color: #ff6b6b !important;
}

/* Внутренности ячейки календаря — число и день недели — красятся собственным
   тёмно-серым, и на тёмной ячейке это 1,37:1. Заставляем наследовать цвет
   самой ячейки: тогда и обычные, и выбранный день читаются автоматически,
   и не нужно угадывать имя класса для каждой подписи. */
.b24-mount [class*='calendar-resbook-webform-block-date-item'] * {
  color: inherit !important;
}

/* Строка с выбранным периодом — та же история, свой тёмно-серый. */
.b24-mount [class*='calendar-resbook-webform-block-result'],
.b24-mount [class*='calendar-resbook-webform-block-result'] * {
  color: var(--ink) !important;
}

/* ══ Кнопка «наверх» ═════════════════════════════════════════════════════════
   Страница длинная — двадцать экранов, — и возврат к началу через шапку
   не очевиден: до неё ещё надо долистать. Появляется после двух экранов,
   раньше начало страницы и так рядом. */

.totop {
  position: fixed;
  right: clamp(1rem, 2.5vw, 2rem);
  /* Над баннером cookie, пока тот показан: его высоту отдаёт скрипт
     переменной — она зависит и от ширины экрана, и от того, раскрыта ли
     настройка категорий. */
  bottom: calc(clamp(1rem, 2.5vw, 2rem) + var(--cookie-h, 0px));
  z-index: var(--z-top, 200);
  display: grid;
  place-items: center;
  /* 44 px — минимум по WCAG для тач-цели. */
  width: 3rem;
  height: 3rem;
  border-radius: 50%;
  border: 1px solid var(--line-strong);
  background: rgb(11 17 31 / 88%);
  backdrop-filter: blur(10px);
  color: var(--ink-2);
  text-decoration: none;
  transition: color var(--dur) var(--ease-out-quart),
    border-color var(--dur) var(--ease-out-quart),
    transform var(--dur) var(--ease-out-quart);
}

.totop svg {
  width: 1.25rem;
  height: 1.25rem;
}

.totop:hover,
.totop:focus-visible {
  color: var(--ink);
  border-color: var(--asp-teal);
  transform: translateY(-2px);
}

/* На телефоне поднимаем над липкой панелью действий: иначе кнопка ложится
   поверх «Забронировать». */
@media (max-width: 900px) {
  .totop {
    bottom: calc(4.25rem + env(safe-area-inset-bottom, 0px) + var(--cookie-h, 0px));
  }
}

@media (prefers-reduced-motion: reduce) {
  .totop:hover,
  .totop:focus-visible {
    transform: none;
  }
}


/* ══ Файлы cookie ════════════════════════════════════════════════════════════
   Панель фиксированная, поэтому её появление не двигает раскладку — сдвиг
   здесь был бы обиднее всего: баннер видят все и в первую секунду.

   Скрыт в разметке и показывается скриптом только тому, кто ещё не выбирал:
   вернувшийся посетитель не видит мигания. */

.cookie {
  position: fixed;
  inset: auto 0 0;
  /* Выше липкой панели телефона: она тоже прижата к низу. */
  z-index: calc(var(--z-top, 200) + 10);
  padding-block: 1rem;
  background: rgb(11 17 31 / 96%);
  border-top: 1px solid var(--line);
  backdrop-filter: blur(var(--glass-blur)) saturate(140%);
  color: var(--ink);
}

.cookie__inner {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 3vw, 2.5rem);
  flex-wrap: wrap;
}

.cookie__text {
  flex: 1 1 22rem;
  margin: 0;
  font-size: var(--fs-sm);
  line-height: 1.5;
  color: var(--ink-2);
}

.cookie__text a {
  color: var(--asp-teal-light);
}

.cookie__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

/* Третья кнопка не должна спорить за внимание с первыми двумя: она ведёт
   не к решению, а к выбору его состава. */
.btn--quiet {
  border-color: transparent;
  background: none;
  color: var(--ink-2);
}

.btn--quiet:hover {
  border-color: var(--line-strong);
  color: var(--ink);
}

.cookie__tune {
  margin-top: 1rem;
  padding-top: 1rem;
  border-top: 1px solid var(--line);
}

.cookie__cats {
  list-style: none;
  margin: 0 0 1rem;
  padding: 0;
  display: grid;
  gap: 0.75rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
}

.cookie__cats li {
  padding: 0.875rem 1rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: rgb(255 255 255 / 4%);
}

.cookie__cats label {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  /* 44 px тач-цели набираем самой строкой: галочку жмут пальцем. */
  min-height: 44px;
  cursor: pointer;
}

.cookie__cats input:disabled {
  cursor: default;
}

.cookie__cats li:has(input:disabled) label {
  cursor: default;
}

.cookie__cats b {
  font-size: var(--fs-sm);
}

.cookie__cats span {
  display: block;
  font-size: var(--fs-xs);
  line-height: 1.45;
  color: var(--ink-muted);
}

/* На телефоне панель поднимаем над липкими кнопками: иначе «Принять все»
   и «Позвонить» оказываются друг на друге. */
@media (max-width: 900px) {
  .cookie {
    bottom: calc(3.5rem + env(safe-area-inset-bottom, 0px));
  }

  .cookie__actions .btn {
    flex: 1 1 auto;
    justify-content: center;
  }
}

/* Кнопка, которая ведёт себя как ссылка: повторный выбор в подвале — это
   не действие на странице, а вызов того же баннера. */
.foot__link {
  min-height: 44px;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 0.25em;
  cursor: pointer;
}

.foot__link:hover {
  color: var(--asp-teal);
}


/* ══ Липкая панель действий на телефоне ══════════════════════════════════════
   Мобильный посетитель решает «позвонить или закрыть», и кнопка звонка не
   должна уезжать вверх вместе со страницей. На десктопе панель не нужна:
   телефон и кнопка брони и так стоят в шапке. */

.dock {
  position: fixed;
  inset: auto 0 0;
  z-index: var(--z-top, 200);
  display: none;
  gap: 0.5rem;
  padding: 0.5rem 0.75rem;
  /* Без safe-area на iPhone кнопки уезжают под системную полосу — это прямая
     грабля из разбора прошлого проекта. */
  padding-bottom: calc(0.5rem + env(safe-area-inset-bottom, 0px));
  background: rgb(10 15 28 / 92%);
  border-top: 1px solid var(--line);
  backdrop-filter: blur(14px);
}

.dock__btn {
  flex: 1 1 0;
  /* 44 px — минимум по WCAG, 48 — уже комфортно пальцу. */
  min-height: 48px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.5rem 0.75rem;
  border-radius: var(--radius);
  font-size: var(--fs-sm);
  font-weight: 600;
  line-height: 1.2;
  text-decoration: none;
}

.dock__icon {
  width: 1.125rem;
  height: 1.125rem;
  flex: none;
}

.dock__btn--call {
  background: var(--asp-blue-deep);
  color: #fff;
}

.dock__btn--book {
  background: rgb(255 255 255 / 8%);
  border: 1px solid var(--line-strong);
  color: var(--ink);
}

.dock__btn:active {
  transform: scale(0.98);
}

@media (max-width: 900px) {
  .dock {
    display: flex;
  }
  /* Панель перекрывает низ страницы — освобождаем под неё место, иначе
     последняя строка подвала оказывается под кнопками. */
  body {
    padding-bottom: calc(4rem + env(safe-area-inset-bottom, 0px));
  }
}

/* ══ Вопросы ═════════════════════════════════════════════════════════════════
   На <details> без скрипта: раскрытие — штатное поведение браузера, работает
   с клавиатуры и читается скринридером без дополнительной разметки ролей. */

.faq {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.75rem;
  max-width: 52rem;
}

.faq__item {
  border: 1px solid var(--lt-line);
  border-radius: var(--radius-lg);
  background: var(--lt-bg-2);
  overflow: hidden;
}

.faq summary {
  /* 48 px тач-цели набираются паддингом, а не «примерно». */
  min-height: 48px;
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: 1rem 1.25rem;
  font-weight: 600;
  color: var(--lt-ink);
  cursor: pointer;
  list-style: none;
}

.faq summary::-webkit-details-marker {
  display: none;
}

/* Плюс превращается в минус поворотом — одна фигура вместо двух иконок. */
.faq summary::after {
  content: '';
  flex: none;
  width: 0.75rem;
  height: 0.75rem;
  margin-left: auto;
  background: currentColor;
  clip-path: polygon(45% 0, 55% 0, 55% 45%, 100% 45%, 100% 55%, 55% 55%, 55% 100%, 45% 100%, 45% 55%, 0 55%, 0 45%, 45% 45%);
  transition: transform var(--dur) var(--ease-out-quart);
}

.faq details[open] summary::after {
  transform: rotate(45deg);
}

.faq summary:focus-visible {
  outline: 2px solid var(--asp-blue-deep);
  outline-offset: -2px;
}

.faq details p {
  margin: 0;
  padding: 0 1.25rem 1.25rem;
  max-width: 60ch;
  color: var(--lt-ink-2);
}

/* ══ Бронирование: четыре шага ═══════════════════════════════════════════════
   Колонки разделены линиями, а не карточками: это одна последовательность,
   и рамки вокруг каждого шага разбили бы её на четыре независимых блока.
   Короткая градиентная черта поверх линии отмечает начало шага. */

.steps {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: clamp(1.25rem, 2.5vw, 2rem);
  grid-template-columns: 1fr;
  counter-reset: step;
}

.steps__item {
  position: relative;
  padding-top: clamp(1rem, 2vw, 1.5rem);
  border-top: 1px solid var(--line);
}

.steps__item::before {
  content: '';
  position: absolute;
  top: -1px;
  left: 0;
  width: 3rem;
  height: 2px;
  background: linear-gradient(90deg, var(--asp-teal), var(--asp-blue));
}

/* Кадр идёт первым в колонке: так все четыре выравниваются по верху,
   а разная длина текста под ними уже ничего не сдвигает. Пропорция
   вытянутая — шаг это пояснение, а не витрина, и высокий кадр отодвинул бы
   сам текст на второй экран. */
/* Рамка нужна не для красоты: внутри неё кадр приближается под курсором
   и въезжает при появлении, не задевая соседние колонки. */
.steps__frame {
  display: block;
  overflow: hidden;
  margin-bottom: var(--space-4);
  border-radius: var(--radius);
  border: 1px solid var(--line);
  transition: border-color var(--dur) var(--ease-out-quart),
    transform var(--dur) var(--ease-out-quart);
}

.steps__shot {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  transition: transform 520ms var(--ease-out-quart);
}

/* Кадр второго шага почти квадратный: при обрезке по центру верх монитора
   уходил за границу. Прижимаем к верхнему краю. */
.steps__shot--top {
  object-position: center top;
}

@media (hover: hover) {
  .steps__item:hover .steps__frame {
    border-color: var(--asp-teal);
    transform: translateY(-3px);
  }

  .steps__item:hover .steps__shot {
    transform: scale(1.05);
  }
}

.steps__num {
  margin: 0 0 var(--space-3);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--asp-teal);
  font-variant-numeric: tabular-nums;
}

.steps__item h3 {
  margin: 0 0 0.5rem;
  font-size: var(--fs-base);
}

.steps__item p:last-child {
  margin: 0;
  font-size: var(--fs-sm);
  line-height: 1.5;
  color: var(--ink-2);
}

/* Появление шага: сначала едет вся колонка (общий механизм), а внутри неё
   отдельно всплывает кадр и дорисовывается черта над шагом. Простого
   подъёма на 18 пикселей на блоке с четырьмя фотографиями не видно —
   глазу нужно, чтобы двигалось то, на что он смотрит. */
[data-reveal] .steps__item .steps__frame {
  opacity: 0;
  transform: translateY(14px) scale(1.04);
}

[data-reveal] .steps__item::before {
  transform: scaleX(0);
  transform-origin: left center;
}

[data-reveal] .steps__item.is-in .steps__frame {
  opacity: 1;
  transform: none;
  transition: opacity 700ms var(--ease-out-quart),
    transform 700ms var(--ease-out-quart);
  /* Кадр трогается чуть позже своей колонки — иначе движение сливается
     в одно и читается как рывок. */
  transition-delay: calc(var(--i, 0) * var(--step, 70ms) + 110ms);
}

[data-reveal] .steps__item.is-in::before {
  transform: none;
  transition: transform 620ms var(--ease-out-quart);
  transition-delay: calc(var(--i, 0) * var(--step, 70ms));
}

/* Просьбу «меньше движения» уважаем: кадр просто стоит на месте. */
@media (prefers-reduced-motion: reduce) {
  .steps__frame,
  .steps__shot {
    transition: border-color var(--dur) var(--ease-out-quart);
  }

  .steps__item:hover .steps__frame,
  .steps__item:hover .steps__shot {
    transform: none;
  }
}

@media (min-width: 40rem) {
  .steps {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* Вертикальные разделители появляются только в четыре колонки: при переносе
   строки линия слева оказалась бы в начале ряда и читалась бы как ошибка. */
@media (min-width: 64rem) {
  .steps {
    --step-pad: clamp(1rem, 2vw, 1.75rem);
    grid-template-columns: repeat(4, minmax(0, 1fr));
    column-gap: 0;
    /* Отступ внутри колонок одинаковый — иначе первая шире прочих и снимок
       в ней выше. Чтобы она при этом начиналась вровень с заголовком
       раздела, весь список сдвигаем влево ровно на этот отступ. */
    margin-inline: calc(-1 * var(--step-pad));
  }

  .steps__item {
    padding-inline: var(--step-pad);
    padding-bottom: clamp(1.5rem, 3vw, 2.5rem);
  }

  .steps__item + .steps__item {
    border-left: 1px solid var(--line);
  }

  .steps__item::before {
    left: var(--step-pad);
  }
}


/* ══ Вопросы: две колонки ════════════════════════════════════════════════════
   Слева заголовок и переход к форме, справа сам список. На узком экране
   колонки складываются, и текст идёт перед вопросами — так же, как читается
   на широком. */

.faq__split {
  display: grid;
  gap: clamp(1.5rem, 4vw, 3.5rem);
  align-items: start;
}

@media (min-width: 60rem) {
  .faq__split {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
  }
}

.faq__intro {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-4);
}

.faq__intro h2 {
  margin: 0;
  max-width: 16ch;
}

.faq__intro .lead {
  margin: 0;
  max-width: 40ch;
}

/* ── Тёмный вариант списка ───────────────────────────────────────────────────
   Раздел переехал в тёмную часть страницы, а карточки были свёрстаны под
   светлую: белый лист на тёмном фоне выглядел бы заплаткой. */

.act--dark .faq {
  max-width: none;
}

.act--dark .faq__item {
  border-color: var(--glass-line);
  background: var(--glass-bg);
  transition: border-color var(--dur) var(--ease-out-quart);
}

.act--dark .faq__item:has(details[open]) {
  border-color: rgb(29 233 182 / 45%);
}

.act--dark .faq summary {
  color: var(--ink);
}

.act--dark .faq details p {
  color: var(--ink-2);
}

.act--dark .faq summary:focus-visible {
  outline-color: var(--asp-teal);
}

/* Плюс в кружке, как в макете. Кружок рисуем самой меткой, а знак — двумя
   полосами внутри неё: отдельная фигура потребовала бы второго
   псевдоэлемента, а он у строки уже занят. */
.act--dark .faq summary::after {
  width: 1.75rem;
  height: 1.75rem;
  clip-path: none;
  border: 1px solid var(--glass-line);
  border-radius: 50%;
  color: var(--asp-teal-light);
  background:
    linear-gradient(currentColor, currentColor) center / 0.625rem 1px no-repeat,
    linear-gradient(currentColor, currentColor) center / 1px 0.625rem no-repeat;
}

/* Открытый вопрос помечаем минусом, а не крестом: поворот плюса на 45°
   означал бы «закрыть», а не «свернуть». */
.act--dark .faq details[open] summary::after {
  transform: none;
  background: linear-gradient(currentColor, currentColor) center / 0.625rem 1px no-repeat;
}


/* ══ Калькулятор аренды ══════════════════════════════════════════════════════
   Одна карточка: шапка, поля, полоса итога, сноски. Раньше это были три
   независимые колонки, и блок не читался как единый инструмент — глаз не
   понимал, где он начинается и где кончается.

   Считает страница, бронирует Битрикс. Поэтому здесь нет ни одного поля
   для контактов: только выбор, сумма и переход к форме брони. */

.calc__fallback {
  max-width: 44ch;
  color: var(--ink-2);
}

/* Карточку показывает только скрипт: без него считать нечем, а пустые поля
   с нулём вместо суммы читаются как поломка, а не как «нужен JavaScript». */
.calc__card {
  display: none;
}

[data-js='on'] .calc__card {
  display: block;
  border: 1px solid var(--glass-line);
  border-radius: clamp(1rem, 2vw, 1.75rem);
  background: var(--glass-bg);
  backdrop-filter: blur(var(--glass-blur));
  overflow: hidden;
}

/* ── Шапка ─────────────────────────────────────────────────────────────────── */

.calc__head {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: clamp(1.25rem, 2.5vw, 1.75rem);
  border-bottom: 1px solid var(--line);
}

.calc__badge {
  flex: none;
  display: grid;
  place-items: center;
  width: 3rem;
  height: 3rem;
  border-radius: var(--radius);
  border: 1px solid rgb(29 233 182 / 28%);
  background: rgb(29 233 182 / 10%);
  color: var(--asp-teal);
}

.calc__badge svg {
  width: 1.5rem;
  height: 1.5rem;
}

.calc__titles {
  display: flex;
  flex-direction: column;
  gap: 0.125rem;
  min-width: 0;
}

.calc__eyebrow {
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

.calc__head h2 {
  margin: 0;
  font-size: clamp(1.25rem, 1rem + 1vw, 1.75rem);
}

/* ── Тело: превью и поля ───────────────────────────────────────────────────── */

.calc__body {
  display: grid;
  gap: clamp(1.25rem, 2.6vw, 2.25rem);
  padding: clamp(1.25rem, 2.5vw, 1.75rem);
}

@media (min-width: 760px) {
  .calc__body {
    grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr);
    align-items: start;
  }
}

/* Превью. Кадры светлые, поэтому рамка и радиус: на тёмной карточке картинка
   должна читаться как снимок товара, а не как дыра в фоне. */
.calc__shot {
  margin: 0;
  display: flex;
  flex-direction: column;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: rgb(255 255 255 / 4%);
}

.calc__shot img {
  display: block;
  width: 100%;
  /* Кадр снят горизонтально, а режется вертикально: конструкция и фигура
     стоят по центру, поэтому обрезаются только пустые поля по бокам.
     Уже 3:4 не берём — фигура начинает уходить за край, а она тут главное. */
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

@media (min-width: 760px) {
  /* 4:3, а не 3:4: при вертикальном кадре превью становилось выше колонки
     полей, и справа от нижней половины картинки зияла пустота. Заодно срез
     мельче — фигура человека точно остаётся в кадре. */
  .calc__shot img {
    aspect-ratio: 4 / 3;
  }
}

.calc__shot img[hidden] {
  display: none;
}

.calc__shot figcaption {
  padding: 0.75rem 1rem;
  border-top: 1px solid var(--line);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--ink);
}

/* ── Поля ──────────────────────────────────────────────────────────────────── */

.calc__fields {
  display: grid;
  gap: clamp(1rem, 2vw, 1.5rem);
  min-width: 0;
}

@media (min-width: 560px) {
  /* Название конструкции длинное («Мобильная промостойка 800 × 380 мм — от
     2 000 ₽»), а срок — это одно число. Делить пополам значило бы обрезать
     первое ради пустоты во втором. */
  .calc__fields {
    grid-template-columns: minmax(0, 1.45fr) minmax(0, 0.55fr);
  }
  .calc__opts {
    grid-column: 1 / -1;
  }
}

.field {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin: 0;
  min-width: 0;
}

.field__label {
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

.field__control {
  /* 48 px тач-цели набираются паддингом, а не «примерно». */
  min-height: 48px;
  width: 100%;
  padding: 0.75rem 1rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: rgb(255 255 255 / 5%);
  color: var(--ink);
  font: inherit;
  /* Тёмная тема для родных стрелок списка и счётчика поля числа. */
  color-scheme: dark;
}

/* Раскрытый список рисует не страница, а браузер поверх неё. Наш светлый
   текст доставался пунктам по наследству, а фон окна оставался белым —
   получалось светлое по светлому, читался только пункт под курсором.

   Лечим двумя способами сразу, потому что платформы ведут себя по-разному:
   color-scheme выше просит у браузера тёмное окно (это работает в macOS,
   где список системный и стилям не поддаётся), а явный фон у пунктов
   срабатывает в Chrome под Windows и Linux. */
.field__control option {
  background: var(--bg-deep);
  color: var(--ink);
}

.field__control:focus-visible {
  outline: 2px solid var(--asp-teal);
  outline-offset: 2px;
  border-color: transparent;
}

.field__hint {
  font-size: var(--fs-xs);
  color: var(--ink-muted);
}

/* ── Дополнительные услуги ─────────────────────────────────────────────────── */

.calc__opts {
  display: flex;
  flex-wrap: wrap;
  gap: 0.625rem;
  margin: 0;
  padding: 0;
  border: 0;
  min-width: 0;
}

.calc__opts legend {
  padding: 0 0 0.625rem;
  /* legend не участвует в раскладке flex-контейнера, поэтому ширину задаём
     сами — иначе плашки встают в одну строку с заголовком. */
  float: left;
  width: 100%;
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 48px;
  padding: 0.625rem 1rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: rgb(255 255 255 / 4%);
  font-size: var(--fs-sm);
  color: var(--ink-2);
  cursor: pointer;
  transition: border-color var(--dur) var(--ease-out-quart),
    background var(--dur) var(--ease-out-quart),
    color var(--dur) var(--ease-out-quart);
}

.chip input {
  flex: none;
  width: 1.0625rem;
  height: 1.0625rem;
  accent-color: var(--asp-teal);
}

.chip:has(input:checked) {
  border-color: rgb(29 233 182 / 42%);
  background: rgb(29 233 182 / 10%);
  color: var(--ink);
}

.chip:has(input:focus-visible) {
  outline: 2px solid var(--asp-teal);
  outline-offset: 2px;
}

/* ── Полоса итога ──────────────────────────────────────────────────────────── */

.calc__sum {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-5);
  align-items: center;
  justify-content: space-between;
  padding: clamp(1.25rem, 2.5vw, 1.75rem);
  border-top: 1px solid var(--line);
  background: linear-gradient(
    100deg,
    rgb(41 121 255 / 12%),
    rgb(29 233 182 / 8%) 70%,
    transparent
  );
}

.calc__sum-main {
  min-width: 0;
}

.calc__total-num {
  margin: 0.25rem 0 0.5rem;
  font-size: clamp(2rem, 1.3rem + 3vw, 3rem);
  font-weight: 600;
  line-height: 1.02;
  letter-spacing: -0.02em;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

.calc__meta {
  margin: 0;
  max-width: 60ch;
  font-size: var(--fs-sm);
  line-height: 1.5;
  color: var(--ink-muted);
}

.calc__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin: 0;
}

/* ── Сноски ────────────────────────────────────────────────────────────────── */

.calc__notes {
  display: flex;
  flex-direction: column;
  gap: 0.625rem;
  padding: clamp(1.25rem, 2.5vw, 1.75rem);
  border-top: 1px solid var(--line);
}

.calc__notes p {
  margin: 0;
  max-width: 80ch;
  font-size: var(--fs-sm);
  line-height: 1.6;
  color: var(--ink-muted);
}

.calc__notes b {
  color: var(--ink-2);
}

/* Строка с реквизитами нужна только на бумаге: распечатанный расчёт без
   контактов бесполезен — по нему потом звонят. */
.calc__print-only {
  display: none;
}

/* ══ Печать расчёта ══════════════════════════════════════════════════════════
   Кнопка «Скачать расчёт» вызывает печать страницы, а браузер предлагает
   сохранить в PDF.

   Первая попытка была на visibility: hidden — и это ошибка: невидимое
   содержимое сохраняет высоту, поэтому в PDF уезжало пятнадцать тысяч
   пикселей тёмного фона, а сама карточка сжималась в полоску наверху.
   Нужен display: none — он схлопывает и высоту тоже.

   Прячем по уровням: сначала всё в body, потом всё в main, затем возвращаем
   только секцию расчёта. Так новый раздел на странице не потребует правки
   этих стилей — он спрячется сам. */

@media print {
  html,
  body {
    height: auto;
    background: #fff;
    color: #131a2d;
  }

  body > *,
  #main > * {
    display: none !important;
  }

  body > #main,
  #main > #calc {
    display: block !important;
  }

  /* Секция расчёта на бумаге — просто карточка, без фона и отступов страницы. */
  #calc {
    padding: 0 !important;
    background: none !important;
  }

  #calc .act__aurora {
    display: none !important;
  }

  #calc .container {
    max-width: none !important;
    padding: 0 !important;
  }

  [data-js='on'] .calc__card {
    border: 1px solid #d5e4f6;
    border-radius: 0;
    background: #fff;
    backdrop-filter: none;
  }

  /* На бумаге тёмная тема стоила бы половину картриджа. */
  .calc__head h2,
  .calc__total-num,
  .calc__shot figcaption,
  .calc__notes b {
    color: #131a2d;
  }

  .calc__eyebrow,
  .field__label,
  .field__hint,
  .calc__meta,
  .calc__notes p {
    color: #4a5a76;
  }

  .calc__head,
  .calc__sum,
  .calc__notes,
  .calc__shot,
  .calc__shot figcaption {
    border-color: #d5e4f6;
  }

  .calc__sum {
    background: #f2f7fd;
  }

  .calc__badge {
    border-color: #bfe9df;
    background: #eafaf5;
    color: #00806e;
  }

  /* Кнопки на бумаге бессмысленны, поля выбора — тоже: расчёт уже сделан,
     и всё выбранное перечислено строкой под суммой. */
  .calc__actions,
  .calc__fields {
    display: none !important;
  }

  /* Освободившееся место отдаём превью — оно единственное, что осталось. */
  .calc__body {
    grid-template-columns: minmax(0, 1fr) !important;
  }

  .calc__shot {
    max-width: 22rem;
  }

  .calc__print-only {
    display: block;
  }
}


/* ── Доказательства рядом с решением ─────────────────────────────────────────
   Не отдельным разделом «почему мы», а там, где человек нажимает кнопку.
   Всё перечисленное проверяемо: год, парк, документы, реквизиты. */

.calc__proof {
  flex-basis: 100%;
  font-size: var(--fs-sm);
  color: var(--ink-muted);
}

/* Проверяемые факты — плашками, а не текстом в столбик. Без границ
   четыре факта, пояснение и контакты шли одним потоком одинакового веса,
   и глазу было не за что зацепиться. */
.proof {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(45%, 11rem), 1fr));
  gap: 0.625rem;
}

.proof li {
  padding: 0.875rem 1rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: rgb(255 255 255 / 4%);
}

.proof__icon {
  display: block;
  width: 1.25rem;
  height: 1.25rem;
  margin-bottom: 0.625rem;
  color: var(--asp-teal);
}

.proof b {
  display: block;
  font-size: var(--fs-sm);
  font-weight: 600;
  line-height: 1.25;
  color: var(--ink);
}

.proof span {
  display: block;
  margin-top: 0.125rem;
  font-size: var(--fs-xs);
  line-height: 1.45;
  color: var(--ink-muted);
}

/* ── Логотипы клиентов ───────────────────────────────────────────────────────
   Пока их нет, раздел не должен занимать место и обещать содержание. */

.clients:has(.clients__list:empty) {
  display: none;
}

/* Заголовок работает подписью, а не заголовком: в образце это строчка
   вразрядку над полосой. Уровень h2 при этом сохраняем — для читалки
   и поисковика раздел остаётся разделом. */
.clients__head {
  margin-bottom: clamp(2rem, 5vw, 3.25rem);
  text-align: center;
}

.clients__eyebrow {
  margin: 0 0 var(--space-3);
  font-size: var(--fs-sm);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--asp-teal);
}

.clients__sub {
  margin: 0;
  font-size: var(--fs-sm);
  color: var(--ink-muted);
}

.clients__list {
  --logo-h: clamp(2.25rem, 4vw, 3.5rem);
  list-style: none;
  margin: 0;
  padding: 0;
  /* Не сетка: в образце ряды разной длины и каждый по центру. Колонки
     одинаковой ширины растягивали бы короткие знаки пустотой по бокам,
     а длинные поджимали. */
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: clamp(1.5rem, 3vw, 2.25rem) clamp(2rem, 5vw, 3.5rem);
}

.clients__list li {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: min(100%, 10.5rem);
  min-height: var(--logo-h);
}

.clients__list img {
  display: block;
  width: auto;
  height: auto;
  max-width: var(--logo-w, 9.5rem);
  max-height: var(--logo-h);
  object-fit: contain;
  /* Логотипы приходят разноцветными и рвут ритм полосы. Приглушаем, но
     возвращаем цвет под курсором — так видно, что это настоящие компании. */
  filter: grayscale(1);
  opacity: 0.75;
  transition: filter var(--dur) var(--ease-out-quart),
    opacity var(--dur) var(--ease-out-quart);
}

@media (hover: hover) {
  .clients__list img:hover {
    filter: none;
    opacity: 1;
  }
}

/* На тёмной полосе цвет вернуть некуда: почти все знаки чёрные и на этом
   фоне просто исчезнут. brightness(0) кладёт знак в чистый чёрный,
   invert(1) поднимает его в белый — прозрачность при этом цела, поэтому
   получается ровный силуэт. Под курсором добавляем яркости, а не цвета. */
.act--dark .clients__list img {
  filter: grayscale(1) invert(1) brightness(1.15);
  opacity: 0.72;
}

@media (hover: hover) {
  .act--dark .clients__list img:hover {
    filter: grayscale(1) invert(1) brightness(1.15);
    opacity: 1;
  }
}


/* ── Выход из сцены ──────────────────────────────────────────────────────────
   Появляется на месте подсказки «Листайте», когда та гаснет. Видимость ведёт
   скрипт: она привязана к прогрессу прокрутки, а не к таймеру — иначе кнопка
   всплывала бы у того, кто уже пролистал сцену насквозь. */

.skipscene {
  position: absolute;
  left: 50%;
  bottom: 1.25rem;
  z-index: var(--z-top, 200);
  transform: translateX(-50%);
  /* 44 px — минимум по WCAG для тач-цели. */
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.625rem 1.125rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-pill);
  background: rgb(10 15 28 / 72%);
  backdrop-filter: blur(10px);
  font-size: var(--fs-sm);
  color: var(--ink-2);
  text-decoration: none;
  opacity: var(--skip, 0);
  /* При нулевой прозрачности кнопка не должна ловить клики: она невидима,
     но лежит поверх сцены. */
  pointer-events: none;
  transition: color var(--dur) var(--ease-out-quart),
    border-color var(--dur) var(--ease-out-quart);
}

.skipscene::after {
  content: '↓';
  font-size: 1em;
  line-height: 1;
}

.skipscene:hover,
.skipscene:focus-visible {
  color: var(--ink);
  border-color: var(--asp-teal);
}

/* Без скрипта прогресса нет, значит нет и сцены — обходить нечего. */
:root:not([data-motion='on']) .skipscene {
  display: none;
}


/* Плашка-справка: услуга есть, но платить за неё отдельно не надо — она
   входит в другую строку заказа. Отличается от выключенной именно тем,
   что её не предлагают выбрать. */
.chip:has(input:disabled) {
  cursor: default;
  border-style: dashed;
  color: var(--ink-muted);
}

.chip input:disabled {
  opacity: 0.4;
}

/* ══ Каталог: подбор по задаче ═══════════════════════════════════════════════ */

.act__eyebrow {
  margin: 0 0 var(--space-3);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  /* Не бирюзовый: #00bfa5 на светлом фоне даёт 2,33:1 при норме 4,5 — мелкий
     текст в 12 px этого не прощает. Брендовый синий даёт 6,3:1 и остаётся
     акцентом, а не превращается в серую подпись. */
  color: var(--asp-blue-deep);
}

/* Кнопки фильтра показываются только при работающем скрипте: фильтровать
   иначе нечем, а неработающие кнопки хуже, чем их отсутствие. Карточки
   при этом видны все — содержимое не теряется. */
.cat__tasks {
  display: none;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: var(--space-6);
}

[data-js='on'] .cat__tasks {
  display: flex;
}

/* Тот же класс, что у услуг в расчёте, но на светлой секции: плашка должна
   выглядеть одинаково по всей странице, а не по-разному в каждом блоке. */
.chip--task {
  border-color: var(--lt-line);
  background: var(--lt-bg-2);
  color: var(--lt-ink-2);
  font-weight: 500;
}

.chip--task:hover {
  border-color: var(--asp-teal-deep);
  color: var(--lt-ink);
}

.chip--task[aria-pressed='true'] {
  border-color: var(--asp-teal-deep);
  background: rgb(0 191 165 / 10%);
  color: var(--lt-ink);
  font-weight: 600;
}

.chip--task:focus-visible {
  outline: 2px solid var(--asp-blue-deep);
  outline-offset: 2px;
}

.cat__empty {
  margin: 0 0 var(--space-6);
  max-width: 52ch;
  color: var(--lt-ink-muted);
}

/* Переход в расчёт. Не кнопка: это перемещение по странице, а не действие,
   и выглядеть оно должно ссылкой. */
.cat__pick {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  /* 44 px тач-цели набираем высотой строки, а не отступом сверху: иначе
     ссылка отрывается от нижней кромки карточки. */
  min-height: 44px;
  font-size: var(--fs-sm);
  font-weight: 600;
  white-space: nowrap;
  color: var(--asp-blue-deep);
  text-decoration: none;
}

.cat__pick::after {
  content: '→';
}

.cat__pick:hover {
  text-decoration: underline;
  text-underline-offset: 0.25em;
}

/* Скрытые фильтром карточки убираем из сетки целиком, иначе grid оставит
   от них пустые ячейки. */
.cat__item[hidden] {
  display: none;
}

/* ══ Полный цикл и доверие ═══════════════════════════════════════════════════
   Два раздела на одних и тех же плашках. Всё оформление, наведение и
   появление берутся от общего .tile — здесь только раскладка: в первом
   экране плашки стоят узкой колонкой рядом с моделью, а тут занимают
   ширину раздела. */

.tiles--wide {
  width: 100%;
  gap: clamp(0.75rem, 1.5vw, 1.25rem);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
}

.tiles--wide .tile {
  display: flex;
  flex-direction: column;
  padding: clamp(1.125rem, 1.8vw, 1.5rem);
}

/* Заголовок и текст разводим воздухом, а не отступом у абзаца: плашки
   разной высоты, и текст должен начинаться на одной линии. */
.tiles--wide .tile__icon {
  margin-bottom: clamp(1.5rem, 3vw, 2.25rem);
}

.tiles--wide .tile h3 {
  margin: 0 0 0.5rem;
}

/* ── Светлый вариант ─────────────────────────────────────────────────────────
   Бирюзовая пиктограмма на белом даёт 1,4:1 — на тёмном она акцент, здесь
   превратилась бы в бледное пятно. Берём тот же брендовый синий, что
   у надзаголовка раздела. */

.act--light .tile {
  background: var(--lt-bg-2);
  border-color: var(--lt-line);
  backdrop-filter: none;
}

.act--light .tile__icon {
  color: var(--asp-blue-deep);
}

@media (hover: hover) {
  .act--light .tile:hover {
    border-color: var(--asp-blue);
    background: var(--lt-bg-2);
  }
}

.act--light .badges li {
  border-color: var(--lt-line);
  background: var(--lt-bg-2);
}

/* ── Панельный выбор снимков ─────────────────────────────────────────────────
   Формат по образцу заказчика: панели стоят в ряд, активная раскрывается
   на семь долей, остальные держатся узкими полосами со значком. Подпись
   выезжает только у раскрытой — на полосе шириной в значок ей всё равно
   негде поместиться.

   Раскрытие ведёт скрипт, но начальное состояние живёт в разметке: первая
   панель помечена активной, и без скрипта раздел остаётся крупным снимком
   с четырьмя полосами, а не пятью одинаковыми щелями. */

.trust__shots {
  --pick-h: clamp(17rem, 32vw, 25rem);
  list-style: none;
  margin: 0 0 clamp(1.5rem, 3vw, 2.5rem);
  padding: 0;
  display: flex;
  gap: 0.375rem;
  height: var(--pick-h);
}

.trust__shots:empty {
  display: none;
}

.trust__shots li {
  position: relative;
  flex: 1 1 0;
  min-width: 3.5rem;
  overflow: hidden;
  border-radius: var(--radius-lg);
  border: 1px solid var(--line);
  background: var(--bg-deep);
  transition: flex-grow 700ms var(--ease-out-quart),
    border-color 700ms var(--ease-out-quart),
    box-shadow 700ms var(--ease-out-quart);
}

.trust__shots li.is-active {
  flex-grow: 7;
  border-color: var(--asp-blue);
  box-shadow: 0 20px 60px rgb(10 20 40 / 22%);
}

/* Кнопка занимает панель целиком: нажимать нужно по снимку, а не по метке. */
.pick__btn {
  display: block;
  width: 100%;
  height: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  text-align: left;
}

.pick__btn:focus-visible {
  outline: 2px solid var(--asp-teal);
  outline-offset: -4px;
}

.trust__shots img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Свёрнутая панель показывает снимок крупнее: в полосе шириной в значок
     общий план не читается, а фрагмент — читается. */
  transform: scale(1.12);
  transition: transform 700ms var(--ease-out-quart);
}

.is-active .trust__shots img,
.trust__shots li.is-active img {
  transform: none;
}

.pick__scrim {
  position: absolute;
  inset: auto 0 0;
  height: 60%;
  pointer-events: none;
  background: linear-gradient(to top, rgb(6 10 20 / 88%), rgb(6 10 20 / 0%));
  opacity: 0.5;
  transition: opacity 700ms var(--ease-out-quart);
}

.trust__shots li.is-active .pick__scrim {
  opacity: 1;
}

.pick__label {
  position: absolute;
  inset: auto 0 1rem;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding-inline: 0.75rem;
  pointer-events: none;
}

.pick__icon {
  flex: none;
  display: grid;
  place-items: center;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 50%;
  border: 1px solid rgb(255 255 255 / 24%);
  background: rgb(16 22 34 / 82%);
  backdrop-filter: blur(10px);
  color: #fff;
}

.pick__icon svg {
  width: 1.125rem;
  height: 1.125rem;
}

/* Подпись выезжает вместе с раскрытием. Не переносим её по словам: пока
   панель едет, перенос дёргал бы текст на каждом кадре. */
.pick__text {
  min-width: 0;
  white-space: nowrap;
  color: #fff;
  opacity: 0;
  transform: translateX(1.5rem);
  transition: opacity 700ms var(--ease-out-quart),
    transform 700ms var(--ease-out-quart);
}

.trust__shots li.is-active .pick__text {
  opacity: 1;
  transform: none;
}

.pick__text b {
  display: block;
  font-size: var(--fs-base);
  font-weight: 700;
  line-height: 1.2;
}

.pick__text span {
  display: block;
  font-size: var(--fs-sm);
  color: rgb(255 255 255 / 78%);
}

/* На узком экране гармошка бессмысленна: раскрытая панель всё равно шириной
   в экран, а свёрнутые — в палец. Раскладываем снимки столбцом и показываем
   все подписи сразу. */
@media (max-width: 47.99rem) {
  .trust__shots {
    flex-direction: column;
    height: auto;
    gap: 0.625rem;
  }

  .trust__shots li {
    flex: none;
    height: clamp(9rem, 42vw, 13rem);
  }

  .trust__shots li,
  .trust__shots li.is-active {
    border-color: var(--line);
    box-shadow: none;
  }

  .trust__shots img {
    transform: none;
  }

  .trust__shots .pick__scrim {
    opacity: 1;
  }

  .trust__shots .pick__text {
    opacity: 1;
    transform: none;
    white-space: normal;
  }
}

@media (prefers-reduced-motion: reduce) {
  .trust__shots li,
  .trust__shots img,
  .pick__scrim,
  .pick__text {
    transition-duration: 1ms;
  }
}

/* ── Метки документов ────────────────────────────────────────────────────────
   Намеренно не кнопки и не .chip: нажимать тут нечего, а вид кнопки обещал бы
   действие. Поэтому рамка тоньше, фон спокойнее и никакого поведения
   под курсором. */

.badges__lead {
  margin: clamp(1.25rem, 2.5vw, 2rem) 0 var(--space-3);
  font-size: var(--fs-sm);
  color: var(--ink-muted);
}

.badges {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.badges li {
  padding: 0.4rem 0.875rem;
  border: 1px solid var(--glass-line);
  border-radius: var(--radius-pill);
  background: var(--glass-bg);
  font-size: var(--fs-sm);
  color: var(--ink-2);
}


/* ══ Условия аренды ══════════════════════════════════════════════════════════
   Две колонки: слева заявление и переход в расчёт, справа список условий
   строками. Каждая цифра здесь — из прайса или из раздела «Как проходит
   аренда», а не из головы. */

.conds {
  display: grid;
  gap: clamp(1.5rem, 4vw, 3.5rem);
  padding: clamp(1.5rem, 4vw, 3rem);
  border: 1px solid var(--glass-line);
  border-radius: clamp(1rem, 2vw, 1.75rem);
  background: var(--glass-bg);
  backdrop-filter: blur(var(--glass-blur));
}

@media (min-width: 60rem) {
  .conds {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
    align-items: start;
  }
}

.conds__text {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.conds__text h2 {
  margin: 0;
  max-width: 14ch;
}

.conds__text .lead {
  margin: 0;
  max-width: 46ch;
}

/* На тёмном фоне синий из светлой темы читается плохо — берём бирюзу. */
.act__eyebrow--dark {
  color: var(--asp-teal);
}

.conds__link {
  align-self: flex-start;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  font-weight: 600;
  color: var(--asp-teal-light);
  text-decoration: underline;
  text-underline-offset: 0.3em;
  text-decoration-thickness: 1px;
}

.conds__link:hover {
  color: var(--ink);
}

.conds__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.conds__list li {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.875rem 1.125rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: rgb(255 255 255 / 4%);
  font-size: var(--fs-sm);
}

.conds__list span {
  color: var(--ink-2);
}

.conds__list b {
  flex: none;
  font-weight: 600;
  color: var(--asp-teal-light);
  font-variant-numeric: tabular-nums;
}
