/* ==========================================================================
   S4Y — витрина выкупа On из Бангкока
   Дизайн-система: токены → примитивы → компоненты → секции.

   Визуальная идея: не «белый лист + чёрный гротеск + большой кроссовок», а
   диспетчерская выкупа. Тёмный чернильный фон как основа, тёплая бумага для
   чтения, вермилион для действия и служебный «операционный» слой (нумерация,
   моноширинные метки, тонкие линии) — он и создаёт ощущение процесса, за
   которым стоит живой человек.

   Кроссовки On в подавляющем большинстве светлые, поэтому карточки стоят на
   цветных подложках: на бумажном фоне белая пара исчезает.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Токены
   -------------------------------------------------------------------------- */
:root {
  /* Чернила и бумага */
  --ink:        #0B0D0F;
  --ink-2:      #14181C;
  --ink-3:      #1E242A;
  --ink-4:      #2C343B;
  --paper:      #F4F1EB;
  --paper-2:    #EAE5DC;
  --paper-3:    #DCD5C8;

  /* Действие и статусы */
  --signal:     #FF4A17;
  /* Кольцо фокуса. Отдельным значением, а не `color-mix()` на месте: у кольца
     один цвет на всю витрину, и он обязан быть проверяемым — вычисленный вид
     `color-mix()` зависит от браузера и сверке не поддаётся. */
  --signal-ring: rgba(255, 74, 23, .45);
  --signal-2:   #E23C0C;
  --jade:       #17795E;
  --amber:      #A8720B;
  --slate:      #6B7780;

  /* Текст */
  --text:            var(--ink);
  --text-muted:      #59626A;
  --text-invert:     var(--paper);
  --text-invert-mut: #9AA3AB;

  /* Линии */
  --line:        rgba(11, 13, 15, .14);
  --line-strong: rgba(11, 13, 15, .28);
  --line-invert: rgba(244, 241, 235, .16);

  /* Типографика */
  /* Подменные семейства с подогнанными метриками стоят СРАЗУ за основными
     (015Ac §17): пока woff2 не доехал, текст рисуется ими и занимает столько же
     места. Системные шрифты остаются последним рубежом — на случай, когда нет
     ни одного из перечисленных в `local()`. */
  --font-display: 'Geologica', 'S4Y Display Fallback', 'S4Y Display Fallback 2', 'Segoe UI', system-ui, sans-serif;
  --font-text:    'Golos Text', 'S4Y Text Fallback', 'S4Y Text Fallback 2', 'Segoe UI', system-ui, sans-serif;

  --step--2: clamp(.6875rem, .67rem + .08vw, .75rem);
  --step--1: clamp(.8125rem, .79rem + .1vw, .875rem);
  --step-0:  clamp(1rem, .96rem + .18vw, 1.0625rem);
  --step-1:  clamp(1.125rem, 1.05rem + .35vw, 1.3125rem);
  --step-2:  clamp(1.375rem, 1.2rem + .8vw, 1.75rem);
  --step-3:  clamp(1.75rem, 1.45rem + 1.4vw, 2.5rem);
  --step-4:  clamp(1.875rem, 1.5rem + 1.7vw, 2.875rem);
  --step-5:  clamp(2.5rem, 1.9rem + 2.6vw, 4.25rem);

  /* Ритм */
  --gutter:  clamp(1.125rem, .6rem + 2.6vw, 3.5rem);
  --section: clamp(4.5rem, 3rem + 6vw, 9rem);
  --measure: 62ch;

  /* Форма */
  --radius:    3px;
  --radius-lg: 6px;
  --radius-pill: 999px;

  /* Движение */
  --ease:     cubic-bezier(.4, 0, .2, 1);
  --ease-out: cubic-bezier(.2, .8, .2, 1);
  --fast:     150ms;
  --base:     240ms;
  --slow:     420ms;

  /* Ритм витрины первого экрана (016A §9).

     Показ + переход = период смены кадра. Держать эти числа порознь нельзя:
     «премиально» получается не из длительности показа и не из длительности
     перехода, а из их СУММЫ, и менять их надо парой. Скрипт читает обе величины
     отсюда и складывает — второго набора чисел в проекте нет.

     Было 5 200 + 1 100 ≈ 6,3 с на кадр: обычный посетитель уходил с первого
     экрана раньше, чем успевала произойти первая смена. Стало 2,3 + 0,6 ≈ 2,9 с. */
  --showcase-dwell: 2300ms;
  --showcase-shift: 600ms;

  --header-h: 68px;

  /* Расстояние между блоками полноэкранного меню (017Cab §5…§7).

     Считается от ШИРИНЫ, а не от высоты: ширина при прокрутке не меняется,
     высота на телефоне — меняется вместе с панелями браузера, и расстояние от
     неё зависеть не имеет права. Около 31 px на 390 и 34 px на 430. */
  --menu-gap: clamp(1.75rem, 8vw, 2.75rem);
}

@media (min-width: 60rem) {
  :root { --header-h: 76px; }
}

/* --------------------------------------------------------------------------
   2. Сброс и основа
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* Якорь не должен уезжать под липкую шапку. `--header-h` — ПОЛНАЯ высота
     шапки вместе с нижней границей (017Ca §18), поэтому отступ здесь точный. */
  scroll-padding-top: calc(var(--header-h) + 1.5rem);
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--text);
  font-family: var(--font-text);
  font-size: var(--step-0);
  line-height: 1.55;
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;

  /* Горизонтальный вынос ОБРЕЗАЕТСЯ, а не прячется в прокрутку (017Ca §18).

     `overflow-x: hidden` делает область просмотра прокручиваемой по горизонтали —
     просто без видимой полосы. Прокрутка при этом существует: её можно вызвать
     жестом, инерцией и вызовом из скрипта, и на телефоне именно она даёт
     «дёргание» липкой шапки вбок при диагональном смахивании. `clip` не создаёт
     прокрутку вовсе — ни в одну сторону, — а обрезает ровно так же.

     Запасной вариант нужен: `overflow: clip` появился в Safari 16, а витрина
     обязана оставаться целой и на более старых. Там остаётся прежнее поведение. */
  overflow-x: hidden;
}

@supports (overflow: clip) {
  body { overflow-x: clip; }
}

/* Блокировка прокрутки под оверлеем (меню, панель фильтров, таблица размеров).

   ПОЧЕМУ НЕ ПРОСТО `overflow: hidden` (017Ca §18). На iOS Safari этого мало:
   страница под оверлеем продолжает прокручиваться пальцем, и, закрыв меню,
   покупатель оказывается не там, где его открыл, — то есть «меню смещается».
   Фиксация тела на месте с сохранением позиции прокрутки работает везде
   одинаково; саму позицию возвращает скрипт, он же её и запомнил. */
body.is-locked {
  position: fixed;
  inset-inline: 0;
  width: 100%;
  overflow: hidden;
}

h1, h2, h3, h4 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 700;
  line-height: 1.02;
  letter-spacing: -.028em;
  text-wrap: balance;
}

p { margin: 0; text-wrap: pretty; }
ul, ol { margin: 0; padding: 0; list-style: none; }
/* height: auto обязателен: атрибуты width/height у <img> стоят ради стабильного
   layout (без CLS), но без этого правила они же ломают пропорции и отменяют
   aspect-ratio из CSS. */
img, svg { display: block; max-width: 100%; }
img { height: auto; }
button { font: inherit; color: inherit; }

a { color: inherit; text-decoration: none; }

/* Правило браузера [hidden]{display:none} слабее авторского .card{display:flex},
   поэтому скрытие через атрибут hidden требует !important. */
[hidden] { display: none !important; }

:focus-visible {
  outline: 2px solid var(--signal);
  outline-offset: 3px;
  border-radius: 2px;
}

.skip {
  position: fixed;
  top: .5rem;
  left: .5rem;
  z-index: 200;
  padding: .75rem 1.25rem;
  background: var(--signal);
  color: #fff;
  font-weight: 600;
  border-radius: var(--radius);
  transform: translateY(-160%);
  transition: transform var(--base) var(--ease-out);
}

.skip:focus { transform: none; }

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

/* --------------------------------------------------------------------------
   3. Раскладка
   -------------------------------------------------------------------------- */
.shell {
  width: 100%;
  max-width: 1560px;
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.shell--narrow { max-width: 1180px; }

/* На очень широких экранах полоса контента не должна расползаться. */
@media (min-width: 112.5rem) {
  .shell { max-width: 1680px; }
}

.section { padding-block: var(--section); }
.section--ink { background: var(--ink); color: var(--text-invert); }
.section--tight { padding-block: calc(var(--section) * .62); }

.section__head {
  display: grid;
  gap: clamp(1rem, .5rem + 1.6vw, 2rem);
  margin-bottom: clamp(2rem, 1rem + 3vw, 4rem);
}

@media (min-width: 56.25rem) {
  .section__head--split {
    grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr);
    align-items: end;
    gap: clamp(2rem, 4vw, 5rem);
  }
}

.section__title { font-size: var(--step-4); }
.section__lead {
  max-width: var(--measure);
  color: var(--text-muted);
  font-size: var(--step-1);
}

.section--ink .section__lead { color: var(--text-invert-mut); }

/* Служебная метка — «операционный» слой айдентики */
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  font-family: var(--font-display);
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.section--ink .eyebrow { color: var(--text-invert-mut); }

.eyebrow::before {
  content: '';
  width: 1.75rem;
  height: 1px;
  background: currentColor;
  opacity: .55;
}

.eyebrow--signal { color: var(--signal); }

/* --------------------------------------------------------------------------
   4. Примитивы
   -------------------------------------------------------------------------- */
.btn {
  --btn-bg: var(--ink);
  --btn-fg: var(--paper);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .625rem;
  min-height: 48px;
  padding: .875rem 1.5rem;

  /* ПОДПИСЬ КНОПКИ — КОМАНДА, А НЕ АБЗАЦ (016B, правка владельца).
     Без этого «Написать в Telegram» в узкой колонке ломался на три строки
     («Написать» / «в» / «Telegram»), а кнопка вырастала до 95 px высотой.
     Причина не в самой кнопке: в гибкой раскладке элемент сжимается до своего
     min-content, а min-content текста с переносами — это самое длинное СЛОВО.
     Запрет переноса делает min-content равным всей подписи, и ряд действий
     честно переносит кнопку ЦЕЛИКОМ вместо того, чтобы её раздавить.
     `max-width` оставляет предохранитель: если ширины не хватит даже на одну
     кнопку, она обрежется по контейнеру, а не вытолкнет страницу вбок. */
  white-space: nowrap;
  max-width: 100%;
  background: var(--btn-bg);
  color: var(--btn-fg);
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  font-family: var(--font-display);
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: -.005em;
  cursor: pointer;
  transition: background var(--fast) var(--ease), color var(--fast) var(--ease),
              border-color var(--fast) var(--ease), transform var(--fast) var(--ease);
}

.btn:hover { transform: translateY(-1px); }
.btn:active { transform: translateY(0); }

.btn--signal { --btn-bg: var(--signal); --btn-fg: #fff; }
.btn--signal:hover { --btn-bg: var(--signal-2); }

.btn--ghost {
  --btn-bg: transparent;
  --btn-fg: currentColor;
  border-color: var(--line-strong);
}

.btn--ghost:hover { --btn-bg: rgba(11, 13, 15, .06); }

.hero .btn--ghost,
.section--ink .btn--ghost,
.menu .btn--ghost,
.masthead--over .btn--ghost { border-color: var(--line-invert); }

.hero .btn--ghost:hover,
.section--ink .btn--ghost:hover,
.menu .btn--ghost:hover,
.masthead--over .btn--ghost:hover { --btn-bg: rgba(244, 241, 235, .1); }

.btn--sm { min-height: 40px; padding: .5rem 1.125rem; font-size: var(--step--2); }
.btn--block { width: 100%; }

.btn__arrow { transition: transform var(--base) var(--ease-out); }
.btn:hover .btn__arrow { transform: translateX(3px); }

/* Деньги атомарны: число и знак валюты не разрываются переносом. */
.money {
  white-space: nowrap;
  font-family: var(--font-display);
  font-weight: 600;
  letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
}

.money--lg { font-size: var(--step-2); }

.chip {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  min-height: 34px;
  padding: .3125rem .75rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: .01em;
  white-space: nowrap;
}

.chip__dot {
  width: .5rem;
  height: .5rem;
  border-radius: 50%;
  background: var(--slate);
  flex: none;
}

/* Знак состояния вместо цветной точки (015Ac §21).

   Цветная точка несла ВЕСЬ смысл: для человека, не различающего зелёный и
   серый, «есть» и «нет» выглядели одинаково. Знак читается без цвета, а цвет
   остаётся вторым, подкрепляющим слоем. */
.chip__mark {
  flex: none;
  width: 1.125rem;
  height: 1.125rem;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid currentColor;
  font-size: .6875rem;
  font-weight: 700;
  line-height: 1;
}

/* Отметка «проверено …» рядом с сигналом. Приглушена намеренно: это уточнение к
   состоянию, а не второе состояние. Чипу разрешён перенос — на узком экране
   «Есть у источника · проверено сегодня» иначе выезжает за край. */
.chip__scope { color: var(--text-muted); font-weight: 400; }

.chip__meta {
  color: var(--text-muted);
  font-weight: 400;
  white-space: nowrap;
}

/* Чип с отметкой «проверено …» длиннее обычного и обязан переноситься:
   на 360 px «Есть у источника · проверено сегодня» одной строкой не помещается. */
.pdp__signal,
.bline__chip {
  flex-wrap: wrap;
  white-space: normal;
  row-gap: .125rem;
  max-width: 100%;
}

.chip--ok      { color: var(--jade); border-color: color-mix(in srgb, var(--jade) 34%, transparent); }
.chip--ok      .chip__dot { background: var(--jade); }
.chip--warn    { color: var(--amber); border-color: color-mix(in srgb, var(--amber) 36%, transparent); }
.chip--warn    .chip__dot { background: var(--amber); }
.chip--neutral { color: var(--text-muted); }
.chip--off     { color: var(--slate); opacity: .75; }
.chip--off     .chip__dot { background: transparent; box-shadow: inset 0 0 0 1.5px currentColor; }

.rule { height: 1px; border: 0; margin: 0; background: var(--line); }
.section--ink .rule { background: var(--line-invert); }

/* --------------------------------------------------------------------------
   5. Верхняя строка и шапка
   -------------------------------------------------------------------------- */
.topline {
  background: var(--ink);
  color: var(--text-invert-mut);
  font-size: var(--step--2);
  letter-spacing: .01em;
}

.topline__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  min-height: 34px;
  padding-block: .375rem;
}

.topline__place {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  font-family: var(--font-display);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--paper);
}

.topline__place::before {
  content: '';
  width: .375rem; height: .375rem;
  border-radius: 50%;
  background: var(--signal);
}

@media (max-width: 47.99rem) {
  .topline__place { display: none; }
  .topline__inner { justify-content: center; text-align: center; }
}

.masthead {
  position: sticky;
  top: 0;
  z-index: 90;
  background: var(--paper);
  border-bottom: 1px solid var(--line);

  /* ПОЧЕМУ ЦВЕТ ТЕКСТА НЕ ПЛАВАЕТ, А ПЕРЕКЛЮЧАЕТСЯ (016A §16, §17).

     Одновременный плавный переход фона и текста проходит через середину, а
     середина здесь — серое на сером: `#5D5E5D` поверх `rgba(244,241,235,.647)`.
     Это измеренное значение из старой версии, и именно оно на снимке владельца
     выглядит сломанным. Никакой порядок плавных переходов этого не спасает:
     светлый текст на почти молочном фоне так же нечитаем, как тёмный на почти
     чёрном.

     Поэтому фон и рамка едут 160 мс, а цвет текста и знаков СТУПЕНЬЮ на 64-й
     миллисекунде. Момент не «на глаз»: контраст светлого текста падает с
     осветлением фона, контраст тёмного растёт, и обе кривые пересекаются при
     плотности фона около 0,45 — это и есть 64 мс на кривой `--ease`. Ступень
     ровно в точке пересечения даёт наибольший ИЗ ВОЗМОЖНЫХ минимум. Измерено на
     медленной прокрутке через границу: 7,5:1 в худшей точке против 1,0:1 до
     правки; в покое обоих состояний — 17:1.

     Длительность выбрана не «покрасивее», а по геометрии: за 160 мс обычная
     прокрутка проходит меньше половины высоты шапки, то есть фон успевает
     набрать плотность РАНЬШЕ, чем светлый контент доезжает до строки текста.
     Ширины и высоты не анимируются вовсе: шапка не должна дёргаться. */
  transition: background 160ms var(--ease), border-color 160ms var(--ease),
              color 0s linear 64ms;
}

/* Над тёмным первым экраном шапка прозрачная, при скролле «приземляется». */
.masthead--over {
  background: transparent;
  border-color: transparent;
  color: var(--paper);
  /* Обратный путь мгновенный по цвету: тёмный экран уже под шапкой, и светлый
     текст читается на нём сразу — ждать нечего. */
  transition: background 160ms var(--ease), border-color 160ms var(--ease),
              color 0s linear 0s;
}

/* Первый кадр: состояние шапки ставится ДО отрисовки, и «приземления» из
   неправильного состояния быть не должно (§18). Класс снимается на следующем
   кадре — дальше переходы работают как обычно. */
.masthead--boot,
.masthead--boot * { transition: none !important; }

.masthead__inner {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 3vw, 3rem);
  /* `--header-h` — ПОЛНАЯ высота шапки, включая нижнюю границу (017Ca §18).

     Раньше токен стоял в `min-height` напрямую, и настоящая шапка была на
     пиксель выше объявленного: липкая колонка фильтров, липкая галерея товара,
     отступ для якорей и отрицательный отступ первого экрана — всё считалось от
     числа, которого на экране не существовало. Один пиксель не видно, но
     расхождение между «сколько занимает шапка» и «сколько мы думаем, что она
     занимает» — ровно тот класс ошибок, из которого вырастает «шапка не на
     месте». Теперь токен равен измеряемой величине, а граница вычитается здесь. */
  min-height: calc(var(--header-h) - 1px);
}

.wordmark {
  flex: none;
  display: inline-flex;
  align-items: baseline;
  gap: .375rem;
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-weight: 800;
  letter-spacing: -.045em;
}

.wordmark__slash { color: var(--signal); }

.wordmark__note {
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: .1em;
  text-transform: uppercase;
  opacity: .6;
}

@media (max-width: 74.99rem) { .wordmark__note { display: none; } }

.masthead__nav { display: none; }

@media (min-width: 62rem) {
  .masthead__nav {
    display: flex;
    align-items: center;
    gap: clamp(1rem, 2vw, 2rem);
    margin-inline-end: auto;
  }
}

.masthead__link {
  position: relative;
  padding-block: .5rem;
  font-size: var(--step--1);
  font-weight: 500;
  white-space: nowrap;
}

.masthead__link::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: .125rem;
  height: 1.5px;
  background: var(--signal);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--base) var(--ease-out);
}

.masthead__link:hover::after,
.masthead__link[aria-current='true']::after { transform: scaleX(1); }

.masthead__actions {
  display: flex;
  align-items: center;
  gap: .625rem;
  margin-inline-start: auto;
}

@media (min-width: 62rem) { .masthead__actions { margin-inline-start: 0; } }

.masthead__cta { display: none; }
@media (min-width: 30rem) { .masthead__cta { display: inline-flex; } }

/* Кнопка меню (017Cab §3).

   ЧТО БЫЛО И ПОЧЕМУ СЛОМАЛОСЬ. Знак рисовался тремя ПУСТЫМИ `<span>`:
   `height: 1.5px` + `background: currentColor`, а ширину им давало растягивание
   внутри `display: flex` САМОЙ КНОПКИ. Ни один из трёх параметров не был
   собственным свойством знака — всё держалось на том, что браузер применит flex
   к содержимому `<button>`. Там, где он этого не делает, содержимое кнопки
   раскладывается анонимным блоком, пустые `<span>` становятся строчными, а
   высота к строчному непустому боксу не применяется вовсе: три полоски
   схлопываются в ничто. Рамка при этом рисуется кнопкой и остаётся видимой —
   получается ПУСТОЙ КРУЖОК, ровно то, что владелец снял на iPhone.

   Проверяемость этого утверждения: `mobile-shell.py` меряет геометрию знака,
   СЧИТАЕТ нарисованные пиксели внутри кружка и отдельно доказывает, что знак
   больше не исчезает, когда раскладка кнопки перестаёт быть flex.

   ЧТО СТАЛО. Замещённый элемент со своими размерами и своей геометрией линий.
   От раскладки кнопки он не зависит: центрируется и flex-ом, и `margin: auto`
   в обычном блоке. Цвет — `currentColor`, поэтому знак живёт в обоих
   состояниях шапки. Ни иконочного шрифта, ни символа Unicode, ни внешнего
   файла, ни масок и фонов: только собственная разметка проекта (§4). */
.burger {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* Запасная центровка для раскладки, в которой flex к содержимому кнопки не
     применяется: там знак — блок внутри анонимного бокса, и его центрирует
     `margin: auto` по горизонтали и сама кнопка по вертикали. */
  text-align: center;
  width: 44px; height: 44px;
  padding: 0;
  background: none;
  color: inherit;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-pill);
  cursor: pointer;
}

.masthead--over .burger { border-color: var(--line-invert); }

@media (min-width: 62rem) { .burger { display: none; } }

.burger__glyph { display: block; margin: auto; }
.burger__glyph--close { display: none; }
.burger[aria-expanded='true'] .burger__glyph--menu { display: none; }
.burger[aria-expanded='true'] .burger__glyph--close { display: block; }

/* Мобильное меню — самостоятельный экран, а не сжатый десктоп.

   ДЕФЕКТ, КОТОРЫЙ ЗДЕСЬ ЗАКРЫТ (017Cab §5…§8). Строки сетки были
   `auto 1fr auto`, а навигация внутри средней строки стояла по центру
   (`align-content: center`). Значит расстояние между навигацией и оранжевой
   кнопкой было НЕ заданным расстоянием, а ОСТАТКОМ высоты экрана. Пока остаток
   есть — виден «задуманный» отступ; как только экран становится ниже, остаток
   обнуляется, и кнопка встаёт вплотную к черте под «Вопросами».

   На iPhone высота области просмотра меняется сама: у страницы, стоящей в самом
   верху, панели браузера развёрнуты и экран ниже; после прокрутки они
   складываются и экран выше. Отсюда и два состояния владельца — одно и то же
   меню выглядело по-разному в зависимости от того, прокручена ли страница.

   ТЕПЕРЬ расстояния заданы явно (`gap`), строки — по содержимому,
   `align-content: start`. Остаток высоты больше ни на что не влияет, поэтому
   оба состояния совпадают. Если экран слишком низкий, содержимое прокручивается
   ВНУТРИ оверлея (§7, §10), а не сжимается до соприкосновения.

   `gap` намеренно считается от `vw`, а не от `vh`: ширина при прокрутке не
   меняется, высота — меняется, и отступ от неё зависеть не имеет права. */
.menu {
  position: fixed;
  inset: 0;
  z-index: 95;
  /* Колонка, а не сетка: `position: sticky` у элемента сетки ограничен своей
     ячейкой, а ячейка при строках `auto` равна самому элементу — прилипать
     было бы некуда. Шапке меню прилипать надо (§10). */
  display: flex;
  flex-direction: column;
  /* Ничто не растягивается и НИЧТО НЕ СЖИМАЕТСЯ. Сжатие — это и есть
     «схлопнуть отступы, пока элементы не соприкоснутся», от чего мы уходим (§7). */
  overflow-y: auto;
  /* Прокрутка оверлея не «пробивается» на страницу под ним. */
  overscroll-behavior: contain;
  background: var(--ink);
  color: var(--text-invert);
  /* Верхний отступ живёт в шапке меню: она липкая и обязана закрывать собой всё,
     что проезжает под ней. */
  padding: 0 var(--gutter) calc(var(--gutter) + env(safe-area-inset-bottom));
  opacity: 0;
  visibility: hidden;
  transform: translateY(-1.5rem);
  transition: opacity var(--base) var(--ease), transform var(--base) var(--ease-out), visibility var(--base);
}

.menu > * { flex: none; }

/* Оверлей закрывает ровно видимую часть экрана, а не ту, что была бы видна при
   сложенных панелях браузера. Под `@supports`, потому что единицу знают не все
   браузеры; там остаётся прежнее поведение `inset: 0`, и оно тоже рабочее —
   внутренняя прокрутка не даёт содержимому оказаться недостижимым (§8). */
@supports (height: 100dvh) {
  .menu { height: 100dvh; }
}

.menu.is-open { opacity: 1; visibility: visible; transform: none; }

/* Шапка меню прилипает к верху оверлея: на низком экране содержимое
   прокручивается внутри, и крестик не имеет права уехать за край (§10).
   Нижний отступ шапки — это и есть расстояние до навигации: так липкая полоса
   закрывает собой всё вплоть до первого пункта, без просвета. */
.menu__head {
  position: sticky;
  top: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding-block: calc(var(--gutter) + env(safe-area-inset-top)) var(--menu-gap);
  background: var(--ink);
}

.menu__head .eyebrow { color: var(--text-invert-mut); }

.menu__close {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  background: none;
  color: var(--paper);
  border: 1px solid var(--line-invert);
  border-radius: 50%;
  cursor: pointer;
}

.menu__close:hover { background: rgba(244, 241, 235, .1); }

/* Навигация стоит по НАЧАЛУ строки, а не по её центру: центрирование внутри
   растянутой строки и было тем механизмом, который превращал остаток высоты в
   отступ над кнопкой (§5). */
.menu__list { display: grid; align-content: start; gap: .25rem; }

.menu__link {
  display: flex;
  align-items: baseline;
  gap: 1rem;
  padding-block: clamp(.625rem, 2vw, 1rem);
  border-bottom: 1px solid var(--line-invert);
  font-family: var(--font-display);
  font-size: var(--step-3);
  font-weight: 600;
  letter-spacing: -.03em;
}

.menu__index {
  font-size: var(--step--2);
  letter-spacing: .12em;
  color: var(--signal);
}

/* Расстояние между навигацией и кнопкой задано ЯВНО и не зависит ни от высоты
   экрана, ни от прокрутки (§5, §7). */
.menu__foot { display: grid; gap: 1rem; margin-block-start: var(--menu-gap); }
.menu__note { color: var(--text-invert-mut); font-size: var(--step--1); max-width: 44ch; }

/* --------------------------------------------------------------------------
   6. Первый экран
   -------------------------------------------------------------------------- */
.hero {
  position: relative;
  /* Шапка прозрачная и липкая: герой должен начинаться под ней, а не после неё. */
  margin-block-start: calc(var(--header-h) * -1);
  background: var(--ink);
  color: var(--text-invert);
  overflow: hidden;
  isolation: isolate;
}

/* Графический слой: дуга «движения» вместо стоковой фотографии. */
.hero__disc,
.hero__ring {
  position: absolute;
  z-index: -1;
  border-radius: 50%;
  pointer-events: none;
}

.hero__disc {
  inset-inline-end: -8%;
  top: 12%;
  width: min(72vw, 560px);
  aspect-ratio: 1;
  background: linear-gradient(150deg, #FF6330 0%, var(--signal) 38%, #B92D06 100%);
}

.hero__ring {
  inset-inline-end: -20%;
  top: 2%;
  width: min(96vw, 760px);
  aspect-ratio: 1;
  border: 1px solid var(--line-invert);
}


.hero__grid-lines {
  position: absolute;
  z-index: -1;
  inset: 0;
  background-image: linear-gradient(to right, var(--line-invert) 1px, transparent 1px);
  background-size: calc(100% / 6) 100%;
  opacity: .5;
  pointer-events: none;
}

.hero__inner {
  display: grid;
  /* На мобильном пара показывается сразу после заголовка, до кнопок: первый экран
     должен продавать желание, а не список фактов. Порядок задаётся областями. */
  grid-template-areas: 'copy' 'shot' 'cta';
  gap: clamp(1.5rem, 3vw, 2.5rem);
  padding-block: calc(var(--header-h) + clamp(1.25rem, 3vw, 3rem)) clamp(2rem, 4vw, 3.5rem);
}

.hero__copy { grid-area: copy; }
.hero__cta  { grid-area: cta; }
.hero__shot { grid-area: shot; position: relative; }

@media (min-width: 62rem) {
  .hero__inner {
    grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr);
    grid-template-areas: 'copy shot' 'cta shot';
    align-items: start;
    gap: clamp(1.5rem, 2vw, 2.5rem) clamp(2rem, 4vw, 4.5rem);
  }

  .hero__shot { align-self: center; }
}

.hero__title {
  margin-block: clamp(1rem, 2vw, 1.75rem) clamp(1.125rem, 2vw, 1.75rem);
  font-size: var(--step-5);
  font-weight: 800;
  line-height: 1.0;
  letter-spacing: -.04em;
}

.hero__title-accent { color: var(--signal); }

.hero__lead {
  max-width: 46ch;
  color: var(--text-invert-mut);
  font-size: var(--step-1);
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: .75rem;
}

.hero__facts {
  display: grid;
  gap: 1px;
  margin-top: clamp(1.5rem, 2.4vw, 2.25rem);
  background: var(--line-invert);
  border-block: 1px solid var(--line-invert);
}

@media (min-width: 34rem) { .hero__facts { grid-template-columns: repeat(3, 1fr); } }

.hero__fact { background: var(--ink); padding: 1.125rem 0; }

@media (min-width: 34rem) {
  .hero__fact { padding: 1.25rem clamp(.875rem, 1.5vw, 1.5rem); }
  .hero__fact:first-child { padding-inline-start: 0; }
}

/* Заголовок довода. Прежде здесь стояло крупное число (12 / ฿ / 0 ₽); теперь чисел
   нет, и «цифровой» кегль был бы враньём о характере строки: это обещание сервиса,
   а не измеренная величина (015Aa §7). */
.hero__fact-title {
  font-family: var(--font-display);
  font-size: var(--step-0);
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -.01em;
  color: var(--signal);
  text-wrap: balance;
}

.hero__fact-note {
  margin-top: .375rem;
  font-size: var(--step--2);
  color: var(--text-invert-mut);
  line-height: 1.45;
}

.hero__shot-frame {
  /* flex, а не grid: при фиксированной высоте кадра grid прижимает ряд к верху
     и обрезает пару снизу, flex центрирует её по высоте контейнера. */
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.hero__shot img { position: relative; }

.hero__shot img {
  width: min(100%, 620px);
  margin-block: -7%;
  filter: drop-shadow(0 32px 52px rgba(0, 0, 0, .5));
  transform: rotate(-7deg);
}

.hero__caption {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: .5rem 1rem;
  padding-top: 1rem;
  border-top: 1px solid var(--line-invert);
  font-size: var(--step--2);
}

.hero__caption b { font-family: var(--font-display); font-size: var(--step--1); font-weight: 600; }
.hero__caption span { color: var(--text-invert-mut); }

@media (max-width: 61.99rem) {
  /* На узких экранах диск секции уезжал за кнопки — переносим его внутрь кадра пары. */
  .hero__disc,
  .hero__ring { display: none; }

  /* Кадр не режем по высоте руками: object-fit сам берёт середину квадратной
     подложки, где и лежит пара, а поворот на мобильном только мешает. */
  .hero__shot-frame { overflow: visible; }

  .hero__shot-frame::before {
    content: '';
    position: absolute;
    z-index: -1;
    inset-inline-end: -10%;
    top: 50%;
    translate: 0 -50%;
    width: 56%;
    aspect-ratio: 1;
    border-radius: 50%;
    background: linear-gradient(150deg, #FF6330 0%, var(--signal) 38%, #B92D06 100%);
  }

  .hero__shot img {
    width: 100%;
    aspect-ratio: 2 / 1;
    object-fit: cover;
    object-position: center;
    margin-block: 0;
    transform: none;
    filter: drop-shadow(0 18px 30px rgba(0, 0, 0, .45));
  }
}

/* --------------------------------------------------------------------------
   7. Витрина моделей
   -------------------------------------------------------------------------- */
.filters {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
  margin-bottom: clamp(1.5rem, 3vw, 2.5rem);
}

.filter {
  min-height: 42px;
  padding: .5rem 1.125rem;
  background: transparent;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-pill);
  font-family: var(--font-display);
  font-size: var(--step--1);
  font-weight: 500;
  cursor: pointer;
  transition: background var(--fast) var(--ease), color var(--fast) var(--ease),
              border-color var(--fast) var(--ease);
}

.filter:hover { background: rgba(11, 13, 15, .05); }

.filter[aria-pressed='true'] {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--paper);
}

.filter__count { opacity: .6; font-variant-numeric: tabular-nums; }

/* Компактный выбор пола на главной (017Cab §11 · 017Caba §3…§8).

   ЭТО ОДНА ОПЦИЯ КАТАЛОГА, А НЕ ЕЩЁ ОДНО ГЛАВНОЕ ДЕЙСТВИЕ. Элемент стоит в том
   же ряду, что назначения, имеет ту же высоту, ту же пилюлю, ТУ ЖЕ типографику
   и то же оформление счётчика — и намеренно тише: подпись «ПОЛ» мелкими
   прописными приглушённым.

   ПОЧЕМУ СВОЙ ЭЛЕМЕНТ, А НЕ `<select>`. Нативный выбор приносил с собой чужую
   типографику (значение рисовалось шрифтом текста в 17 px рядом с чипами в
   14 px), свой крупный треугольник и — главное — раскрытый список, который
   рисует операционная система. Привести к языку витрины можно было только
   закрытое состояние, и то наполовину.

   ПОЧЕМУ ТЕПЕРЬ МОЖНО 14 px. Правило «не мельче 16 px» относится к ПОЛЯМ ФОРМЫ:
   iOS Safari увеличивает страницу при касании `input`/`select`/`textarea` с
   мелким шрифтом. Кнопка и ссылка полем формы не являются — масштаб они не
   дёргают. Поля формы в элементе управления больше нет, поэтому исчезло и
   единственное основание быть крупнее соседей. */
.genderpick {
  position: relative;
  display: inline-block;
}

/* Треугольник раскрытия рисуем сами. */
.genderpick__button::-webkit-details-marker { display: none; }
.genderpick__button { list-style: none; }

.genderpick__button {
  display: inline-flex;
  align-items: center;
  gap: .625rem;
  min-height: 42px;
  padding: .5rem 1rem .5rem 1.125rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-pill);
  /* Ровно то же, что у `.filter`: одно семейство, один кегль, один вес. */
  font-family: var(--font-display);
  font-size: var(--step--1);
  font-weight: 500;
  white-space: nowrap;
  cursor: pointer;
  user-select: none;
  transition: background var(--fast) var(--ease), border-color var(--fast) var(--ease);
}

.genderpick__button:hover { background: rgba(11, 13, 15, .05); }

/* Подпись, значение и счётчик стоят на ОДНОЙ БАЗОВОЙ ЛИНИИ, а не по центру
   каждый по себе: кегли у них разные, и центрирование разводит их по вертикали
   на пару пикселей — это и читается как «прыжок». */
.genderpick__text {
  display: inline-flex;
  align-items: baseline;
  gap: .4375rem;
}

.genderpick__label {
  font-size: var(--step--2);
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.genderpick__sep { color: var(--text-muted); opacity: .6; }

/* Треугольник заметно мельче нативного и приглушён: это подсказка, а не кнопка. */
.genderpick__caret {
  flex: none;
  color: var(--text-muted);
  transition: transform var(--fast) var(--ease);
}

.genderpick[open] .genderpick__caret { transform: rotate(180deg); }

.genderpick[open] .genderpick__button { border-color: var(--ink); }

/* ФОКУС — ЧАСТЬ САМОГО ЭЛЕМЕНТА (§6). Общий `:focus-visible` витрины отступает
   от элемента на 3 px и рисует прямоугольник со своим радиусом — вокруг пилюли
   он выглядел отдельной оранжевой рамкой, висящей в воздухе. Здесь кольцо
   повторяет форму пилюли и прилегает к её границе. */
.genderpick .genderpick__button:focus-visible,
.genderpick .genderpick__option:focus-visible {
  outline: none;
  border-color: var(--signal);
  box-shadow: 0 0 0 2px var(--signal-ring);
}

/* У опции своей границы нет — кольцо уходит ВНУТРЬ, иначе оно вылезло бы
   за край панели. */
.genderpick .genderpick__option:focus-visible {
  box-shadow: inset 0 0 0 2px var(--signal-ring), inset 0 0 0 1px var(--signal);
}

/* В режиме принудительных цветов системная рамка обязана вернуться: там
   `box-shadow` не рисуется вовсе, и без этого фокус исчез бы совсем. */
@media (forced-colors: active) {
  .genderpick__button:focus-visible,
  .genderpick__option:focus-visible { outline: 2px solid; outline-offset: -2px; }
}

/* Раскрытый список — ПРОДОЛЖЕНИЕ пилюли, а не отдельный слой интерфейса:
   та же бумага, та же граница, тот же кегль. Тень сдержанная — список лежит
   на своём месте, а не «летит» над страницей. */
.genderpick__panel {
  position: absolute;
  z-index: 20;
  inset-inline-start: 0;
  top: calc(100% + .375rem);
  min-width: 100%;
  /* Список не может вылезти за экран даже на 320 px: ширина ограничена самим
     окном, а не надеждой на то, что слева достаточно места (§13). */
  max-width: min(17rem, calc(100vw - 2 * var(--gutter)));
  padding: .3125rem;
  background: var(--paper);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg);
  box-shadow: 0 10px 24px rgba(11, 13, 15, .12);
}

.genderpick__list {
  display: grid;
  gap: 1px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.genderpick__option {
  display: flex;
  align-items: baseline;
  gap: .4375rem;
  /* Цель нажатия ~44 px по высоте (§15): список пальцем, а не курсором. */
  min-height: 40px;
  padding: .5rem .75rem;
  border-radius: var(--radius);
  font-family: var(--font-display);
  font-size: var(--step--1);
  font-weight: 500;
  white-space: nowrap;
}

.genderpick__option:hover { background: rgba(11, 13, 15, .06); }

/* Отметка выбранного — ЗНАК, а не только заливка: выбор виден и без цвета. */
.genderpick__tick {
  flex: none;
  align-self: center;
  color: var(--signal);
  visibility: hidden;
}

.genderpick__option.is-active { font-weight: 600; }
.genderpick__option.is-active .genderpick__tick { visibility: visible; }

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

/* Колонки заданы явно, а не auto-fill: с малым minmax (нужным для двух колонок
   на телефоне) auto-fill давал 5–6 узких колонок на планшете. */
.grid {
  display: grid;
  gap: clamp(.625rem, 1.4vw, 1.25rem);
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (min-width: 40rem) { .grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 64rem) { .grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.card {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--paper-2);
  border-radius: var(--radius-lg);
  overflow: hidden;
  text-align: start;
  border: 0;
  padding: 0;
  transition: transform var(--base) var(--ease-out), box-shadow var(--base) var(--ease);
}

.card:hover { transform: translateY(-4px); box-shadow: 0 18px 40px -24px rgba(11, 13, 15, .55); }

/* Ссылка карточки растянута на всю её площадь.

   КАРТОЧКА БОЛЬШЕ НЕ ОДНА БОЛЬШАЯ ССЫЛКА (017Ca §3). Точки расцветок стали
   настоящими элементами управления, а вложить их внутрь ссылки нельзя: такая
   разметка недопустима, и диктор читает её неверно. Поэтому ссылка осталась
   одна — у названия модели, — а нажимаемой остаётся вся карточка: площадь даёт
   псевдоэлемент. Точки лежат выше по слою и перехватывают нажатие на себя. */
.card__link { position: static; color: inherit; }

.card__link::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  cursor: pointer;
}

/* Обводка фокуса обязана обвести КАРТОЧКУ, а не одну строку названия: клавиатурой
   человек выбирает карточку целиком. `:has` не поддержан — остаётся обычная
   обводка вокруг названия, и это по-прежнему видимый фокус. */
.card__link:focus-visible { outline: 2px solid var(--signal); outline-offset: 2px; }
.card:has(.card__link:focus-visible) { outline: 2px solid var(--signal); outline-offset: 3px; }
.card:has(.card__link:focus-visible) .card__link:focus-visible { outline: 0; }

.card__media {
  position: relative;
  /* На телефоне сетка двухколоночная — квадрат экономит высоту. */
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  background: var(--card-ground, var(--ink-3));
  overflow: hidden;
}

.card__media img {
  width: 86%;
  transition: transform var(--slow) var(--ease-out);
}

@media (min-width: 40rem) { .card__media { aspect-ratio: 4 / 3; } }

.card:hover .card__media img { transform: scale(1.055) rotate(-2deg); }

/* Бейдж внизу, пол — сверху: в двухколоночной сетке они иначе наезжали друг на друга. */
/* Осознанное состояние «фотографии нет» — вместо битой картинки. */
.media-empty {
  display: grid;
  place-items: center;
  padding: 1rem;
  text-align: center;
  font-family: var(--font-display);
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: rgba(244, 241, 235, .62);
  border: 1px dashed rgba(244, 241, 235, .3);
  border-radius: var(--radius);
  margin: 12%;
  min-width: 60%;
  min-height: 40%;
}

.card__badge {
  position: absolute;
  inset-block-end: .5rem;
  inset-inline-start: .5rem;
  max-width: calc(100% - 1rem);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  padding: .1875rem .5rem;
  background: var(--signal);
  color: #fff;
  border-radius: var(--radius-pill);
  font-family: var(--font-display);
  font-size: var(--step--2);
  font-weight: 600;
  letter-spacing: .02em;
}

.card__gender {
  position: absolute;
  inset-block-start: .5rem;
  inset-inline-end: .5rem;
  padding: .1875rem .5rem;
  background: rgba(11, 13, 15, .55);
  color: var(--paper);
  border-radius: var(--radius-pill);
  font-size: var(--step--2);
  /* Safari до сих пор требует префикс: без него бейдж на фотографии теряет
     размытие и читается хуже (016A §53). */
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}

.card__body {
  display: flex;
  flex-direction: column;
  gap: .375rem;
  padding: .75rem .875rem 1rem;
  flex: 1;
}

@media (min-width: 40rem) {
  .card__body { gap: .5rem; padding: 1rem 1.125rem 1.125rem; }
}

.card__name {
  font-family: var(--font-display);
  font-size: var(--step-0);
  font-weight: 600;
  letter-spacing: -.025em;
  line-height: 1.15;
}

@media (min-width: 40rem) { .card__name { font-size: var(--step-1); } }

.card__tagline {
  font-size: var(--step--2);
  color: var(--text-muted);
  line-height: 1.4;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

@media (min-width: 40rem) { .card__tagline { font-size: var(--step--1); } }

/* Название выбранной расцветки: покупатель обязан понимать, ЧТО он сейчас
   видит, не открывая страницу товара (017Ca §3). Одна строка — вторая съела бы
   высоту двухколоночной сетки телефона. */
.card__colorway {
  margin-top: auto;
  padding-top: .25rem;
  font-size: var(--step--2);
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.card__swatches {
  position: relative;
  /* Выше растянутой ссылки: нажатие на точку меняет карточку, а не уводит
     на страницу товара (§3). */
  z-index: 1;
  display: flex;
  flex-wrap: wrap;
  /* Промежутка нет: он уже внутри цели нажатия. Соседние цели смыкаются, но не
     перекрываются (§21). */
  gap: 0;
  padding-top: .125rem;
  /* Ряд сдвинут на половину «воздуха» цели, чтобы первая точка стояла по левому
     краю текста карточки, а не с отступом. */
  margin-inline-start: -6px;
}

.swatch {
  width: 1rem;
  height: 1rem;
  border-radius: 50%;
  box-shadow: inset 0 0 0 1px rgba(11, 13, 15, .22);
  flex: none;
}

/* Точка расцветки как элемент управления.

   ЦЕЛЬ НАЖАТИЯ БОЛЬШЕ САМОЙ ТОЧКИ (§21). Видимая точка остаётся 16 px — ряд из
   четырёх точек в карточке шириной 144 px иначе не помещается, — а нажимаемым
   является всё поле 28×28, то есть выше минимума WCAG 2.5.8 (24 px).

   «Воздух» встроен в САМ элемент, а не сделан отступами и псевдоэлементом. Это
   не косметика: цель нажатия, нарисованная псевдоэлементом, не видна ни
   инструментам проверки доступности, ни нашему собственному набору — он читает
   размеры элемента и честно говорит «16 px». Проверяемость важнее экономии
   строчки. */
.swatch-pick {
  position: relative;
  display: inline-grid;
  place-items: center;
  flex: none;
  width: 28px;
  height: 28px;
  border-radius: 50%;
}

.swatch-pick .swatch { position: relative; transition: box-shadow var(--fast) var(--ease); }
.swatch-pick:hover .swatch { box-shadow: inset 0 0 0 1px rgba(11, 13, 15, .45); }
.swatch-pick:focus-visible { outline: 2px solid var(--signal); outline-offset: -2px; }

/* Выбранная расцветка: кольцо цвета чернил через просвет бумаги. Читается и в
   чёрно-белом виде — это форма, а не цвет. */
.swatch-pick.is-active .swatch { box-shadow: 0 0 0 2px var(--paper-2), 0 0 0 3.5px var(--ink); }

/* Расцветка, в которой выбранного фильтром размера сейчас нет (§9).

   ПРИЗНАКОВ ТРИ, И НИ ОДИН НЕ ЦВЕТОВОЙ: точка обесцвечивается, гаснет и
   перечёркивается. Диктору то же самое уходит словами — скрытой подписью внутри
   ссылки.

   Перечёркивание НАРОЧНО выходит за края точки и обведено цветом карточки.
   Первый вариант — короткая линия по диаметру — на снимке оказался неотличим от
   границы двухцветной заливки: расцветки вида «айвори/роза» сами нарисованы
   диагональю под 135°, и «перечёркнуто» читалось у всех подряд. Признак,
   который путается с оформлением, — это не признак. */
.swatch-pick.is-off .swatch { opacity: .5; filter: grayscale(1); }

.swatch-pick.is-off .swatch::after {
  content: '';
  position: absolute;
  left: -5px;
  right: -5px;
  top: 50%;
  height: 2px;
  margin-top: -1px;
  background: var(--text);
  box-shadow: 0 0 0 1px var(--paper-2);
  border-radius: 1px;
  transform: rotate(-45deg);
}

/* Что именно не так с выбранной расцветкой — словами, рядом с ценой. */
.card__note {
  display: flex;
  align-items: flex-start;
  gap: .375rem;
  font-size: var(--step--2);
  line-height: 1.3;
  color: var(--amber);
}

.card__price {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: .125rem .5rem;
  padding-top: .5rem;
  border-top: 1px solid var(--line);
}

.card__price-label { font-size: var(--step--2); color: var(--text-muted); width: 100%; }
.card__price .money--lg { font-size: var(--step-1); }

@media (min-width: 40rem) {
  .card__price { gap: .25rem .625rem; padding-top: .625rem; }
  .card__price .money--lg { font-size: var(--step-2); }
}

.grid__empty {
  padding: clamp(2rem, 5vw, 3.5rem);
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius-lg);
  text-align: center;
  color: var(--text-muted);
}

/* --------------------------------------------------------------------------
   8. Ценности, процесс, доверие
   -------------------------------------------------------------------------- */
.values { display: grid; gap: 1px; background: var(--line); border-block: 1px solid var(--line); }

@media (min-width: 40rem) { .values { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 68rem) { .values { grid-template-columns: repeat(4, 1fr); } }

.value {
  background: var(--paper);
  padding: clamp(1.25rem, 2vw, 2rem) clamp(1rem, 1.6vw, 1.75rem) clamp(1.75rem, 2.6vw, 2.5rem);
  display: grid;
  gap: .625rem;
  align-content: start;
}

.value__index {
  font-family: var(--font-display);
  font-size: var(--step--2);
  font-weight: 600;
  letter-spacing: .14em;
  color: var(--signal);
}

.value__title { font-size: var(--step-1); }
.value__body { color: var(--text-muted); font-size: var(--step--1); }

.steps { display: grid; gap: 1px; background: var(--line-invert); }

@media (min-width: 44rem) { .steps { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 72rem) { .steps { grid-template-columns: repeat(3, 1fr); } }

.step {
  position: relative;
  background: var(--ink);
  padding: clamp(1.5rem, 2.4vw, 2.25rem) clamp(1.125rem, 1.8vw, 2rem) clamp(2rem, 3vw, 2.75rem);
  display: grid;
  gap: .625rem;
  align-content: start;
}

.step__head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }

.step__num {
  display: grid;
  place-items: center;
  width: 2.25rem; height: 2.25rem;
  border: 1px solid var(--signal);
  border-radius: 50%;
  color: var(--signal);
  font-family: var(--font-display);
  font-size: var(--step--1);
  font-weight: 600;
}

.step__tag {
  font-size: var(--step--2);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--text-invert-mut);
}

.step__title { font-size: var(--step-1); }
.step__body { color: var(--text-invert-mut); font-size: var(--step--1); }

.trust { display: grid; gap: clamp(2rem, 4vw, 4rem); }

@media (min-width: 62rem) {
  .trust { grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr); align-items: start; }
}

.trust__can { display: grid; gap: 1px; background: var(--line); border-block: 1px solid var(--line); }
.trust__item { background: var(--paper); padding: clamp(1.125rem, 2vw, 1.75rem) 0; display: grid; gap: .5rem; }
.trust__item-title { font-size: var(--step-1); }
.trust__item-body { color: var(--text-muted); font-size: var(--step--1); max-width: var(--measure); }

.trust__cannot {
  padding: clamp(1.5rem, 2.6vw, 2.25rem);
  background: var(--ink);
  color: var(--text-invert);
  border-radius: var(--radius-lg);
  display: grid;
  gap: 1rem;
}

.trust__cannot h3 { font-size: var(--step-2); }
.trust__cannot ul { display: grid; gap: .75rem; }

.trust__cannot li {
  position: relative;
  padding-inline-start: 1.75rem;
  color: var(--text-invert-mut);
  font-size: var(--step--1);
}

.trust__cannot li::before {
  content: '';
  position: absolute;
  inset-inline-start: 0;
  top: .5em;
  width: .75rem; height: 1.5px;
  background: var(--signal);
}

/* --------------------------------------------------------------------------
   9. Размеры
   -------------------------------------------------------------------------- */
.sizing { display: grid; gap: clamp(2rem, 4vw, 3.5rem); }

@media (min-width: 62rem) {
  .sizing { grid-template-columns: minmax(0, .95fr) minmax(0, 1.05fr); align-items: start; }
}

.sizing > * { min-width: 0; }
.sizing__steps { display: grid; gap: 1.25rem; min-width: 0; }

.sizing__step {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: .375rem 1rem;
  padding-bottom: 1.25rem;
  border-bottom: 1px solid var(--line);
}

.sizing__step-num {
  grid-row: span 2;
  font-family: var(--font-display);
  font-size: var(--step-2);
  font-weight: 700;
  color: var(--paper-3);
  letter-spacing: -.04em;
}

.sizing__step-title { font-size: var(--step-1); min-width: 0; }
.sizing__step-body { color: var(--text-muted); font-size: var(--step--1); min-width: 0; }

.table-wrap {
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  -webkit-overflow-scrolling: touch;
}

table.sizes {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--step--1);
  font-variant-numeric: tabular-nums;
}

table.sizes th, table.sizes td {
  padding: .625rem .875rem;
  text-align: start;
  white-space: nowrap;
  border-bottom: 1px solid var(--line);
}

table.sizes thead th {
  position: sticky;
  top: 0;
  background: var(--paper-2);
  font-family: var(--font-display);
  font-size: var(--step--2);
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
}

table.sizes tbody tr:last-child th,
table.sizes tbody tr:last-child td { border-bottom: 0; }
table.sizes tbody tr:hover { background: var(--paper-2); }
table.sizes tbody th { font-family: var(--font-display); font-weight: 600; }

.table-note { margin-top: .75rem; font-size: var(--step--2); color: var(--text-muted); }

/* --------------------------------------------------------------------------
   10. Вопросы
   -------------------------------------------------------------------------- */
.faq { display: grid; gap: 0; border-top: 1px solid var(--line); max-width: 62rem; }

.faq details { border-bottom: 1px solid var(--line); }

.faq summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  padding-block: clamp(1rem, 1.8vw, 1.5rem);
  font-family: var(--font-display);
  font-size: var(--step-1);
  font-weight: 600;
  letter-spacing: -.02em;
  cursor: pointer;
  list-style: none;
}

.faq summary::-webkit-details-marker { display: none; }

.faq summary::after {
  content: '';
  flex: none;
  width: 1.125rem; height: 1.125rem;
  background:
    linear-gradient(currentColor, currentColor) center / 100% 1.5px no-repeat,
    linear-gradient(currentColor, currentColor) center / 1.5px 100% no-repeat;
  transition: background-size var(--base) var(--ease-out);
}

.faq details[open] summary::after { background-size: 100% 1.5px, 1.5px 0; }

.faq__answer {
  padding-bottom: clamp(1rem, 1.8vw, 1.5rem);
  max-width: var(--measure);
  color: var(--text-muted);
}

/* --------------------------------------------------------------------------
   11. Финальный призыв и подвал
   -------------------------------------------------------------------------- */
.finale {
  display: grid;
  gap: clamp(1.5rem, 3vw, 2.5rem);
  align-items: end;
}

@media (min-width: 56.25rem) {
  .finale { grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); }
}

.finale__title { font-size: var(--step-4); }
.finale__lead { color: var(--text-invert-mut); max-width: var(--measure); margin-top: 1rem; }

/* РЯД ДЕЙСТВИЙ — одно правило на все поверхности витрины (016B, правка владельца).

   Было: `grid-auto-flow: column` — четыре кнопки насильно в один ряд внутри узкой
   колонки финального призыва. На 1024 и 1440 каждой доставалось по 130 px, и все
   четыре подписи ломались на три строки. Один ряд любой ценой — не композиция.

   Стало: кнопки переносятся целиком. Хватает места — стоят в строку; не хватает —
   ложатся 2×2 и выглядят так, будто так и задумано. На телефоне занимают всю
   ширину: там столбец читается лучше ряда. */
.finale__actions {
  /* Сетка, а не гибкая строка — и это важно для ПОСЛЕДНЕЙ строки.

     При `flex-wrap` кнопка, оставшаяся одна в строке, растягивается на всю
     ширину: на 768 px получалось три кнопки по 230 px и четвёртая на 709 px.
     Сетка `auto-fit` держит одинаковые колонки, поэтому одинокая кнопка
     занимает свою колонку и остаётся такой же, как соседи. */
  display: grid;
  /* 11.5rem — измеренная ширина самой длинной подписи («Написать в WhatsApp»,
     181 px) с небольшим запасом. Меньше нельзя: подпись начнёт переноситься.
     Больше тоже плохо — на 1024 px колонка в 384 px вместила бы только одну
     кнопку, и ряд рассыпался бы в столбик из четырёх. */
  grid-template-columns: repeat(auto-fit, minmax(11.5rem, 1fr));
  gap: .625rem;
}

/* 14rem — ширина самой длинной подписи («Написать в WhatsApp») с запасом. Отсюда
   геометрия получается сама и одинаковая:

     широкая колонка  → две кнопки в строке, обе по половине;
     узкая колонка    → по одной в строке, все во всю ширину;
     телефон          → столбец.

   Кнопки одного ряда никогда не оказываются разной ширины — до правки на 1024 px
   три мессенджера стояли столбиком и каждый был шириной со свою подпись, что
   выглядело случайностью, а не композицией.

   Главное действие остаётся сильнее соседей ЦВЕТОМ, а не размером: оранжевая
   заливка против сдержанного контура. Раздувать его шире прочих не нужно. */
.finale__actions .btn { width: 100%; }

@media (min-width: 56.25rem) {
  /* КОРЕНЬ ТРЁХСТРОЧНЫХ ПОДПИСЕЙ БЫЛ ЗДЕСЬ.

     `justify-self: end` сжимал правую ячейку до ширины содержимого, а содержимым
     была строка из четырёх кнопок. Получался замкнутый круг: ячейка узкая, потому
     что кнопки узкие, а кнопки узкие, потому что ячейка узкая. Измерение показало
     230 px на ЛЮБОЙ ширине экрана — даже на 1920.

     Теперь ячейка занимает свою колонку целиком (`stretch`), и сетка кнопок сама
     решает, сколько их поместится в строку. Прижатость вправо сохраняется самой
     колонкой сетки `.finale`, а не сжатием содержимого. */
  .finale > div:last-child { justify-self: stretch; }
}

.footer { background: var(--ink-2); color: var(--text-invert); padding-block: clamp(2.5rem, 5vw, 4rem) 2rem; }

.footer__top {
  display: grid;
  gap: clamp(1.75rem, 3vw, 3rem);
  padding-bottom: clamp(1.75rem, 3vw, 2.5rem);
  border-bottom: 1px solid var(--line-invert);
}

@media (min-width: 40rem) {
  .footer__top { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 68rem) {
  .footer__top { grid-template-columns: minmax(0, 1.5fr) repeat(3, minmax(0, .72fr)); }
}

.footer__about { color: var(--text-invert-mut); max-width: 46ch; margin-top: 1rem; font-size: var(--step--1); }

.footer__col-title {
  font-family: var(--font-display);
  font-size: var(--step--2);
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--text-invert-mut);
  margin-bottom: .875rem;
}

.footer__links { display: grid; gap: .125rem; }

/* Текстовая ссылка высотой в строку — слишком мелкая цель на телефоне. */
.footer__links a {
  display: inline-flex;
  align-items: center;
  min-height: 34px;
  font-size: var(--step--1);
}
.footer__links a:hover { color: var(--signal); }

.footer__links--contact a {
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: .0625rem;
  min-height: 42px;
}

.footer__contact-value { color: var(--text-invert-mut); font-size: var(--step--2); }
.footer__links--contact a:hover .footer__contact-value { color: inherit; }

.footer__bottom {
  display: grid;
  gap: 1rem;
  padding-top: clamp(1.25rem, 2.4vw, 2rem);
  font-size: var(--step--2);
  color: var(--text-invert-mut);
}

@media (min-width: 56.25rem) {
  .footer__bottom { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); align-items: start; }
}

/* --------------------------------------------------------------------------
   12. Карточка модели (диалог)
   -------------------------------------------------------------------------- */
.sheet {
  width: min(100%, 1080px);
  max-height: 100%;
  margin: auto;
  padding: 0;
  border: 0;
  border-radius: var(--radius-lg);
  background: var(--paper);
  color: var(--text);
  overflow: hidden;
}

.sheet::backdrop { background: rgba(11, 13, 15, .68); -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px); }

.sheet__inner { display: grid; max-height: min(88vh, 860px); overflow-y: auto; }

@media (min-width: 56.25rem) {
  .sheet__inner { grid-template-columns: minmax(0, .95fr) minmax(0, 1.05fr); overflow: hidden; }
}

.sheet__media {
  position: relative;
  display: grid;
  place-items: center;
  padding: clamp(1.5rem, 3vw, 2.5rem);
  background: var(--sheet-ground, var(--ink-3));
  min-height: 240px;
}

.sheet__media img { width: min(100%, 460px); }


.sheet__panel {
  --sheet-pad: clamp(1.25rem, 2.4vw, 2rem);
  display: grid;
  align-content: start;
  gap: 1.125rem;
  padding: var(--sheet-pad);
  overflow-y: auto;
}

.sheet__close {
  position: absolute;
  inset-block-start: .75rem;
  inset-inline-end: .75rem;
  width: 40px; height: 40px;
  display: grid;
  place-items: center;
  background: rgba(11, 13, 15, .55);
  color: var(--paper);
  border: 0;
  border-radius: 50%;
  cursor: pointer;
  z-index: 2;
}

@media (min-width: 56.25rem) {
  .sheet__close { background: var(--paper-2); color: var(--ink); }
}

.sheet__title { font-size: var(--step-3); }

.sheet__price {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: .375rem .875rem;
  padding-block: .875rem;
  border-block: 1px solid var(--line);
}

.sheet__price-note { width: 100%; font-size: var(--step--2); color: var(--text-muted); }

.sheet__group-title {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  font-family: var(--font-display);
  font-size: var(--step--2);
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: .625rem;
}

/* Правая часть заголовка группы — это значение (название расцветки) или ссылка,
   а не служебная метка: капслок и разрядка тут только мешают читать. */
.sheet__group-title [data-sheet-colorway-label] {
  text-transform: none;
  letter-spacing: 0;
  color: var(--text);
  font-weight: 500;
}

.sheet__group-title a { text-decoration: underline; text-underline-offset: .2em; }
.sheet__group-title a:hover { color: var(--signal); }

.colorways { display: flex; flex-wrap: wrap; gap: .5rem; }

.colorway {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  min-height: 40px;
  padding: .375rem .75rem .375rem .5rem;
  background: transparent;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-pill);
  font-size: var(--step--2);
  cursor: pointer;
  transition: border-color var(--fast) var(--ease), background var(--fast) var(--ease);
}

.colorway[aria-pressed='true'] { border-color: var(--ink); background: var(--paper-2); }

.sizes-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(4.25rem, 1fr));
  gap: .375rem;
}

.size {
  min-height: 46px;
  padding: .375rem .25rem;
  display: grid;
  place-items: center;
  gap: .125rem;
  background: transparent;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  font-family: var(--font-display);
  font-size: var(--step--1);
  font-weight: 600;
  cursor: pointer;
  transition: border-color var(--fast) var(--ease), background var(--fast) var(--ease);
}

.size:hover { border-color: var(--line-strong); }

/* Размер стал радиокнопкой (форма добавления в подборку работает без JS).
   Сам input скрыт, но остаётся фокусируемым: обводку рисует :has(:focus-visible). */
.size input[type='radio'] {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

.size:has(input:checked) { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.size:has(input:focus-visible) { outline: 2px solid var(--ink); outline-offset: 2px; }
.size[aria-pressed='true'] { background: var(--ink); border-color: var(--ink); color: var(--paper); }

/* Состояние размера — ЗНАКОМ, а не только цветом (015Ac §20, §21).

   Плитка стала двухслойной: число размера и маленький знак состояния в углу.
   Знак читается без цвета, а у отсутствующего размера число ещё и зачёркнуто —
   это узнаётся мгновенно и не требует легенды. */
.size { position: relative; }
.size__value { line-height: 1.1; }

.size__mark {
  position: absolute;
  inset-block-start: .125rem;
  inset-inline-end: .3125rem;
  font-size: .625rem;
  font-weight: 700;
  line-height: 1;
  color: var(--slate);
}

.size--ok   .size__mark { color: var(--jade); }
.size--warn .size__mark { color: var(--amber); }
.size:has(input:checked) .size__mark { color: var(--paper); }

/* Размера сейчас нет ни у одного проверенного продавца. Плитка приглушена и
   число зачёркнуто — но она остаётся выбираемой: «найдите мне такую пару» —
   это работа сервиса выкупа (D-033). Что произойдёт при добавлении, говорит
   кнопка: она превращается в «Добавить для проверки» (D-109). */
.size--blocked { opacity: .6; }
.size--blocked .size__value { text-decoration: line-through; text-decoration-thickness: 1.5px; }
.size--blocked:has(input:checked) { opacity: 1; background: var(--slate); border-color: var(--slate); }

/* Условные обозначения под сеткой: знаки обязаны называть себя словами. */
.sizes-legend {
  display: flex;
  flex-wrap: wrap;
  gap: .25rem .875rem;
  margin-top: .625rem;
  font-size: var(--step--2);
  color: var(--text-muted);
}

.sizes-legend__item { display: inline-flex; align-items: center; gap: .3125rem; }

.sizes-legend__mark {
  font-weight: 700;
  font-family: var(--font-display);
}

.sizes-legend__item--ok      .sizes-legend__mark { color: var(--jade); }
.sizes-legend__item--warn    .sizes-legend__mark { color: var(--amber); }
.sizes-legend__item--off     .sizes-legend__mark { color: var(--slate); }
.sizes-legend__item--neutral .sizes-legend__mark { color: var(--text-muted); }

/* Состояние ВЫБРАННОГО размера — крупной строкой у цены и кнопки (§38).
   Раньше на этом месте молчаливо стоял сигнал модели, и он оставался зелёным,
   когда нужного размера не было ни у кого. */
.sizestate {
  display: flex;
  align-items: flex-start;
  gap: .5rem;
  margin-top: .75rem;
  padding: .625rem .875rem;
  border: 1px solid var(--line);
  border-inline-start-width: 3px;
  border-radius: var(--radius);
  font-size: var(--step--1);
  font-weight: 600;
  line-height: 1.35;
}

.sizestate__mark {
  flex: none;
  font-family: var(--font-display);
  font-weight: 700;
}

.sizestate--ok      { color: var(--jade);  border-inline-start-color: var(--jade); }
.sizestate--warn    { color: var(--amber); border-inline-start-color: var(--amber); }
.sizestate--off     { color: var(--ink);   border-inline-start-color: var(--slate); background: var(--paper-2); }
.sizestate--neutral { color: var(--text-muted); border-inline-start-color: var(--line-strong); }

/* Кнопка «Добавить для проверки» — другое обещание, и выглядеть она обязана
   иначе, чем обычная покупка. */
.pdp__add--check { --btn-bg: var(--ink-3); --btn-fg: var(--paper); }
.pdp__add--check:hover { --btn-bg: var(--ink-2); }

.sheet__hint {
  display: grid;
  gap: .5rem;
  padding: .875rem 1rem;
  background: var(--paper-2);
  border-radius: var(--radius);
  font-size: var(--step--2);
  color: var(--text-muted);
}

.sheet__actions { display: grid; gap: .625rem; }

.sheet__channels {
  display: grid;
  gap: .5rem;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
}

.sheet__status {
  min-height: 1.25rem;
  font-size: var(--step--2);
  color: var(--jade);
  font-weight: 600;
}

/* На телефоне квадратная подложка съедала пол-экрана до цены и размеров —
   берём широкий кадр из её середины (там и лежит пара). */
@media (max-width: 56.24rem) {
  .sheet__media { min-height: 0; padding: .75rem; overflow: hidden; }
  .sheet__media img { width: 100%; aspect-ratio: 5 / 2; object-fit: cover; }

  /* Прокручивается только .sheet__inner: пока панель тоже была скролл-контейнером
     нулевой прокрутки, sticky внутри неё не работал. */
  .sheet__panel { overflow: visible; }

  /* Кнопки связи держим на виду: на телефоне карточка выше экрана, и главное
     действие иначе оказывается за пределами видимой части диалога. */
  .sheet__actions {
    position: sticky;
    bottom: 0;
    margin: 0 calc(var(--sheet-pad) * -1) calc(var(--sheet-pad) * -1);
    padding: .75rem var(--sheet-pad) calc(var(--sheet-pad) + env(safe-area-inset-bottom));
    background: var(--paper);
    border-top: 1px solid var(--line);
  }
}

/* --------------------------------------------------------------------------
   13. Появление секций
   -------------------------------------------------------------------------- */
[data-reveal] {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity var(--slow) var(--ease-out), transform var(--slow) var(--ease-out);
  transition-delay: var(--reveal-delay, 0ms);
}

[data-reveal].is-revealed { opacity: 1; transform: none; }

/* JS не выполнился — контент обязан остаться видимым. */
.no-js [data-reveal] { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }

  [data-reveal] { opacity: 1; transform: none; }
  .card:hover { transform: none; }
  .card:hover .card__media img { transform: none; }
}

/* ==========================================================================
   14. Каталог и страница товара (итерация 002A)
   Расширяют ту же систему, что и главная: те же токены, та же карточка,
   те же состояния наличия.
   ========================================================================== */

.page { padding-block: clamp(1.5rem, 2vw + 1rem, 3rem) var(--section); }
.page__head { display: grid; gap: .75rem; margin-block: clamp(1rem, 2vw, 2rem) clamp(1.75rem, 3vw, 2.75rem); }
.page__title { font-size: var(--step-4); }
.page__lead { max-width: var(--measure); color: var(--text-muted); font-size: var(--step-1); }

.section__more { margin-top: clamp(1.5rem, 3vw, 2.5rem); }

/* --- Страница 404 (итерация 007) ---------------------------------------
   Тупик — плохая 404. Верстается как обычный экран витрины: заголовок, короткое
   объяснение и настоящие выходы — каталог, менеджер, назначения. */
.notfound__shell { display: grid; gap: 1.25rem; max-width: 1180px; }
.notfound__title { font-size: var(--step-4); margin: 0; }
.notfound__lead { max-width: var(--measure); margin: 0; color: var(--text-muted); font-size: var(--step-1); }

.notfound__actions {
  display: flex;
  flex-wrap: wrap;
  gap: .625rem;
  margin: .25rem 0 0;
}

.notfound__grid { display: grid; gap: .625rem; margin-top: .5rem; }

.notfound__grid-title {
  margin: 0;
  font-size: var(--step--2);
  font-weight: 600;
  color: var(--text-muted);
}

.notfound__links {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.notfound__links a {
  display: inline-flex;
  align-items: center;
  min-height: 40px;
  padding: 0 .875rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: var(--step--1);
  color: var(--ink);
  text-decoration: none;
}

.notfound__links a:hover { border-color: var(--ink); }

/* --- хлебные крошки --- */
.crumbs { font-size: var(--step--2); color: var(--text-muted); }
.crumbs ol { display: flex; flex-wrap: wrap; align-items: center; gap: .375rem .5rem; }
.crumbs li { display: flex; align-items: center; gap: .5rem; }
.crumbs li + li::before { content: '/'; opacity: .45; }
/* Крошки — самостоятельные элементы управления, поэтому им нужна высота цели
   нажатия не меньше 24 px (WCAG 2.5.8), а не высота строки. */
.crumbs a,
.crumbs [aria-current] { display: inline-flex; align-items: center; min-height: 26px; }
.crumbs a { text-decoration: underline; text-underline-offset: .2em; text-decoration-color: var(--line-strong); }
.crumbs a:hover { color: var(--signal); }
.crumbs [aria-current] { color: var(--text); }

/* --- раскладка каталога --- */
.catalog { display: grid; gap: clamp(1.25rem, 2.5vw, 2.5rem); }

@media (min-width: 64rem) {
  .catalog { grid-template-columns: minmax(0, 15.5rem) minmax(0, 1fr); align-items: start; }
}

.catalog__main { min-width: 0; }

.catalog__toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .75rem 1rem;
  padding-bottom: 1rem;
  margin-bottom: 1rem;
  border-bottom: 1px solid var(--line);
}

.catalog__total { font-size: var(--step--1); color: var(--text-muted); margin-inline-end: auto; }

.catalog__sort { display: flex; flex-wrap: wrap; gap: .25rem .875rem; }

.catalog__sort-link {
  padding-block: .25rem;
  font-size: var(--step--2);
  color: var(--text-muted);
  border-bottom: 1.5px solid transparent;
}

.catalog__sort-link:hover { color: var(--text); }
.catalog__sort-link.is-active { color: var(--text); border-color: var(--signal); }

/* Выбор пола прямо над списком — на телефоне (017Ca §13, §14).

   ПОЧЕМУ ОН ПОЯВИЛСЯ. Пол живёт в боковой колонке, а на телефоне боковая колонка
   превращается в панель, которую надо открыть кнопкой «Фильтры». Назначение при
   этом видно сразу — чипами на главной и крошками, — и покупатель на телефоне
   думал, что пола у каталога просто нет (приёмка 017C, дефект 3).

   Это НЕ второй фильтр: адреса и счётчики те же самые, из того же фасета. На
   десктопе ряд скрыт — там выбор стоит в колонке, и два одинаковых элемента
   управления на одном экране путают.

   Ряд ПЕРЕНОСИТСЯ, а не прокручивается вбок. Первый вариант был прокручиваемым —
   и это тихо воспроизводило исходный дефект: «Женские» уезжали за край, то есть
   снова оказывались спрятанными. Смысл правки ровно в том, чтобы все группы были
   видны сразу; вторая строка на узком экране — приемлемая за это цена. */
.genderbar {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
  margin-bottom: 1rem;
}

.genderbar .chip {
  flex: none;
  /* Цель для пальца: ряд стоит первым на экране каталога и нажимается чаще
     всего остального (§21). */
  min-height: 40px;
  padding-inline: .875rem;
  font-size: var(--step--1);
}

@media (min-width: 64rem) { .genderbar { display: none; } }

.catalog__active { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; margin-bottom: 1.25rem; }
/* «Сбросить фильтры» — отдельное ДЕЙСТВИЕ, а не слово в предложении, поэтому
   цель обязана быть не меньше 24 px по высоте: 016A §52 нашёл её в 17 px рядом с
   чипами фильтров, где палец промахивается мимо и попадает в соседний чип. */
.catalog__reset {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
  font-size: var(--step--2);
  color: var(--text-muted);
  text-decoration: underline;
  text-underline-offset: .2em;
}
.catalog__reset:hover { color: var(--signal); }

.chip--action { transition: border-color var(--fast) var(--ease), background var(--fast) var(--ease); }
.chip--action:hover { border-color: var(--line-strong); }
.chip--action.is-active { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.chip--remove { cursor: pointer; }
.chip--remove:hover { border-color: var(--signal); color: var(--signal); }

/* --- фасеты --- */
.catalog__filters-head { display: none; }
.catalog__filters-body { display: grid; gap: clamp(1.25rem, 2vw, 1.75rem); }

@media (min-width: 64rem) {
  .catalog__filters { position: sticky; top: calc(var(--header-h) + 1rem); }
  .catalog__filters-open { display: none; }
}

.facet { display: grid; gap: .625rem; }
.facet--search { grid-auto-flow: column; grid-template-columns: minmax(0, 1fr) auto; gap: .5rem; align-items: center; }

.field {
  width: 100%;
  min-height: 40px;
  padding: .5rem .875rem;
  background: transparent;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-pill);
  font: inherit;
  font-size: var(--step--1);
  color: inherit;
}

.field::placeholder { color: var(--text-muted); }

.facet__title {
  font-family: var(--font-display);
  font-size: var(--step--2);
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.facet__list { display: grid; }

.facet__link {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  min-height: 38px;
  padding-block: .375rem;
  font-size: var(--step--1);
  border-bottom: 1px solid var(--line);
}

.facet__link:hover { color: var(--signal); }
.facet__link.is-active { font-weight: 600; }
.facet__link.is-active span:first-child { text-decoration: underline; text-decoration-color: var(--signal); text-underline-offset: .25em; }

.facet__count { color: var(--text-muted); font-variant-numeric: tabular-nums; font-size: var(--step--2); }
.facet__chips { display: flex; flex-wrap: wrap; gap: .5rem; }
.facet__sizes { display: grid; grid-template-columns: repeat(auto-fill, minmax(3.25rem, 1fr)); gap: .375rem; }

.size--link { text-decoration: none; }
.size--link.is-active { background: var(--ink); border-color: var(--ink); color: var(--paper); }

/* Панель фильтров на телефоне — тот же приём, что у меню: своя кнопка закрытия,
   потому что оверлей перекрывает шапку. */
@media (max-width: 63.99rem) {
  .catalog__filters {
    position: fixed;
    inset: 0;
    z-index: 96;
    display: grid;
    grid-template-rows: auto 1fr;
    gap: 1rem;
    padding: calc(var(--gutter) + env(safe-area-inset-top)) var(--gutter) calc(var(--gutter) + env(safe-area-inset-bottom));
    background: var(--paper);
    opacity: 0;
    visibility: hidden;
    transform: translateY(1.5rem);
    transition: opacity var(--base) var(--ease), transform var(--base) var(--ease-out), visibility var(--base);
    overflow-y: auto;
  }

  .catalog__filters.is-open { opacity: 1; visibility: visible; transform: none; }

  .catalog__filters-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    position: sticky;
    top: 0;
    padding-block: .5rem;
    background: var(--paper);
  }

  .catalog__filters-head .menu__close { color: var(--ink); border-color: var(--line-strong); }
  .catalog__filters-head .menu__close:hover { background: rgba(11, 13, 15, .06); }
  .catalog__filters-body { align-content: start; }
}

/* --- пустое состояние и постраничная навигация --- */
.grid__empty { display: grid; gap: .75rem; justify-items: center; }
.grid__empty-title { font-family: var(--font-display); font-size: var(--step-2); font-weight: 600; color: var(--text); }
.grid__empty p { max-width: 52ch; }
.grid__empty-actions { display: flex; flex-wrap: wrap; gap: .625rem; justify-content: center; margin-top: .75rem; }

.pager { display: flex; flex-wrap: wrap; gap: .375rem; margin-top: clamp(1.5rem, 3vw, 2.5rem); }

.pager__link {
  display: grid;
  place-items: center;
  min-width: 42px;
  min-height: 42px;
  padding: .25rem .625rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  font-family: var(--font-display);
  font-size: var(--step--1);
  font-weight: 600;
}

.pager__link:hover { border-color: var(--line-strong); }
.pager__link.is-active { background: var(--ink); border-color: var(--ink); color: var(--paper); }

/* --- страница товара --- */
.pdp { display: grid; gap: clamp(1.5rem, 3vw, 3rem); margin-block: clamp(1rem, 2vw, 2rem) clamp(2rem, 4vw, 3.5rem); }

@media (min-width: 62rem) {
  .pdp { grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr); align-items: start; }
  .pdp__media { position: sticky; top: calc(var(--header-h) + 1.5rem); }
}

.pdp__stage {
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 4 / 3;
  padding: clamp(1rem, 3vw, 2.5rem);
  background: var(--pdp-ground, var(--ink-3));
  border-radius: var(--radius-lg);
  overflow: hidden;
}

.pdp__stage img { width: min(100%, 620px); }

.pdp__thumbs { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: .625rem; }

.pdp__thumb {
  display: grid;
  place-items: center;
  width: 4.5rem;
  aspect-ratio: 1;
  padding: .25rem;
  background: var(--thumb-ground, var(--ink-3));
  border: 2px solid transparent;
  border-radius: var(--radius);
  overflow: hidden;
}

.pdp__thumb.is-active { border-color: var(--signal); }
.pdp__thumb-empty { color: var(--paper); opacity: .6; }

.pdp__info { display: grid; gap: 1rem; align-content: start; min-width: 0; }
.pdp__title { font-size: var(--step-4); }
.pdp__tagline { color: var(--text-muted); font-size: var(--step-1); max-width: var(--measure); }

.pdp__price {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: .375rem .875rem;
  padding-block: 1rem;
  border-block: 1px solid var(--line);
}

.money--xl { font-size: var(--step-3); }
.pdp__price-note { width: 100%; font-size: var(--step--2); color: var(--text-muted); max-width: 52ch; }
.pdp__signal { justify-self: start; }

.pdp__group { display: grid; gap: .625rem; }

.pdp__group-title {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  font-family: var(--font-display);
  font-size: var(--step--2);
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.pdp__group-value { text-transform: none; letter-spacing: 0; color: var(--text); font-weight: 500; }

.pdp__link {
  display: inline-flex;
  align-items: center;
  min-height: 26px;
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  font-family: var(--font-display);
  font-size: var(--step--2);
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--text-muted);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: .2em;
}

.pdp__link:hover { color: var(--signal); }

.colorway.is-active { border-color: var(--ink); background: var(--paper-2); }

.pdp__hint {
  padding: .75rem .875rem;
  background: var(--paper-2);
  border-radius: var(--radius);
  font-size: var(--step--2);
  color: var(--text-muted);
}

.pdp__actions { display: grid; gap: .625rem; }
/* Каналы на странице товара живут по тому же правилу, что и остальные ряды
   действий: колонка не уже подписи, иначе кнопка снова начнёт рвать текст.
   14rem — ширина самой длинной из них («Написать в WhatsApp →») с запасом. */
.pdp__channels { display: grid; gap: .5rem; grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr)); }
.pdp__note { font-size: var(--step--2); color: var(--text-muted); max-width: var(--measure); }

.pdp__section { padding-top: clamp(1.75rem, 3vw, 2.75rem); border-top: 1px solid var(--line); margin-top: clamp(1.75rem, 3vw, 2.75rem); }
.pdp__section-title { font-size: var(--step-2); margin-bottom: 1rem; }
.pdp__prose { max-width: var(--measure); color: var(--text-muted); }

.specs { display: grid; gap: 1px; background: var(--line); border-block: 1px solid var(--line); max-width: 44rem; }
.specs__row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr); gap: 1rem; padding: .625rem 0; background: var(--paper); }
.specs dt { color: var(--text-muted); font-size: var(--step--1); }
.specs dd { margin: 0; font-size: var(--step--1); }

.pdp__source { margin-top: 1rem; font-size: var(--step--2); color: var(--text-muted); max-width: var(--measure); }
.pdp__source a { text-decoration: underline; text-underline-offset: .2em; }
.pdp__source a:hover { color: var(--signal); }

.pdp__buyout { display: grid; gap: 1px; background: var(--line); border-block: 1px solid var(--line); }

@media (min-width: 52rem) { .pdp__buyout { grid-template-columns: repeat(3, 1fr); } }

.pdp__buyout li { background: var(--paper); padding: 1rem clamp(0rem, 1.5vw, 1.25rem) 1.25rem; display: grid; gap: .375rem; align-content: start; }
.pdp__buyout li:first-child { padding-inline-start: 0; }
.pdp__buyout h3 { font-size: var(--step-0); }
.pdp__buyout p { color: var(--text-muted); font-size: var(--step--2); }

/* Липкая полоса действия на телефоне. */
.pdp__bar {
  position: fixed;
  inset-inline: 0;
  bottom: 0;
  z-index: 80;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: .625rem var(--gutter) calc(.625rem + env(safe-area-inset-bottom));
  background: var(--paper);
  border-top: 1px solid var(--line-strong);
  box-shadow: 0 -10px 30px -22px rgba(11, 13, 15, .8);
}

@media (min-width: 62rem) { .pdp__bar { display: none; } }

.pdp__bar-price { display: grid; line-height: 1.2; }
.pdp__bar-price span:last-child { font-size: var(--step--2); color: var(--text-muted); }

/* --- таблица размеров в диалоге --- */
.sheet--guide { width: min(100%, 46rem); }
.sheet--guide .sheet__panel { max-height: min(88vh, 800px); overflow-y: auto; }

.sheet__guide-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  position: sticky;
  top: calc(var(--sheet-pad) * -1);
  padding-block: .5rem;
  margin-block-start: calc(var(--sheet-pad) * -1);
  background: var(--paper);
  z-index: 1;
}

.sheet__guide-head .menu__close { color: var(--ink); border-color: var(--line-strong); flex: none; }
.sheet__guide-head .menu__close:hover { background: rgba(11, 13, 15, .06); }

/* =====================================================================
   16. Подборка, заявка и статус (итерация 003)

   Отдельный слой поверх принятой системы: те же токены, те же карточки и
   чипы, что в каталоге и на странице товара. Стандартных экранов OpenCart
   на витрине нет ни одного.
   ===================================================================== */

.notice {
  padding: .75rem 1rem;
  margin: 0 0 1.25rem;
  border: 1px solid var(--line);
  border-left-width: 3px;
  border-radius: var(--radius);
  font-size: var(--step--1);
}

.notice--ok   { border-left-color: var(--jade); }
.notice--warn { border-left-color: var(--amber); }

/* Ловушка для ботов: вне потока и вне доступности, но не display:none —
   часть ботов такие поля пропускает. */
.honeypot {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* --- Подборка --------------------------------------------------------- */

.basket__head { max-width: 46rem; margin-bottom: 2rem; }
.basket__title { font-size: var(--step-4); margin: .5rem 0 .75rem; }
.basket__lead { color: var(--text-muted); max-width: 40rem; }

.basket__grid {
  display: grid;
  gap: 1.5rem;
  align-items: start;
}

@media (min-width: 62rem) {
  .basket__grid { grid-template-columns: minmax(0, 1fr) 21rem; gap: 2.5rem; }
  .basket__summary { position: sticky; top: 1.5rem; }
}

/* Элемент grid по умолчанию не ужимается меньше своего содержимого (min-width:auto),
   и длинное название модели выталкивало строку за экран на 360 px. Разрешаем сжатие
   на каждом уровне вложенности — иначе правило не работает. */
.basket__grid > *,
.request__grid > *,
.status__grid > * { min-width: 0; }

.basket__lines { display: grid; gap: .75rem; min-width: 0; }
.bline { min-width: 0; }

/* Дети grid-контейнера тоже начинаются с min-width:auto — без этого длинное
   название модели растягивало строку шире экрана на 360 px. */
.bline__body > *,
.bline__side > *,
.rlist__body > * { min-width: 0; }

.bline__title,
.bline__meta,
.rlist__body { overflow-wrap: anywhere; }

.bline {
  display: grid;
  grid-template-columns: 88px minmax(0, 1fr);
  gap: 1rem;
  padding: 1rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--paper);
}

@media (min-width: 40rem) {
  .bline { grid-template-columns: 104px minmax(0, 1fr) auto; align-items: start; }
}

.bline--missing { grid-template-columns: minmax(0, 1fr) auto; opacity: .8; }

.bline__shot {
  display: grid;
  place-items: center;
  aspect-ratio: 1;
  border-radius: var(--radius);
  background: var(--pdp-ground, var(--paper-2));
  overflow: hidden;
}

.bline__shot img { width: 100%; height: 100%; object-fit: contain; }
.bline__noimg { font-size: var(--step--2); color: rgba(255, 255, 255, .7); text-align: center; }

.bline__body { display: grid; gap: .375rem; align-content: start; min-width: 0; }
.bline__title { font-size: var(--step-0); margin: 0; }
/* Ссылка на товар в одну строку давала цель нажатия 20 px — на телефоне это мало.
   Небольшой вертикальный отступ доводит её до 26 px, не меняя вид карточки. */
.bline__title a {
  display: inline-block;
  padding-block: .3125rem;
  color: inherit;
  text-decoration: none;
}
.bline__title a:hover { text-decoration: underline; }

.bline__meta {
  display: flex;
  flex-wrap: wrap;
  column-gap: .875rem;
  row-gap: .125rem;
  font-size: var(--step--1);
  color: var(--text-muted);
  margin: 0;
}

.bline__size { white-space: nowrap; color: var(--ink); }
.bline__chip { justify-self: start; margin: .25rem 0 0; }

.bline__note {
  margin: 0;
  font-size: var(--step--2);
  color: var(--text-muted);
  max-width: 34rem;
}

.bline__side {
  display: grid;
  gap: .5rem;
  justify-items: start;
  grid-column: 1 / -1;
}

@media (min-width: 40rem) {
  .bline__side { grid-column: auto; justify-items: end; text-align: right; }
}

.bline__qty { display: flex; align-items: center; gap: .375rem; }

.bline__qty-input {
  width: 3.5rem;
  min-height: 40px;
  padding: .25rem .5rem;
  text-align: center;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  font-family: var(--font-display);
  font-weight: 600;
  background: var(--paper);
  color: var(--ink);
}

.bline__qty-apply,
.bline__remove {
  min-height: 40px;
  padding: 0 .5rem;
  background: none;
  border: 0;
  color: var(--text-muted);
  font-size: var(--step--2);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.bline__qty-apply:hover,
.bline__remove:hover { color: var(--ink); }

.bline__price { margin: 0; display: grid; gap: .125rem; }
.bline__unit { font-size: var(--step--2); color: var(--text-muted); }

/* Текстовые ссылки страниц заявки — полноценные цели нажатия: 22 px высоты
   строки для пальца мало, а аудит доступности требует минимум 24. */
.basket__more,
.status__more {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  margin-top: .25rem;
  font-size: var(--step--1);
  color: var(--text-muted);
}

.basket__ask a,
.status__link-hint a {
  display: inline-block;
  padding: .25rem 0;
  min-height: 24px;
}

.basket__card {
  display: grid;
  gap: 1rem;
  padding: 1.25rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--paper-2);
}

.basket__card-title { font-size: var(--step-1); margin: 0; }

.basket__total,
.basket__delivery {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  margin: 0;
  flex-wrap: wrap;
}

.basket__delivery { font-size: var(--step--2); color: var(--text-muted); }

.basket__facts {
  display: grid;
  gap: .5rem;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--step--2);
  color: var(--text-muted);
}

.basket__facts li { padding-left: 1rem; position: relative; }
.basket__facts li::before { content: '·'; position: absolute; left: .25rem; }

.basket__ask { margin: 0; font-size: var(--step--2); color: var(--text-muted); }

.basket__empty {
  display: grid;
  gap: .75rem;
  justify-items: start;
  max-width: 36rem;
  padding: 2rem;
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius-lg);
}

.basket__empty h2 { font-size: var(--step-2); margin: 0; }
.basket__empty p { color: var(--text-muted); margin: 0; }
.basket__empty-actions { display: flex; flex-wrap: wrap; gap: .625rem; margin-top: .5rem; }

/* --- Заявка ----------------------------------------------------------- */

.request__head { max-width: 46rem; margin-bottom: 2rem; }
.request__title { font-size: var(--step-4); margin: .5rem 0 .75rem; }
.request__lead { color: var(--text-muted); max-width: 42rem; }

.request__grid { display: grid; gap: 1.5rem; align-items: start; }

@media (min-width: 62rem) {
  .request__grid { grid-template-columns: minmax(0, 1fr) 21rem; gap: 2.5rem; }
  .request__aside { position: sticky; top: 1.5rem; }
}

.request__main { display: grid; gap: 1.25rem; min-width: 0; }

.field { display: grid; gap: .375rem; border: 0; padding: 0; margin: 0; min-width: 0; }

.field__label {
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: .01em;
}

.field__opt { font-weight: 400; color: var(--text-muted); }

.field__input {
  width: 100%;
  min-height: 48px;
  padding: .625rem .875rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--paper);
  color: var(--ink);
  font: inherit;
  font-size: max(16px, var(--step--1)); /* 16px не даёт iOS зумить поле при фокусе */
}

.field__input:focus-visible { outline: 2px solid var(--ink); outline-offset: 1px; }
.field__input--area { min-height: 96px; resize: vertical; line-height: 1.5; }
.field__input--sm { min-height: 40px; font-size: var(--step--2); }
.field__input--bad { border-color: var(--amber); }

.field__hint { margin: 0; font-size: var(--step--2); color: var(--text-muted); }
.field__error { margin: 0; font-size: var(--step--2); color: var(--amber); }

.choices { display: flex; flex-wrap: wrap; gap: .5rem; }

.choice {
  position: relative;
  display: inline-flex;
  align-items: center;
  min-height: 46px;
  padding: .5rem 1.125rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-pill);
  cursor: pointer;
  font-size: var(--step--1);
  font-weight: 500;
}

.choice input { position: absolute; opacity: 0; width: 1px; height: 1px; pointer-events: none; }
.choice:has(input:checked) { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.choice:has(input:focus-visible) { outline: 2px solid var(--ink); outline-offset: 2px; }

.field--consent { margin-top: .25rem; }

.consent {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: .625rem;
  align-items: start;
  font-size: var(--step--2);
  color: var(--text-muted);
  cursor: pointer;
}

.consent input {
  width: 20px;
  height: 20px;
  margin-top: .125rem;
  accent-color: var(--ink);
}

.request__submit { display: grid; gap: .75rem; justify-items: center; margin-top: .5rem; }
.request__back {
  background: none;
  border: 0;
  color: var(--text-muted);
  font: inherit;
  font-size: var(--step--2);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
  min-height: 44px;
}

.request__promise {
  padding: 1rem 1.125rem;
  margin: 0;
  background: var(--paper-2);
  border-radius: var(--radius);
  font-size: var(--step--1);
  color: var(--text-muted);
}

.request__promise strong { color: var(--ink); }

.rcard {
  display: grid;
  gap: .875rem;
  padding: 1.25rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--paper);
}

.rcard__head { display: flex; justify-content: space-between; align-items: center; gap: 1rem; flex-wrap: wrap; }
.rcard__title { font-size: var(--step-1); margin: 0; }

.rcard__edit {
  background: none;
  border: 0;
  color: var(--text-muted);
  font: inherit;
  font-size: var(--step--2);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
  min-height: 44px;
}

.rcard__rows { display: grid; gap: .625rem; margin: 0; }
.rcard__rows > div { display: grid; grid-template-columns: 10rem minmax(0, 1fr); gap: .75rem; }
.rcard__rows dt { color: var(--text-muted); font-size: var(--step--2); }
.rcard__rows dd { margin: 0; overflow-wrap: anywhere; }

@media (max-width: 30rem) {
  .rcard__rows > div { grid-template-columns: 1fr; gap: .125rem; }
}

.rlist { display: grid; gap: .75rem; margin: 0; padding: 0; list-style: none; }

.rlist__item {
  display: grid;
  grid-template-columns: 56px minmax(0, 1fr) auto;
  gap: .75rem;
  align-items: center;
}

.rlist__shot {
  display: grid;
  place-items: center;
  aspect-ratio: 1;
  border-radius: var(--radius);
  background: var(--pdp-ground, var(--paper-2));
  overflow: hidden;
}

.rlist__shot img { width: 100%; height: 100%; object-fit: contain; }
.rlist__body { display: grid; gap: .125rem; min-width: 0; font-size: var(--step--1); }
.rlist__meta { font-size: var(--step--2); color: var(--text-muted); }
.rlist__price { white-space: nowrap; font-size: var(--step--1); }
.rlist--compact .rlist__item { grid-template-columns: 44px minmax(0, 1fr) auto; }

/* --- Статус заявки ----------------------------------------------------- */

.status__shell { display: grid; gap: 1.75rem; }
.status__hero { max-width: 46rem; }
.status__title { font-size: var(--step-3); margin: .5rem 0 .75rem; overflow-wrap: anywhere; }
.status__lead { color: var(--text-muted); }
.status__lead strong { color: var(--ink); }

.status__ok {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  margin: 0;
  color: var(--jade);
  font-size: var(--step--1);
  font-weight: 600;
}

.status__tick {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--jade) 14%, transparent);
}

.status__grid { display: grid; gap: 1.5rem; align-items: start; }

@media (min-width: 62rem) {
  .status__grid { grid-template-columns: minmax(0, 1fr) 21rem; gap: 2.5rem; }
  .status__aside { position: sticky; top: 1.5rem; }
}

.status__main { display: grid; gap: 1rem; min-width: 0; }
.status__hint,
.status__note,
.status__contact { margin: 0; font-size: var(--step--2); color: var(--text-muted); }
.status__contact strong { color: var(--ink); }

.timeline { display: grid; gap: .75rem; margin: 0; padding: 0; list-style: none; }

.timeline__item {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: .625rem;
  align-items: start;
  color: var(--text-muted);
  font-size: var(--step--2);
}

.timeline__dot {
  width: .5rem;
  height: .5rem;
  margin-top: .375rem;
  border-radius: 50%;
  background: var(--line-strong);
}

.timeline__item.is-current { color: var(--ink); }
.timeline__item.is-current .timeline__dot { background: var(--jade); }
.timeline__body { display: grid; gap: .125rem; }
.timeline__body time { font-size: var(--step--2); color: var(--text-muted); }

.status__link { display: grid; gap: .375rem; }
.status__link-title { margin: 0; font-size: var(--step--1); font-weight: 600; }
.status__link-hint { margin: 0; font-size: var(--step--2); color: var(--text-muted); }


/* --- Мелочи страницы товара -------------------------------------------- */

.pdp__add { margin-top: .25rem; }

.pdp__add-note {
  margin: .5rem 0 0;
  font-size: var(--step--2);
  color: var(--text-muted);
}

.pdp__add-note.is-warn { color: var(--amber); }

.masthead__count {
  display: inline-grid;
  place-items: center;
  min-width: 1.375rem;
  height: 1.375rem;
  margin-left: .375rem;
  padding: 0 .3125rem;
  border-radius: var(--radius-pill);
  background: var(--paper);
  color: var(--ink);
  font-size: var(--step--2);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.btn.is-busy { opacity: .6; pointer-events: none; }

/* Согласованный заказ на странице покупателя — главный блок, поэтому он выделен
   рамкой, а отправленная заявка убрана в раскрывающийся вторичный блок. */
.rcard--agreed { border-color: color-mix(in srgb, var(--jade) 40%, var(--line)); }

.rcard--history { gap: .75rem; }
.rcard--history > summary {
  display: flex;
  align-items: center;
  min-height: 44px;
  font-size: var(--step--1);
  font-weight: 600;
  color: var(--text-muted);
  cursor: pointer;
}

.rcard--history > summary:hover { color: var(--ink); }

/* Оплата и выкуп на странице покупателя. */
.status__note--ok { color: var(--jade); }
.status__pay { display: grid; gap: .5rem; margin: 0; }

.status__sources {
  display: grid;
  gap: .25rem;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--step--2);
  color: var(--text-muted);
}

/* --- Отправка и доставка на странице покупателя (итерация 006) -----------

   Посылок может быть несколько, и каждая — самостоятельный блок: покупатель не
   должен догадываться, что в какой едет. Трек-номера бывают длинными и
   нечитаемыми, поэтому они переносятся и набраны моноширинным начертанием. */
.rcard--parcel { gap: .875rem; }
.rcard--alert { border-color: color-mix(in srgb, var(--amber) 44%, var(--line)); }
.status__note--warn { color: var(--amber); }

.parcel__facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  gap: .625rem 1rem;
  margin: 0;
}

.parcel__fact { display: grid; gap: .125rem; min-width: 0; }
.parcel__fact--wide { grid-column: 1 / -1; }
.parcel__fact dt { font-size: var(--step--2); color: var(--text-muted); }

.parcel__fact dd {
  margin: 0;
  font-size: var(--step--1);
  /* Длинный адрес пункта выдачи и длинное название перевозчика ломаются по
     месту, а не растягивают страницу вбок. */
  overflow-wrap: anywhere;
}

.parcel__track {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  letter-spacing: .01em;
}

.parcel__title {
  margin: 0;
  font-size: var(--step--2);
  font-weight: 600;
  color: var(--text-muted);
}

/* Состав посылки — без картинок и цен: здесь важно «что внутри», а не витрина. */
.rlist--parcel { gap: .375rem; }
.rlist--parcel .rlist__item { grid-template-columns: minmax(0, 1fr); gap: 0; }
.timeline--parcel { font-size: var(--step--2); }

/* --- Правовые документы (013A) ------------------------------------------------------
   Юридический текст читают глазами, а не сканируют: узкая колонка, крупный интерлиньяж
   и обычный размер шрифта. «Мелким шрифтом, чтобы влезло» — ровно то, чего здесь быть
   не должно. */
.legal__shell { max-width: 64rem; }

.legal__head { padding-block: clamp(1.5rem, 4vw, 2.5rem) 0; }
.legal__title { font-size: clamp(1.75rem, 4vw, 2.5rem); line-height: 1.15; margin: .5rem 0 0; }
.legal__lead { color: var(--muted); font-size: var(--step-1); line-height: 1.55; margin-top: 1rem; max-width: 46ch; }
.legal__meta { color: var(--muted); font-size: var(--step--1); margin-top: 1rem; }

/* Колонка — `minmax(0, 1fr)`, а не неявная `auto` (017Cabj): `auto` растёт до самой
   длинной НЕРАЗРЫВНОЙ строки текста, а в политике это адрес расширения Firefox
   (~360 px). На телефоне документ становился шире экрана, правый край текста
   уезжал за границу, а оглавление растягивалось вместе с колонкой. */
.legal__body { display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(1.5rem, 4vw, 2.5rem); margin-top: clamp(1.75rem, 4vw, 2.5rem); }

@media (min-width: 60rem) {
  /* Оглавление уезжает вбок и остаётся на виду при прокрутке — так в длинном документе
     видно, где ты находишься. */
  .legal__body { grid-template-columns: 15rem minmax(0, 1fr); align-items: start; gap: 3rem; }
  .legal__toc { position: sticky; top: 5rem; }
}

.legal__toc { border-left: 2px solid var(--line); padding-left: 1rem; }
.legal__toc-title { font-size: var(--step--1); text-transform: uppercase; letter-spacing: .08em; color: var(--muted); margin: 0 0 .625rem; }
.legal__toc ol { margin: 0; padding: 0 0 0 1.125rem; display: grid; grid-template-columns: minmax(0, 1fr); gap: .375rem; }
.legal__toc a { color: var(--text); text-decoration: none; font-size: var(--step--1); line-height: 1.4; }
.legal__toc a:hover { text-decoration: underline; }

.legal__section { margin-bottom: 2.25rem; scroll-margin-top: 5rem; }
.legal__section h2 { font-size: var(--step-1); line-height: 1.25; margin: 0 0 .75rem; }

/* Колонка шире прежнего, но не «во всю страницу»: 78ch — верх комфортной строки, и
   ровно та ширина, на которой выключка по формату перестаёт рвать текст пробелами
   (015Aa §4, §5). Заголовки, кнопки и навигация не выключаются никогда: у коротких
   строк выключка даёт дыры, а не ровный край. */
.legal__section p,
.legal__list {
  max-width: 78ch;
  text-align: justify;
  text-justify: inter-word;
  hyphens: auto;
  -webkit-hyphens: auto;
  hyphenate-limit-chars: 6 3 3;
  overflow-wrap: break-word;
}

.legal__section p { line-height: 1.7; margin: 0 0 .875rem; }
/* Та же `minmax(0, 1fr)`, что у `.legal__body`: неразрывный адрес в пункте списка
   иначе растит неявную колонку списка шире экрана (017Cabj). */
.legal__list { margin: 0 0 1rem; padding-left: 1.25rem; display: grid; grid-template-columns: minmax(0, 1fr); gap: .375rem; }
.legal__list li { line-height: 1.6; }

/* Совсем узкий экран — единственное место, где выключка проигрывает: в колонку
   помещается четыре-пять русских слов, и переносы уже не спасают. Порог взят ниже
   целевой ширины приёмки: на 390 px выключка сохраняется, как просил владелец, а
   разваливается она только на совсем маленьких экранах. */
@media (max-width: 21rem) {
  .legal__section p,
  .legal__list { text-align: start; }
}

.legal__memo-cta { border: 1px solid var(--line); border-radius: var(--radius); padding: 1.25rem; background: var(--surface-2, transparent); }
.legal__memo-cta h2 { margin-top: 0; }

.legal__seller { border-top: 1px solid var(--line); margin-top: 2rem; padding-top: 1.5rem; }
.legal__seller-title { font-size: var(--step-0); margin: 0 0 .75rem; }
.legal__seller-name { font-weight: 600; margin: 0 0 .75rem; }
.legal__seller-rows { display: grid; gap: .5rem; margin: 0 0 1.25rem; }
.legal__seller-rows > div { display: grid; grid-template-columns: 9rem minmax(0, 1fr); gap: .75rem; font-size: var(--step--1); }
.legal__seller-rows dt { color: var(--muted); margin: 0; }
.legal__seller-rows dd { margin: 0; overflow-wrap: anywhere; }
.legal__other { font-size: var(--step--1); color: var(--muted); }

@media (max-width: 40rem) {
  /* На телефоне подпись над значением читается лучше, чем сжатая колонка в 9rem. */
  .legal__seller-rows > div { grid-template-columns: 1fr; gap: .125rem; }
}

.footer__seller { color: var(--text-invert-mut); font-size: var(--step--1); margin-bottom: .5rem; overflow-wrap: anywhere; }

/* Полоса предпросмотра черновика (015A §35). Цвет предупреждающий, а не фирменный:
   это служебное состояние, и оно не должно выглядеть частью витрины. */
.preview-bar {
  border: 1px solid #d9a300;
  border-left-width: 4px;
  border-radius: var(--radius);
  background: #fff8e5;
  color: #4a3800;
  padding: .75rem 1rem;
  margin: 1rem 0 0;
  font-size: var(--step--1);
  line-height: 1.5;
}

/* --------------------------------------------------------------------------
   15. Связь: шапка, подвал, подборка (015Ac §10, §11, §23, §43)
   --------------------------------------------------------------------------
   Одно оформление на все места, где покупатель может написать живому человеку.
   До 015Ac связь была текстом в подвале, текстовой ссылкой в подборке и не
   существовала в шапке — три разных решения одной задачи (приёмка, пункты 6,
   10, 12, 16).
   -------------------------------------------------------------------------- */

.iconlink {
  display: inline-grid;
  place-items: center;
  /* 40 px — минимальная цель для пальца; иконка внутри меньше. */
  width: 40px;
  height: 40px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  color: inherit;
  transition: border-color var(--fast) var(--ease), background var(--fast) var(--ease),
              color var(--fast) var(--ease);
}

.iconlink:hover { border-color: var(--line-strong); background: rgba(11, 13, 15, .06); }
.iconlink:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }

/* Над тёмным первым экраном шапка прозрачная — граница и подсветка меняются
   вместе с ней, иначе иконки «висят» белыми плашками. */
.masthead--over .iconlink { border-color: var(--line-invert); }
.masthead--over .iconlink:hover { background: rgba(244, 241, 235, .12); }

/* Фирменные цвета мессенджеров — ТОЛЬКО при наведении и фокусе: в покое ряд
   иконок должен читаться как один элемент управления, а не как гирлянда. */
.iconlink--telegram:hover { color: #2AABEE; }
.iconlink--whatsapp:hover { color: #25D366; }
.iconlink--max:hover      { color: #7B4DFF; }

/* СВЯЗЬ ЕСТЬ НА ЛЮБОЙ ШИРИНЕ (017Ca §16).

   Раньше ряд иконок включался только с 48rem, и это значило буквально следующее:
   повернув телефон из альбомной в портретную, покупатель терял Telegram, WhatsApp
   и MAX — три единственных способа задать вопрос живому человеку. Владелец снял
   ровно это. Способ связаться не может зависеть от того, как человек держит
   телефон.

   Место находится за счёт размера, а не за счёт другого действия (§20): в узкой
   шапке иконки становятся 36 px и стоят плотнее. Подборка и меню остаются на
   месте. Подписанный словами список в развёрнутом меню тоже остаётся — он и
   раньше был, и дублировать его не вредно: там есть место на слова. */
.masthead__contact { display: inline-flex; gap: .25rem; }

@media (min-width: 48rem) { .masthead__contact { gap: .375rem; } }

/* Цель нажатия в узкой шапке — 36 px. Это меньше 44 px, но ряд стоит в одну
   строку с логотипом и кнопкой, и 44 px там означало бы выбросить кнопку
   подборки. Соседние цели не перекрываются (§21). */
@media (max-width: 47.99rem) {
  .masthead__contact .iconlink { width: 36px; height: 36px; }
}

.menu__contact { display: grid; gap: .5rem; }

.menu__contact-title {
  font-size: var(--step--2);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-invert-mut);
}

.menu__contact-list { display: flex; flex-wrap: wrap; gap: .5rem; }

.iconlink--wide {
  width: auto;
  min-height: 44px;
  padding-inline: .875rem;
  gap: .5rem;
  grid-auto-flow: column;
  border-color: var(--line-invert);
  font-size: var(--step--1);
  font-weight: 600;
}

.iconlink--wide:hover { background: rgba(244, 241, 235, .1); }

/* --- Подвал --- */

.footer__contact { display: grid; gap: .625rem; list-style: none; }

.footer__contact-link {
  display: inline-flex;
  align-items: center;
  gap: .625rem;
  color: var(--text-invert-mut);
  text-decoration: none;
}

.footer__contact-link:hover { color: var(--paper); }

.footer__contact-icon {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  flex: none;
  border: 1px solid var(--line-invert);
  border-radius: var(--radius);
}

.footer__contact-body { display: grid; gap: .0625rem; }
.footer__contact-label { font-weight: 600; color: var(--paper); font-size: var(--step--1); }
.footer__contact-value { font-size: var(--step--2); font-variant-numeric: tabular-nums; }

/* --- Блок помощи в подборке --- */

.askbox {
  margin-top: 1.25rem;
  padding: 1rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--paper-2);
}

.askbox__title { font-family: var(--font-display); font-weight: 700; font-size: var(--step-0); }
.askbox__note { margin-top: .25rem; font-size: var(--step--2); color: var(--text-muted); }

.askbox__actions { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: .75rem; }

.askbtn {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  min-height: 44px;
  /* Та же причина, что у `.btn`: подпись канала — команда, а не абзац. */
  white-space: nowrap;
  max-width: 100%;
  padding-inline: .875rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--paper);
  color: var(--ink);
  text-decoration: none;
  font-size: var(--step--1);
  font-weight: 600;
  transition: border-color var(--fast) var(--ease), color var(--fast) var(--ease);
}

.askbtn:hover { border-color: currentColor; }
.askbtn:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }

/* --------------------------------------------------------------------------
   16. Витрина первого экрана (015Ac §17, §18)
   --------------------------------------------------------------------------
   Несколько настоящих пар сменяют друг друга: одна главная, соседние — позади,
   с уменьшением и сдвигом. Вся анимация на transform и opacity, поэтому
   разметка не пересчитывается и сдвига не возникает.

   Геометрия сцены задана СООТНОШЕНИЕМ СТОРОН, а не содержимым: место под кадр
   занято до того, как загрузилась первая фотография. Именно это, а не задержка
   показа, убирает прыжок первого экрана (приёмка, пункт 9).
   -------------------------------------------------------------------------- */

.showcase { position: relative; }

.showcase__stage {
  position: relative;
  aspect-ratio: 1 / 1;
  /* Кадры выходят за края сцены при повороте — обрезать их нельзя. */
  overflow: visible;
  transform-style: preserve-3d;
  perspective: 1200px;
}

.showcase__slide {
  position: absolute;
  inset: 0;
  margin: 0;
  display: grid;
  place-items: center;
  /* Кадры за главным не должны перехватывать курсор и фокус. */
  pointer-events: none;
  will-change: transform, opacity;
  /* Кадр «приезжает» за `--showcase-shift`, прозрачность догоняет чуть раньше:
     так новая пара становится главной до того, как предыдущая доедет назад, и
     смена читается боковым зрением, а не превращается в мигание. */
  transition: transform var(--showcase-shift) var(--ease-out),
              opacity calc(var(--showcase-shift) * .82) var(--ease-out);
}

.showcase__slide img {
  /* Кадр повёрнут, поэтому по диагонали он занимает больше, чем по ширине:
     при 100% пара упиралась в край сцены и обрезалась. 88% оставляют место
     повороту и тени. */
  width: min(88%, 560px);
  filter: drop-shadow(0 32px 52px rgba(0, 0, 0, .5));
}

/* Главный кадр. Небольшой наклон — тот же приём, что был у одиночного кадра. */
.showcase__slide[data-showcase-position='0'],
.showcase__slide.is-current {
  opacity: 1;
  transform: translate3d(0, 0, 0) scale(1) rotate(-7deg);
  z-index: 3;
}

/* Ближний кадр за главным: меньше, правее и глубже. */
.showcase__slide[data-showcase-position='1'] {
  opacity: .38;
  transform: translate3d(14%, 6%, -140px) scale(.78) rotate(-2deg);
  z-index: 2;
}

/* Дальний кадр. */
.showcase__slide[data-showcase-position='2'] {
  opacity: .18;
  transform: translate3d(-12%, 10%, -260px) scale(.64) rotate(-12deg);
  z-index: 1;
}

/* Остальные ждут за сценой: они не видны и не влияют на композицию. */
.showcase__slide[data-showcase-position='rest'] {
  opacity: 0;
  transform: translate3d(0, 14%, -320px) scale(.55);
  z-index: 0;
}

/* Подпись ФИКСИРОВАННОЙ высоты, а не минимальной.

   Разница принципиальна: при `min-height` подпись занимает одну строку основным
   шрифтом и две — подменным (он шире), и в момент подмены высота падает, сдвигая
   всё, что ниже. Именно этот остаток ловился измерением CLS уже после того, как
   был устранён прыжок текста. Высоты хватает на две строки в любом шрифте. */
.showcase__caption {
  height: 3.75rem;
  align-content: flex-start;
  overflow: hidden;
}

.showcase__dots {
  display: flex;
  gap: .5rem;
  margin-top: .75rem;
}

.showcase__dot {
  width: 28px;
  height: 28px;
  display: grid;
  place-items: center;
  background: none;
  border: 0;
  cursor: pointer;
}

.showcase__dot::before {
  content: '';
  width: 100%;
  height: 2px;
  background: var(--line-invert);
  transition: background var(--base) var(--ease);
}

.showcase__dot.is-current::before { background: var(--signal); }
.showcase__dot:hover::before { background: var(--text-invert-mut); }
.showcase__dot:focus-visible { outline: 2px solid var(--paper); outline-offset: 2px; }

/* На телефоне глубина съедает кадр: оставляем смену кадров без 3D-сдвига. */
@media (max-width: 47.99rem) {
  .showcase__stage { perspective: none; }

  /* Та же оранжевая подложка, что была у одиночного кадра: на узком экране
     диск секции скрыт, и без неё пара висит в пустоте. Подложка декоративная
     и в поток не входит — сдвига не добавляет. */
  .showcase__stage::before {
    content: '';
    position: absolute;
    z-index: 0;
    inset-inline-end: 4%;
    top: 50%;
    translate: 0 -50%;
    width: 62%;
    aspect-ratio: 1;
    border-radius: 50%;
    background: linear-gradient(150deg, #FF6330 0%, var(--signal) 38%, #B92D06 100%);
  }

  .showcase__slide { z-index: 1; }

  .showcase__slide[data-showcase-position='1'],
  .showcase__slide[data-showcase-position='2'],
  .showcase__slide[data-showcase-position='rest'] {
    opacity: 0;
    transform: scale(.92);
  }
}

/* Просили меньше движения — движения нет. Кадры просто сменяются по нажатию на
   точку, без переходов и без автоматического перелистывания (скрипт таймер в
   этом режиме не заводит). */
@media (prefers-reduced-motion: reduce) {
  .showcase__slide {
    transition: none;
    transform: none;
  }

  .showcase__slide[data-showcase-position='0'],
  .showcase__slide.is-current { transform: none; opacity: 1; }

  .showcase__slide:not(.is-current) { opacity: 0; }
}

/* Одиночный кадр (запасной случай) тоже резервирует геометрию заранее. */
.hero__shot-frame { aspect-ratio: 1 / 1; width: 100%; }

/* --------------------------------------------------------------------------
   MAX: карточка с номером (016A §5, §6)
   --------------------------------------------------------------------------
   У MAX нет публичной схемы «открыть чат с этим номером», поэтому канал даёт
   НОМЕР, а не ссылку-обманку. Оформление одно на оба режима существования
   карточки:

     без скрипта — обычный блок в подвале, на который ведёт якорь из шапки;
     со скриптом — диалог поверх страницы от нажатой иконки.

   Вся разница — в классе `--dialog`, который ставит скрипт. Разметка одна,
   второй копии номера на странице нет.
   -------------------------------------------------------------------------- */

/* Начальное состояние карточки задаёт СТИЛЬ, а не атрибут `hidden`.

   Браузер объявляет `[hidden]` как `display: none !important`, и важность
   браузера сильнее авторской: страница без скрипта не смогла бы показать
   карточку ничем. Класс `no-js` снимает встроенный скрипт шапки — значит со
   скриптом карточка скрыта уже на первом кадре, а без него видна в подвале. */
html:not(.no-js) .maxcard:not(.is-open) { display: none; }

.maxcard {
  margin: 1.5rem 0 0;
}

.maxcard__panel {
  max-width: 26rem;
  border: 1px solid var(--line-invert);
  border-radius: var(--radius);
  padding: 1.25rem;
  background: rgba(244, 241, 235, .06);
}

.maxcard__head {
  display: flex;
  align-items: center;
  gap: .625rem;
  margin-bottom: .75rem;
}

.maxcard__icon { display: inline-grid; place-items: center; color: #9B7BFF; }

.maxcard__title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--step-0);
  margin: 0;
  margin-inline-end: auto;
}

.maxcard__close {
  display: inline-grid;
  place-items: center;
  width: 36px; height: 36px;
  background: none;
  border: 1px solid var(--line-invert);
  border-radius: var(--radius);
  color: inherit;
  cursor: pointer;
}

.maxcard__close:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }

/* Номер — главное на карточке, и он обязан выделяться мышью целиком:
   скопировать руками должно быть так же возможно, как кнопкой. */
.maxcard__value {
  font-family: var(--font-display);
  font-size: var(--step-2);
  font-weight: 700;
  letter-spacing: .01em;
  margin: 0 0 .5rem;
  /* Префикс нужен Safari: без него номер не выделяется одним касанием, а именно
     так им пользуются на телефоне (016A §53). */
  -webkit-user-select: all;
  user-select: all;
  overflow-wrap: anywhere;
}

.maxcard__note { font-size: var(--step--1); margin: 0 0 1rem; }

.maxcard__actions { display: flex; flex-wrap: wrap; gap: .5rem; }

.maxcard__hint {
  font-size: var(--step--2);
  color: var(--text-invert-mut);
  margin: .75rem 0 0;
}

.maxcard__status { font-size: var(--step--1); margin: .5rem 0 0; min-height: 1.25rem; }

/* --- режим диалога --------------------------------------------------------- */

.maxcard--dialog {
  position: fixed;
  inset: 0;
  z-index: 120;
  margin: 0;
  display: grid;
  place-items: center;
  padding: 1rem;
  background: rgba(11, 13, 15, .64);
}

.maxcard--dialog .maxcard__panel {
  width: min(26rem, 100%);
  background: var(--paper);
  color: var(--ink);
  border-color: var(--line);
  box-shadow: 0 32px 64px rgba(11, 13, 15, .38);
}

.maxcard--dialog .maxcard__close { border-color: var(--line); }
.maxcard--dialog .maxcard__hint { color: var(--muted); }

/* Появление короткое и без движения разметки: диалог не должен ощущаться
   тяжелее самого действия — посмотреть номер. */
.maxcard--dialog.is-open .maxcard__panel { animation: maxcard-in 180ms var(--ease-out) both; }

@keyframes maxcard-in {
  from { opacity: 0; transform: translate3d(0, 8px, 0); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .maxcard--dialog.is-open .maxcard__panel { animation: none; }
}

/* На телефоне карточка садится вниз: большой палец достаёт до кнопки, а не до
   середины экрана. */
@media (max-width: 40rem) {
  .maxcard--dialog { align-items: end; padding: 0; }
  .maxcard--dialog .maxcard__panel {
    width: 100%;
    border-radius: var(--radius) var(--radius) 0 0;
    padding-bottom: calc(1.25rem + env(safe-area-inset-bottom, 0px));
  }
}
