/* ==========================================================================
   UNIGUE — стили сайта
   Палитра взята из готового каталога Unigue (3-Товары/Готовые-каталоги),
   он утверждён как визуальный эталон. Значения скопированы один в один.
   ========================================================================== */

:root {
  /* Типографика утверждена 25.07.2026.
     Эталон — 4-Стиль/Превью-типографика-финал.html, значения скопированы один в один.
     Два шрифта на весь сайт, третьего нет:
       Cormorant Garamond — только крупное и парадное, от 26px, вес 300–400
       Spectral           — всё остальное, включая мелкие капсы и кнопки  */
  --display: 'Cormorant Garamond', Georgia, serif;
  --text:    'Spectral', Georgia, serif;

  --paper:      #f6f3ee;   /* фон страницы  */
  --card:       #ffffff;   /* фон карточки — под белый фон предметных фото */
  --ink:        #211d18;   /* заголовки и акцентные значения */
  --read:       #3a352e;   /* текст для чтения: не чёрный, чёрный на бежевом дешевит */
  --muted:      #8a8175;   /* второстепенный текст */
  --line:       #e4ddd1;   /* линии и рамки */
  --bronze:     #8a6d3b;   /* акцент */
  --bronze-dim: #b09468;
  --dark:       #1e1b15;   /* тёмные блоки */
  --stock:      #2f7d55;   /* в наличии */

  --shell: 1280px;   /* текстовая колонка */
  --shop:  1500px;   /* витрина предметов — шире текста, утв. 28.07.2026 */
  --item:  1200px;   /* страница предмета целиком; 1530 → 1360 21.08.2026:
                        на 15" MacBook прежняя полоса читалась «сайтом для
                        слабовидящего» — всё крупное и ничего не помещается */
  --gut: 28px;

  --step: 8px;
}

/* ---------- база ---------- */

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

/* Скрытие через атрибут hidden. Браузер прячет такие элементы своим правилом
   [hidden] { display: none }, но любое наше правило с display перебивает его:
   авторский стиль всегда старше браузерного. Из-за этого фильтр в каталоге
   помечал карточки скрытыми, а .card { display: flex } возвращал их на экран —
   счётчик «Показано N» менялся, сетка нет. Александр 11.08.2026: «вот здесь
   вообще камня даже близко нет, то есть не фильтрует». Тем же местом были
   сломаны поле «Предмет» в форме (.field { display: grid }) и любые будущие
   скрытия. Правило общее и стоит в базе, чтобы не всплыло третий раз. */
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--read);
  font-family: var(--text);
  font-size: 18px;
  font-weight: 400;
  line-height: 1.72;
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; display: block; }

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

button { font: inherit; color: inherit; cursor: pointer; }

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

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    transition-duration: .01ms !important;
  }
}

.shell {
  width: 100%;
  max-width: var(--shell);
  margin: 0 auto;
  padding: 0 var(--gut);
}

/* Витрина предметов живёт шире текстовой колонки — 1500 вместо 1280.
   Утв. Стасом 28.07.2026 на листе 7-Сайт/превью-ширина.html, ширину он
   подобрал ползунком. Смысл в соотношении: блок разделов идёт во всю ширину
   окна, текст — в колонке 1280, и витрина между ними, а не заодно с текстом.
   Заголовок блока стоит в той же ширине, что и карточки, — тоже его выбор.
   Ширина живёт классом, а не переменной: --shell держит текстовую колонку,
   и подменять её значение внутри страницы значит менять ширину всему,
   что окажется рядом. */
.shell--shop { max-width: var(--shop); }

/* Страница предмета идёт своей шириной — 1530, подобрано Стасом ползунком
   15.08.2026 на листе превью-карточка-*.html. Ширина одна на всю страницу:
   крошки, карточка, блоки текста и «Похожие предметы». До этого верх страницы
   шёл в текстовой колонке 1280, а похожие — в витринной 1500, и на середине
   страницы полоса скакала на 220 точек вбок.
   Витрина главной остаётся на своих 1500 (контракт от 28.07.2026): это разные
   страницы, рядом их никто не видит. */
.shell--item { max-width: var(--item); }

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

/* Заголовки — только Cormorant, только тонкие веса.
   Правило системы: ниже 26px Cormorant не опускается, иначе два серифа
   сливаются в одно пятно. Всё мельче набирается Spectral. */
h1, h2, h3 {
  font-family: var(--display);
  font-weight: 300;
  line-height: 1.14;
  letter-spacing: -0.012em;
  color: var(--ink);
  margin: 0;
}

.h-display { font-size: clamp(40px, 6.4vw, 76px); line-height: 1.04; }
.h-page    { font-size: clamp(34px, 4.6vw, 54px); line-height: 1.10; }
.h-section { font-size: clamp(28px, 3.4vw, 42px); line-height: 1.14; }

/* курсив-акцент внутри заголовка: настоящее курсивное начертание Cormorant,
   а не наклон, который браузер подделывает. Одно-два слова на экран */
h1 em, h2 em, h3 em {
  font-style: italic;
  font-weight: 300;
  color: var(--bronze);
}

/* строка описи: номер позиции, артикул, габариты, остаток.
   Капс с разрядкой на серифе — как гравировка на бирке изделия */
.meta {
  font-family: var(--text);
  font-size: 13px;
  font-weight: 400;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.eyebrow {
  font-family: var(--text);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 20px;
}

.lead {
  font-weight: 300;
  font-size: clamp(19px, 1.6vw, 21px);
  line-height: 1.60;
  color: var(--read);
  max-width: 52ch;
}

.muted { color: var(--muted); }

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

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 15px 30px;
  border: 1px solid var(--ink);
  border-radius: 0;
  background: var(--ink);
  color: var(--paper);
  font-size: 13.5px;
  font-weight: 500;
  letter-spacing: .16em;
  text-transform: uppercase;
  transition: background .25s, color .25s, border-color .25s;
}

.btn:hover { background: var(--bronze); border-color: var(--bronze); color: #fff; }

.btn--ghost { background: transparent; color: var(--ink); border-color: var(--line); }
.btn--ghost:hover { background: transparent; border-color: var(--ink); color: var(--ink); }

.btn--wide { width: 100%; }

.btn--sm { padding: 11px 20px; font-size: 12.5px; }

/* ---------- шапка ---------- */

/* Фирменный знак стоит по центру, служебное — по бокам, меню строкой ниже.
   Логотип по центру читается как подпись автора, а не как вывеска магазина.

   Ширина знака задана одной переменной --logo-w: главная крупнее, внутренние
   мельче, при прокрутке шапка ужимается. Знак теперь векторный (assets/logo.svg
   режется из 4-Стиль/логотип.ai), поэтому потолка по размеру больше нет:
   любое число останется чётким на любом экране.

   --mark-w — ширина монограммы. Она встаёт вместо полного знака на узком
   экране, где надпись «Unigue» мельчает до нечитаемой. Ромб квадратный. */

/* ШАПКА ВНЕ ПОТОКА НА ВСЕХ СТРАНИЦАХ (16.08.2026) — лечение тряски, не косметика.
   Было: position: sticky, то есть шапка занимала место в потоке страницы.
   А высота у неё непостоянная: на 40-м пикселе прокрутки включается is-scrolled
   и шапка ужимается с 223 до 169 (знак 150 → 112, поля 24 → 11). Пока она
   стояла в потоке, это ужимание укорачивало страницу на 54 точки, браузер
   сам возвращал прокрутку назад, чтобы содержимое не прыгнуло, — и выбрасывал
   её в самое начало. Ноль меньше сорока, класс тут же снимался, шапка
   разжималась обратно. Дальше по кругу: медленно листаешь вниз, доходишь до
   сорока — тебя кидает наверх, и так без конца. Стас поймал это на запись
   экрана 16.08.2026 («навбар как истеричный вверх-вниз»); измерено на живых
   страницах: 19 бросков подряд за 25 щелчков колеса на экране 900 px.

   Это ТОТ ЖЕ баг, что вылечили на главной ещё в июле — там шапку вынули из
   потока (.header--over ниже). Лечение получила одна главная, остальные
   213 страниц остались больными. Теперь fixed стоит у всех, и высота шапки
   не влияет на поток нигде.

   Место, которое шапка занимала, держит распорка .header-space — она печатается
   в разметку сразу после шапки на всех страницах, кроме главной (build.py,
   функция head). У главной распорки нет намеренно: там первый экран заезжает
   под шапку по контракту.

   Фон шапки СПЛОШНОЙ, и размытия под ней нет — это лечение тормозов, а не вкус.
   Было: полупрозрачный фон плюс backdrop-filter: blur(10px). Такое размытие
   браузер пересчитывает на каждый кадр прокрутки по всей площади шапки — а она
   на главной 289px высотой во всю ширину. Пока под ней проезжали мелкие плитки
   на белом, это сходило с рук; как только под шапку поехали три крупные
   фотографии разделов, прокрутка начала фризить (поймал Стас 26.07.2026).
   Возвращать blur нельзя. Стеклянный эффект тут ничего и не давал: фон страницы
   ровный бежевый, размывать под ним нечего. */
/* ⭐ ШАПКА-ПОЛОСА — утв. Стасом 28.08.2026 на превью 7-Сайт/превью-шапка-люкс.html.
   Числа скопированы из превью один в один: полоса 105 белая с волосяной
   линией снизу, ширина 1820, отступ от краёв 36, знак 112, меню капсом 12
   с разрядкой .42 и зазором 100, номера в шапке нет, значок 19 контуром 1,4.
   Раскладка: слева «Бренд» и «Коллекции», по центру знак, справа
   «Партнёрам» и значок избранного — одна строка.
   Отменяет: два этажа (знак над рядом меню), растянутый на всю ширину ряд,
   крупный знак главной 298, ужимание при прокрутке и кнопку «Избранное». */
.header {
  --logo-w: 112px;
  --mark-w: 44px;
  --header-pad: 10px;
  --header-bg: #ffffff;
  /* Фон шапки — переменной, потому что у прокрученной он свой, светлее
     страницы (см. ниже). */
  --header-bg: var(--paper);
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 60;
  background: var(--header-bg);
  /* Линии под полосой нет — слово Стаса на превью 28.08.2026. Прокрученную
     шапку от страницы отделяет тень (ниже), а на первом экране — сам кадр. */
  border-bottom: 1px solid var(--line);
  transition: background-color .35s ease, box-shadow .35s ease,
              border-color .35s ease;
}

/* РАСПОРКА ПОД ШАПКОЙ. Пустой блок ровно в её рост: шапка ушла из потока,
   и без распорки первая строка страницы оказалась бы под ней.
   Высота задана числами по трём ширинам экрана — теми же, на которых меняются
   размеры знака и полей (900 и 640). Числа замерены на живых страницах, а не
   выведены на бумаге. app.js уточняет их в --head-space после загрузки шрифтов:
   пока шрифты не пришли, ряд меню занимает другую высоту.
   ВАЖНО: распорка держит рост НЕУЖАТОЙ шапки и при прокрутке не меняется —
   иначе вернётся ровно та болезнь, от которой лечимся. */
.header-space { height: var(--head-space, 105px); }

/* ЗНАК КРУПНЕЕ — утв. Стасом 16.08.2026, эталон 7-Сайт/превью-навбар-и-знак.html.
   Замечание Александра на встрече 11.08.2026: «логотип может быть увеличен
   немножко, потому что ты заходишь на сайт…». Главная 210 → 298, внутренние
   150 → 168, при прокрутке 112 → 176 (ниже).
   Поля шапки на главной убраны с 34 до 14 — тем же ходом: знак вырос, и без
   этого шапка съедала бы у кадра на 40 точек больше.

   14 — это упор ползунка в превью, и ход вниз я после этого расширил и
   пересмотрел на живой странице: 10, 6 и 4 знак прижимают к самому верху окна,
   и он начинает читаться как обрезанный, а не как поставленный. Ниже 14
   становится хуже, поэтому 14 и осталось. */
/* ⛔ Крупный знак главной (298) отменён 28.08.2026: он держался на том, что
   шапка была в два этажа. В полосе знак один на все страницы. Класс остался —
   на нём висит вступительная анимация. */
.header--home     { --mark-w: 54px; }

/* ПРОКРУЧЕННАЯ ШАПКА ОТДЕЛЯЕТСЯ ОТ СТРАНИЦЫ (утв. 27.07.2026).
   До этого шапка была ровно того же бежевого, что и фон страницы, а линии
   под ней на главной нет — и при прокрутке шапка сливалась со страницей
   в одно пятно. Стас поймал это на живой странице.

   Отделяем тремя вещами разом, все включаются только вместе с is-scrolled
   и все — плавно, за те же 0,35 с, что и остальной переход шапки:
     1. фон светлее страницы — шапка читается как светлая полка над бежевым;
     2. волосяная тень вниз — работает там, где под шапку заезжает белая
        карточка предмета и одного светлого фона мало;
     3. линия под шапкой на главной (возвращена Стасом 27.07.2026, см. ниже).
   Тень намеренно почти без размаха вверх (отрицательный разгон -14px):
   нужна глубина под краем, а не серое облако вокруг шапки. */
/* Второй селектор — то же состояние, но проставленное ДО выполнения app.js.
   Класс pre-scrolled вешает скрипт в <head> (build.py, BOOT_SCRIPT), когда
   знает, что страница откроется прокрученной. Без него шапка успевает
   нарисоваться во всю высоту (288 px, знак 210) и только потом ужимается
   до 169 и 112 — скачок почти вдвое, Стас поймал его как рывок 27.07.2026.
   app.js снимает pre-scrolled сразу, как проставит настоящие классы. */
/* ⛔ Ужимание знака и полей при прокрутке снято 28.08.2026. Полоса стоит
   одной высоты всегда — так же, как у образцов, по которым её собирали.
   Остаются фон посветлее и волосяная тень: без них шапка сливается с бежевой
   страницей, а линии под ней теперь нет. */
.header.is-scrolled,
.pre-scrolled .header {
  --header-bg: #fbf9f5;
  box-shadow: 0 10px 24px -14px rgba(33, 29, 24, .22);
}

/* Ужатый знак на ГЛАВНОЙ — своё число, 176 (утв. Стасом 16.08.2026, эталон
   7-Сайт/превью-навбар-и-знак.html).

   Почему двумя правилами, а не одним общим, как было до 16.08.2026.
   Раньше ужатый знак был один на весь сайт — 112, и он был меньше и главной
   (210), и внутренней (150). Стас поднял ужатый до 176, а внутренний до 168 —
   и одно общее число перестало работать: на внутренней странице знак при
   прокрутке стал бы КРУПНЕЕ, чем до прокрутки, то есть шапка «ужималась» бы
   вверх. Поэтому главная ужимается до его 176, а внутренние — до 126: это
   прежняя их доля (112 от 150 — те же три четверти от 168). */
/* (у главной своего ужатого знака больше нет — полоса одна на все страницы) */

/* ШИРИНА ШАПКИ 1480 — утв. Стасом 29.07.2026, эталон 7-Сайт/превью-шапка-акценты.html.
   В разметке у .header__in стоит класс shell, а он держит текстовую колонку
   1280. Для шапки это оказалось тесно: телефон и «Мой список» сидели заметно
   внутри от краёв экрана и читались как случайные хвостики. 1480 — своё число
   шапки, и оно перебивает shell, потому что это правило стоит в файле ниже. */
.header__in {
  display: grid;
  max-width: 1820px;
  /* Боковые колонки равны между собой — от этого знак стоит ровно по центру.
     minmax(0, …) — страховка: на узком экране колонки сожмутся, а не вытолкнут
     шапку за край экрана. */
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  /* ⭐ Навигация и правая группа садятся на НИЖНЮЮ ЛИНИЮ слова «Unigue»,
     а не по середине полосы (28.08.2026). Знак вертикальный, его тяжёлая
     часть — слово внизу; выключка по центру полосы вешала меню в пустоте
     напротив лёгкого ромба, и шапка разваливалась на три несвязанных пятна. */
  align-items: center;
  column-gap: 24px;
  /* Расстояние от знака до ряда меню — 41 (утв. Стасом 16.08.2026, эталон
     7-Сайт/превью-навбар-и-знак.html). Было 20. Замечание Александра было
     «чтобы более чётко всё выглядело в навбаре»: ряд меню, отбитый от знака
     воздухом, читается как отдельная строка навигации, а не как подпись
     под знаком. */
  /* Ряда во втором этаже больше нет: меню, знак и телефон стоят в одной
     строке, поэтому и междурядья нет. */
  row-gap: 0;
  padding: var(--header-pad) 36px;
}

.logo {
  grid-column: 2;
  justify-self: center;
  display: block;
  line-height: 0;
  /* ⭐ ВСЁ В ПОЛОСЕ ВЫРОВНЕНО ПО СЕРЕДИНЕ ПО-НАСТОЯЩЕМУ (28.08.2026).
     Выключка по центру ровняет КОРОБКИ строк, а не то, что видно глазом:
     у капса нет выносных вниз, а строка держит под них место — замер по
     пикселям дал меню на 3,5 выше середины, знак на 1,5, значок на 0,5.
     Эти три сдвига гасят перекос; проверять только замером по пикселям.
     У ЗНАКА сдвиг сделан через top, а не transform: transform на нём держит
     вступительная анимация главной (boot-logo, fill both), и она перебивала
     сдвиг — знак стоял на месте при любом числе. */
  position: relative;
  top: 1.5px;
}

.logo__img {
  width: var(--logo-w);
  height: auto;
}

/* ПЛАВНОЕ УЖИМАНИЕ ШАПКИ — теперь на всех страницах (16.08.2026).
   Знак и поля при прокрутке уменьшаются: на главной 210 → 112 и 34 → 11,
   внутри 150 → 112 и 24 → 11.

   История, из-за которой это правило десять дней стояло только на главной.
   29.07.2026 плавность вернула фриз: ширина знака и поля — это раскладка,
   а не рисование, видеокарте её не отдать, и браузер 15 кадров подряд
   раскладывал заново ВСЮ страницу. На каталоге это 900 с лишним элементов
   на каждом кадре. Причина была не в самой плавности, а в том, что шапка
   на внутренних страницах стояла В ПОТОКЕ (sticky): её высота тянула за собой
   всё содержимое ниже. Тогда плавность оставили одной главной — там шапка
   уже была вне потока и ужимание ничего не двигало.

   16.08.2026 шапку вынули из потока ВЕЗДЕ (правило .header выше — лечение
   тряски, из-за которой страницу выбрасывало наверх). Причина запрета отпала:
   пересчёт заперт внутри шапки и до страницы не доходит. Замерено на живых
   страницах после правки, прокрутка колесом 4 секунды подряд:
   каталог 60 кадров в секунду, 2 тяжёлых из 241; раздел столов 61 и 1;
   карточка предмета 60 и 0; главная 60 и 0. Фриза нет.

   Если фриз когда-нибудь вернётся — сначала проверить, не встала ли шапка
   обратно в поток. Плавно менять размеры можно только пока она вне его. */
.header .header__in { transition: padding .25s ease; }
.header .logo__img { transition: width .25s ease; }

/* В шапке лежат сразу две картинки знака: полная (ромб + надпись «Unigue») и
   одна монограмма. Показана всегда ровно одна. По умолчанию — полная;
   подмена на монограмму описана ниже, в блоке адаптива. */
.logo__img--mark { display: none; width: var(--mark-w); }

/* Запасной случай: знака в светлой версии нет (остался только старый PNG) —
   заливаем контур ровным светлым тоном, иначе в подвале его не видно.
   С вектором не используется: светлая версия приходит готовым файлом. */
.logo__img--pale { filter: brightness(0) invert(87%) sepia(12%) saturate(220%); }

/* Меню разложено по всей ширине, а не сбито в кучку по центру: пункты стоят
   на равном расстоянии, между ними воздух.

   ПОЛЯ МЕНЮ СНЯТЫ — утв. Стасом 29.07.2026 вместе с шириной шапки 1480
   (эталон 7-Сайт/превью-шапка-акценты.html). Раньше по бокам меню стояли
   отступы до 96 px, и крайние пункты — «Каталог» и «Контакты» — висели внутри
   от телефона и от «Моего списка». Теперь ряд идёт ровно в ширину шапки:
   левый край меню совпадает с телефоном, правый — с кнопкой.
   На узком экране меню становится выпадающим столбиком, и там свои поля
   (см. медиазапрос 900 px внизу файла). */
/* Раскладка ряда меню — сетка, а не space-between (20.08.2026).
   При space-between положение каждого пункта зависит от длины соседних слов,
   и средний пункт «Проекты» вставал на 18 px левее оси знака. На фотографии
   это было незаметно, а на первом экране из двух створок мимо оси прошли
   сразу три вещи: шов, знак и пункт меню.

   Пять колонок «1fr 1fr auto 1fr 1fr»: средний пункт лежит в колонке auto,
   слева и справа от неё по две равные доли, поэтому он стоит ровно по центру
   при любых длинах остальных слов. Крайние пункты прижаты к краям выключкой,
   то есть остаются ровно под телефоном и кнопкой избранного — это утверждено
   29.07.2026 и не тронуто. */
/* Меню собрано в левый угол — зазор 42 (утв. 28.08.2026). Прежний ряд во всю
   ширину с дырами по 300 точек отменён вместе с ним; правило «растянутый ряд —
   так и надо» от 25.08.2026 больше не действует. */
.nav {
  grid-column: 1;
  justify-self: start;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  /* Зазор 161, а не 100: левые края пары обязаны встать ровно туда, где
     раньше стояли «Коллекции» (207) и «Партнёрам» (439) — слово Стаса
     28.08.2026. «Бренд» короче «Коллекций», поэтому равный зазор давал 378. */
  gap: 161px;
  padding: 0;
  /* Левая пара стоит не от края, а на местах прежних «Коллекции»
     и «Партнёрам» — отсюда отступ внутрь (28.08.2026). */
  margin-left: var(--nav-left, 171px);
  transform: translateY(3px);
}

/* Средний пункт меню стоит на оси знака (20.08.2026).
   При space-between зазоры между пунктами равны, но положение среднего слова
   зависит от длины соседних: «Бренд» короче «Контактов», и «Проекты» вставали
   на 18 px левее оси. На фотографии это не читалось, а на первом экране из двух
   створок мимо оси прошли сразу три вещи — шов, знак и пункт меню.

   Величину сдвига НЕ пишем числом: она зависит от длин слов и от шрифта,
   а слова в меню менялись уже трижды. Её меряет app.js после загрузки шрифтов
   и кладёт в --nav-shift. Скрипт не отработал — пункт просто останется там,
   где стоял, ряд не развалится.

   Сетку с равными долями здесь пробовали и убрали: средний вставал по центру,
   но «Коллекция» и «Партнёрам» сбивались к нему в кучу, а края разъезжались. */
/* :nth-last-child(3) в пару к :nth-child(3) означает «третий с обоих концов»,
   то есть правило работает только когда пунктов ровно пять. 25.08.2026
   «Проекты» сняты с навбара, пунктов стало четыре, середина ряда пришлась
   на зазор — двигать нечего и незачем. Вернутся пять — правило оживёт само,
   и app.js снова начнёт мерить сдвиг (он тоже проверяет число пунктов). */
.nav > a:nth-child(3):nth-last-child(3) { transform: translateX(var(--nav-shift, 0px)); }

/* Отклик пункта на наведение утверждён Стасом 26.07.2026: подчёркивания нет,
   слово чуть раздвигается по буквам и уходит в бронзу. Эталон —
   7-Сайт/превью-кнопки-бара.html, карточка B «едва уловимо»; значение .105em
   скопировано оттуда один в один.

   Слово лежит в ячейке-сетке вдвоём с невидимым двойником, набранным уже
   раздвинутым. Ширину ячейки держит двойник — по нему она сразу максимальная,
   поэтому при наведении соседние пункты не сдвигаются и ряд стоит на месте.
   Без двойника раздвинутое слово толкало бы соседей вбок. */
/* ЧИТАЕМОСТЬ МЕНЮ — утв. Стасом 16.08.2026, эталон 7-Сайт/превью-навбар-и-знак.html.
   Замечание Александра на встрече 11.08.2026: «сложно, ещё видно их»,
   «чтобы более чётко всё выглядело в навбаре, именно разделы по компании,
   дизайнерам». Кегль при этом НЕ трогали: 19 Стас отверг ещё 29.07.2026,
   и читаемость взята тремя другими вещами:
     вес       400 → 500 (Spectral 500 лежит у нас в assets/fonts/)
     разрядка  .05em → .035em — слово собирается в одно пятно, а не рассыпается
     цвет      наследуемый --read (#3a352e) → --ink (#211d18)

   Про цвет отдельно. На ползунке тон стоял на упоре, то есть почти чёрный
   (#16130f). За упором остаётся только чистый чёрный, а он на бежевом дешевит
   (правило палитры, --read вверху файла). Поставлен --ink: он уже в палитре,
   им набраны заголовки, и им же меню набрано на первом экране поверх кадра —
   теперь тон меню один на весь сайт, а не два разных. От выкрученного упора
   отличается на глаз неразличимо.

   Отклик на наведение задан РАЗБЕГОМ, а не конечным числом. Утверждено
   26.07.2026 как «буквы расходятся с .05em до .105em», то есть плюс .055em.
   База уехала на .035em — значит конечное .09em, разбег тот же. Если записать
   сюда прежние .105em, отклик стал бы сильнее утверждённого. */
.nav a {
  /* 14 / .09 — числа с превью 28.08.2026. Отклик прежний: буквы расходятся
     на .055em и уходят в бронзу (утв. 26.07.2026). */
  /* Мелкий капс с широкой разрядкой — навигация служебная, главное в шапке
     знак. Разрыв масштабов здесь намеренный: знак 112, буква 13. */
  --nav-open: .475em;
  display: inline-grid;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: .42em;
  text-transform: uppercase;
  color: var(--ink);
  padding: 8px 0;
  /* Толщину штриха в переход не кладём: Chrome её не интерполирует. Проверено
     17.08.2026 — при снятии класса is-over-photo значение уходит с .32px в 0
     за первый же кадр, замеры на 30, 90, 180, 300 и 500 мс дают ноль при
     любом transition. Плавным его сделать нельзя; щелчок приходится на тот
     же момент, когда шапка и так меняет фон, и на глаз не читается. */
  transition: letter-spacing .32s ease, color .32s ease;
}

.nav a > span,
.nav-r > span { grid-area: 1 / 1; justify-self: center; white-space: nowrap; }

/* Двойник только держит место: на экране его нет, читалке он не читается
   (в разметке помечен aria-hidden). */
.nav__ghost { visibility: hidden; letter-spacing: var(--nav-open); }

.nav a:hover, .nav a[aria-current="page"] {
  letter-spacing: var(--nav-open);
  color: var(--bronze);
}


/* ⭐ ЗНАЧОК ИЗБРАННОГО — 28.08.2026, вместе с шапкой-полосой.
   Слово Стаса: «нужно сделать лаконично её, значок просто нужен».
   Контур сердца 18 точек, штрих 1,1 — под вес меню; ни рамки, ни кружка-бейджа
   (кружок с цифрой — язык магазина, прежняя кнопка в рамке была единственным
   обведённым элементом шапки и перетягивала внимание с знака).
   Счётчик — просто цифра бронзой справа; пусто — цифры нет вовсе. */
.header__side {
  grid-column: 3;
  justify-self: end;
  display: flex;
  align-items: center;
  /* ЗЕРКАЛО ЛЕВОЙ ГРУППЫ (28.08.2026, слово Стаса «чтобы оформление слева
     и справа было идентичное»): тот же зазор 161 между двумя вещами и тот же
     отступ 171 внутрь от края полосы, что у левой пары. */
  gap: 161px;
  margin-right: var(--nav-left, 171px);
  transform: translateY(1px);
}

/* ⭐ «ПАРТНЁРАМ» СТОИТ СПРАВА, рядом со значком (28.08.2026, слово Стаса).
   Набран тем же, чем меню слева, — это тот же пункт навигации, просто
   на другом краю полосы. */
.header__side .nav-r {
  --nav-open: .475em;
  display: inline-grid;
  font-family: var(--text);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: .42em;
  text-transform: uppercase;
  color: var(--ink);
  padding: 8px 0;
  /* та же поправка на капс, что у меню слева: буквы без выносных вниз
     стоят выше середины строки (замер по пикселям, 28.08.2026) */
  position: relative;
  top: 3.5px;
  transition: letter-spacing .32s ease, color .32s ease;
}

.header__side .nav-r:hover,
.header__side .nav-r[aria-current="page"] {
  letter-spacing: var(--nav-open);
  color: var(--bronze);
}

/* Тот же пункт печатается вторым экземпляром внутри панели меню — она живёт
   только на телефоне, где правой группы нет. Одновременно видно ровно один. */
.nav a.nav-mob { display: none; }

/* Имя классу дано с приставкой header__: голый .fav в проекте уже занят
   кнопкой «отложить» на карточке, и она перебивала значок в шапке —
   он уезжал в угол окна (поймано 28.08.2026). */
.header__fav {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  color: var(--ink);
  transition: color .32s ease;
}

.header__fav svg {
  width: 19px;
  height: 19px;
  display: block;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.4;
  overflow: visible;
}

.header__fav-count {
  font-family: var(--display);
  font-weight: 400;
  font-size: 15px;
  color: var(--bronze);
  font-variant-numeric: oldstyle-nums;
  font-feature-settings: 'onum' 1;
}

.header__fav-count > i { font-style: normal; }
/* ⛔ Цифра у значка снята там же, 28.08.2026 («цифра: нет»).
   Счётчик по-прежнему считается в app.js — вернуть = снять эту строку. */
.header__fav-count { display: none; }
.header__fav:hover { color: var(--bronze); }

/* Номер 18,5 — утв. Стасом 29.07.2026 (эталон 7-Сайт/превью-шапка-акценты.html).
   Было 15,5 при знаке 210: разрыв в тринадцать раз, и номер пропадал в шапке.
   Вес оставлен обычным намеренно — Стас пробовал плотный и вернул этот. */
.header__tel {
  /* Номер переехал направо и набран тем же кеглем и той же разрядкой, что
     меню (28.08.2026). Прежние 18,5 слева отменены: в шапке из трёх слов
     номер вдвое крупнее меню читался как объявление. */
  /* ⛔ НОМЕР В ШАПКЕ СНЯТ — выбор Стаса на превью 28.08.2026 («показывать:
     нет»). Связь остаётся в подвале, на карточке предмета и на «Контактах».
     Вернуть = снять display:none. */
  display: none;
  font-family: var(--text);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: .18em;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  transition: letter-spacing .32s ease, color .32s ease;
}

.header__tel:hover { letter-spacing: .30em; color: var(--bronze); }

.listbtn {
  display: inline-flex;
  align-items: center;
  /* 22 px — расстояние от слова до черты счётчика (утв. 16.08.2026) */
  gap: 22px;
  border: 1px solid var(--line);
  background: transparent;
  padding: 9px 15px;
  font-size: 13.5px;
  font-weight: 500;
  letter-spacing: .14em;
  text-transform: uppercase;
  transition: border-color .2s;
}

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

/* На широком экране кнопка подписана словами, значок сердца не нужен —
   он выходит на телефоне, где место занимает знак по центру. */
.listbtn__icon { display: none; width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 1.6; }

/* Счётчик — цифра за тонкой чертой (утв. 16.08.2026, эталон
   `превью-кнопка-избранное.html`, вариант Д, числа Стас довёл лично).
   Кружка с заливкой больше нет: тёмная точка рядом с засечной надписью читалась
   как значок уведомления в мессенджере, а у нас дорогой сегмент. Черта отделяет
   число от слова так же, как в книге колонцифру отделяют от текста.

   letter-spacing: 0 обязателен. Без него счётчик наследует разрядку заглавных
   .14em от самой кнопки; разрядка добавляет пустое место СПРАВА от знака, и
   цифра уезжает влево — из-за этого прежний кружок выглядел неотцентрованным
   (найдено 16.08.2026, жалоба Стаса была ровно про это). */
.listbtn__count {
  font-family: var(--text);
  font-size: 12px;
  letter-spacing: 0;
  font-variant-numeric: tabular-nums lining-nums;
  height: 15px;
  padding-left: 19px;
  display: inline-flex;
  align-items: center;
  border-left: 1px solid rgba(33, 29, 24, .34);
}

/* Цифра двигается внутри счётчика, черта стоит на месте: сдвиг задан вложенным
   <i>, потому что transform на самом счётчике потянул бы за собой и черту. */
.listbtn__count > i { font-style: normal; transform: translateY(.1px); }

/* Пусто — счётчика нет вовсе. Прежний серый ноль висел на каждой из 214 страниц
   у каждого, кто зашёл впервые, и занимал место в шапке ради сообщения об
   отсутствии (решено 16.08.2026). */
.listbtn__count[data-empty="1"] { display: none; }

/* Отклик на добавление. Раньше его давала смена цифры 0 → 1; теперь цифра при
   первом предмете появляется из ничего, и без движения этого можно не заметить.
   Двигается только цифра — черта неподвижна. */
@keyframes listbtn-count-in {
  0%   { opacity: 0; transform: translateY(-3px) scale(.86); }
  60%  { opacity: 1; transform: translateY(0) scale(1.12); }
  100% { opacity: 1; transform: translateY(.1px) scale(1); }
}
.listbtn__count.is-new > i { animation: listbtn-count-in .34s cubic-bezier(.2, .9, .3, 1.4); }

@media (prefers-reduced-motion: reduce) {
  .listbtn__count.is-new > i { animation: none; }
}

.burger {
  display: none;
  grid-column: 1;
  justify-self: start;
  background: none;
  border: 0;
  padding: 8px;
}
.burger span { display: block; width: 22px; height: 1px; background: var(--ink); margin: 5px 0; }

/* ---------- главная: первый экран ---------- */

/* На первом экране ДВЕ вещи: знак в шапке и одна фотография во весь экран.
   Текста нет — фраза снята Стасом 26.07.2026. Заголовок h1 в разметке остался,
   но спрятан: он нужен поисковикам, человеку на экране — нет.

   Снимок идёт от края до края окна, полей вокруг него нет. Затемняющих плёнок
   и градиентов поверх не кладём: они гасят свет и цвет, ради которых кадр
   и выбран.

   ПРАВИЛО СТАСА, 26.07.2026: первый экран — это РОВНО один экран. Ни пикселя
   следующего блока при открытии страницы видно быть не должно, ни на его
   мониторе, ни на любом другом устройстве. Раньше тут жила полоса подглядывания
   --hero-peek: край блока разделов специально выглядывал снизу, «чтобы было
   видно, что страница продолжается». Стас это забраковал — выглядит как наезд
   одного экрана на другой. Полоса удалена, возвращать нельзя.

   svh (small viewport height) — высота окна при РАЗВЁРНУТЫХ панелях браузера,
   то есть в момент открытия страницы. Берём её, а не dvh: dvh растёт, когда
   на телефоне при прокрутке прячется адресная строка, и низ первого экрана
   пополз бы вверх. Строка с vh выше — запасная, для старых браузеров.

   Высоту шапки меряет app.js и кладёт в --header-h: шапка складывается из
   знака и меню, её высота зависит от картинки — из CSS её не вычислить.
   Число в fallback — на случай, если скрипт не выполнился. */

.hero {
  position: relative;
  overflow: hidden;
  border-bottom: 1px solid var(--line);
  height: calc(100vh - var(--header-h, 103px));
  height: calc(100svh - var(--header-h, 103px));
  min-height: 340px;
}

/* Кадр светлый сверху — шапка ложится прямо на него, и фотография начинается
   от самого верха окна. Отрицательный отступ подтягивает первый экран под
   шапку; сама шапка остаётся sticky и никуда не съезжает. Раз бежевой полосы
   сверху больше нет, её высоту из расчёта высоты экрана убираем. */
/* Шапка лежит поверх фотографии и места в потоке не занимает (position: fixed),
   поэтому первый экран здесь — ровно окно, без вычитаний. Ни высоту шапки,
   ни переменную --header-h тут использовать НЕЛЬЗЯ — почему, написано ниже,
   в правиле .header--over. */
.hero--over {
  height: 100vh;
  height: 100svh;
}

/* Дымка живёт на самой шапке (.header--over::after), а не здесь. Раньше она
   лежала на первом экране — при прокрутке уезжала вместе с ним, шапка теряла
   светлую подложку и включала сплошной бежевый фон с резкой границей поперёк
   фотографии. Стас поймал это на вторую запись экрана. */

/* ==========================================================================
   ПЕРВЫЙ ЭКРАН — ДВЕ СТВОРКИ, ЗАЛИТЫЕ МАТЕРИАЛОМ КОЛЛЕКЦИИ
   Утв. Стасом 20.08.2026, эталон — 7-Сайт/первый-экран.html (вариант 2).
   Значения перенесены из эталона один в один.

   Слева Fashion Metropolis — шпон американского ореха, справа City Edition —
   зернистая кожа. До этого дня здесь стояла одна фотография гостиной, а текста
   на первом экране не было вовсе; оба правила от 26.07.2026 сняты этим решением.

   Шва между створками НЕТ: бумажная полоса посередине резала знак в шапке.

   НА НАВЕДЕНИЕ ОТЗЫВАЕТСЯ ТОЛЬКО ПОДПИСЬ: буквы имени чуть расходятся, линия
   под ним становится бронзовой. Ни фактура, ни ширина створки не двигаются.
   ========================================================================== */

.dvor {
  display: flex;
  gap: 0;
  background: var(--paper);
  border-bottom: 0;
}

/* Створка — ссылка целиком, а не кадр с кнопкой.

   СТВОРКИ НЕПОДВИЖНЫ. Ровно половина и половина, при наведении ширина не
   меняется и граница между материалами никуда не едет. 20.08.2026 я включил
   здесь раскрытие гармошкой, как в блоке «Разделы», — Стас снял: на первом
   экране от этого всё пляшет. Раскрытие карточки и наезд кадра остаются
   языком блока «Разделы», сюда их не переносим. */
.stvor {
  position: relative;
  flex: 1 1 50%;
  min-width: 0;
  overflow: hidden;
  display: block;
  text-decoration: none;
}

.stvor__mat { position: absolute; inset: 0; margin: 0; overflow: hidden; }
.stvor__mat img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* ---------- имя коллекции ---------- */
.stvor__cap {
  position: absolute;
  left: clamp(28px, 3.7vw, 64px);
  right: clamp(28px, 3.7vw, 64px);
  bottom: clamp(38px, 4.4vw, 74px);
  z-index: 2;
  pointer-events: none;
}
.stvor__name {
  font-family: 'Cormorant Garamond', Georgia, serif;
  font-weight: 300;
  font-size: 5.2vw;
  line-height: .98;
  letter-spacing: .06em;
  margin: 0;
  color: #f7f2e9;
  text-shadow: 0 2px 40px rgba(20, 16, 10, .5);
  transition: letter-spacing 1000ms cubic-bezier(.22, .61, .36, 1);
}
.stvor:hover .stvor__name { letter-spacing: .082em; }

.stvor__rule {
  height: 1px;
  margin: 30px 0 0;
  background: rgba(247, 242, 233, .5);
  transition: background-color 700ms ease;
}
.stvor:hover .stvor__rule { background: var(--bronze); }

.stvor__go {
  margin: 22px 0 0;
  font-family: 'Spectral', Georgia, serif;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: rgba(247, 242, 233, .88);
}

/* ---------- телефон: створки друг под другом ---------- */
@media (max-width: 760px) {
  .dvor { flex-direction: column; }
  .dvor:hover .stvor, .dvor .stvor:hover { flex-grow: 1; }
  .stvor__name { font-size: 11.5vw; }
  .stvor__rule { margin-top: 20px; }
  /* Подпись «Смотреть коллекцию». Было 11 точек цветом с прозрачностью .88 —
     замер по живому экрану 26.08.2026 дал контраст к фактуре 3,3 : 1 у ореха
     и 3,1 : 1 у кожи при норме 4,5 для мелкого текста. Кегль 12,5 и цвет без
     прозрачности. Композицию экрана не трогаем: она утверждена 20.08.2026,
     плёнка поверх кадра забракована тогда же, свечение под буквами — 25.08. */
  .stvor__go {
    margin-top: 15px;
    font-size: 12.5px;
    letter-spacing: .18em;
    color: #fbf7f0;
  }
}

/* Пока страница не прокручена, шапка над фотографией прозрачная: видно кадр,
   а не бежевую полосу. Стоит прокрутить — app.js вешает is-scrolled, и фон
   возвращается, иначе меню потеряется на светлых местах страницы.

   Своего фона у шапки над кадром нет: бежевое даёт дым ::after, и его настройки
   Стас утвердил лично 26.07.2026 на живой странице — числа ниже трогать нельзя.
   Красить фон самой шапки по-прежнему нельзя: получается плашка во всю ширину
   с резкой границей на кадре — забраковано трижды.

   Шапка вне потока (position: fixed) — это лечение бага, а не косметика,
   и с 16.08.2026 оно стоит в общем правиле .header, то есть на всех страницах
   сразу. Здесь описание оставлено: главная была первой, где болезнь поймали.
   Шапка при прокрутке уменьшается: знак с 210px до 112px. Пока шапка стояла
   в потоке (sticky) и первый экран подтягивался под неё отрицательным отступом
   в размер --header-h, любое изменение высоты шапки двигало всю страницу и
   меняло её общую длину. Позиция прокрутки от этого сама уезжала за порог 40px,
   класс is-scrolled то появлялся, то пропадал — и страница дёргалась на месте
   при первом же движении колеса. Стас поймал это на запись экрана.
   fixed убирает шапку из потока: теперь её высота ни на что не влияет.
   Своего правила position у .header--over больше нет, оно повторяло общее. */

/* Пока за шапкой стоит фотография первого экрана, класс is-over-photo от app.js.
   Тогда своего фона у шапки нет, а бежевое даёт дым ::after (описан ниже).
   Кадр уехал вверх — класс снимается, включается обычная бежевая шапка из .header.

   Переход между двумя состояниями — ПЛАВНЫЙ, и это обязательное условие.
   Раньше класс снимался мгновенно, фон включался в тот же кадр — и на середине
   прокрутки било по глазам щелчком. Стас поймал это на запись экрана 26.07.2026.
   Теперь фон проявляется цветом за 0,35 с, дым за то же время гаснет. */
.header--over {
  transition: background-color .35s ease, border-color .35s ease,
              box-shadow .35s ease;
}

/* Пока кадр за шапкой — на ней нет ничего: ни фона, ни линии, ни тени.
   Тень гасим отдельной строкой: класс is-scrolled приходит раньше, чем уезжает
   кадр (порог прокрутки 40 px), и без этого тень легла бы прямо на фотографию. */
.header--over.is-over-photo {
  background: transparent;
  border-bottom-color: transparent;
  box-shadow: none;
}

/* ЛИНИЯ ПОД ШАПКОЙ НА ГЛАВНОЙ — возвращена Стасом 27.07.2026.
   История: 26.07.2026 он её снял, потому что она включалась мгновенно, ровно
   в момент ухода кадра, и читалась как вспышка поперёк экрана. Причина была
   не в самой линии, а в щелчке: тогда же переход сделали плавным, 0,35 с.
   Теперь линия проявляется вместе с фоном и тенью, вспышки нет — и шапка
   перестала сливаться со страницей. Линия берётся из общего правила .header;
   отдельного «выключателя» здесь больше нет, и это намеренно. */

/* ДЫМ ПОД ШАПКОЙ. Настройки утверждены Стасом 20.08.2026 на живой странице
   (эталон — 7-Сайт/первый-экран.html, панель с ползунками). Числа перенесены
   из превью один в один, менять их без Стаса нельзя:

     плотность вверху        0.72   (было 0.58 — поднято 25.08.2026, см. ниже)
     плотность у низа шапки  0.72   (то есть заливка РОВНАЯ, без перепада)
     хвост ниже шапки        0      (наружу дым не выходит НИ НА ТОЧКУ)
     зерно                   нет
     дым                     только пока за шапкой первый экран
     линия под шапкой        нет

   Что здесь стояло раньше и почему поменялось. До 20.08.2026 за шапкой была
   фотография гостиной, и дым шёл от 1.00 у знака до 0.65 на строке меню —
   мягкой s-образной кривой в тринадцать ступеней, поверх неё зерно. И кривая,
   и зерно лечили одну болезнь: плавный переход экран рисует ступеньками, а на
   большой площади глаз ловит границу между ними как линию.

   Теперь за шапкой не фотография, а материал коллекции, и Стас выбрал ровную
   вуаль: верх и низ на одном значении 0.58. Перепада нет — значит нет ни
   ступенек, ни границы, и разбивать зерном больше нечего. Зерно на ровной
   заливке только грязнит фактуру, поэтому снято его же ползунком.

   ПЛОТНОСТЬ ПОДНЯТА 0.58 → 0.72 (25.08.2026). Причина: в тот же день с текста
   шапки снят светлый ореол под буквами — Стас: «убрать вот это подсвечивание,
   чтобы было видно избранное, партнёрам, контакты, коллекции, бренд, номер
   телефона», и про вуаль там же: «её оставить такой, просто нужно доработать,
   чтобы видно было».

   Мешал тексту не контраст, а РИСУНОК фактуры: при 0.58 сквозь вуаль проходит
   42 % контраста прожилок ореха, и тонкий штрих Spectral спорит с ними за
   внимание. Замер по живой странице: контраст букв к фону и при 0.58 был
   7,4 : 1 — вдвое выше книжного порога, то есть яркости хватало всегда.
   При 0.72 сквозь вуаль проходит 28 % рисунка: прожилки и зерно кожи видно,
   но под буквами фон становится ровным.

   Выше не идём: с 0.78 материал начинает выглядеть выбеленным, а первый экран
   держится именно на том, что это настоящий орех и настоящая кожа.

   ХВОСТ по-прежнему НОЛЬ. Прежний дым был 400px при шапке в 150–289px, торчал
   из-под неё на четверть экрана и лежал поверх содержимого; когда он гас, эта
   полоса разом меняла цвет — Стас видел это как «то пропадает, то появляется».
   Дым обрезан ровно по шапке: гаснуть снаружи нечему. */
.header--over::after {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 100%;
  z-index: -1;
  pointer-events: none;
  opacity: 0;
  transition: opacity .35s ease;
  background: rgba(246, 243, 238, .72);
}

.header--over.is-over-photo::after { opacity: 1; }

/* Открылись сразу в середине страницы: кадра за шапкой уже нет, а класс
   is-over-photo напечатан в разметке — он рассчитан на верх страницы.
   Отменяем его здесь, до того как отработает app.js. Иначе шапка мигнёт
   прозрачной поверх содержимого и только потом станет бежевой.
   Класс pre-past-photo вешает скрипт в <head>, когда помнит, что человек
   стоял дальше первого экрана. */
.pre-past-photo .header--over.is-over-photo {
  background: var(--header-bg);
  border-bottom-color: var(--line);
  box-shadow: 0 10px 24px -14px rgba(33, 29, 24, .22);
}

.pre-past-photo .header--over.is-over-photo::after { opacity: 0; }

/* ОРЕОЛ ПОД БУКВАМИ СНЯТ — слово Стаса 25.08.2026: «убрать вот это
   подсвечивание, чтобы было видно избранное, партнёрам, контакты, коллекции,
   бренд, номер телефона».

   Что тут стояло раньше и почему ушло. Под каждой буквой лежал светлый ореол
   в три слоя (16, 6 и 2 px), им лечили читаемость поверх фотографии гостиной:
   под текстом была то белая штора, то тёмная рама окна. Ореол честно держал
   контур, но вблизи читается как свечение — буква сидит в светлом пятне,
   и типографика перестаёт быть чистой.

   Чем читаемость держится теперь: за шапкой больше не фотография комнаты,
   а ровный материал коллекции под вуалью, и тексту хватает своего цвета.
   Вуаль доведена до плотности, при которой самый светлый кусок фактуры
   даёт контраст выше книжного порога (см. .header--over::after).

   Цвет остаётся --ink — это тот же тон, которым меню набрано на бежевых
   страницах, то есть один на весь сайт. */
.header--over.is-over-photo .nav a,
.header--over.is-over-photo .header__tel,
.header--over.is-over-photo .listbtn {
  color: var(--ink);
}

/* УТОЛЩЕНИЕ ШТРИХА В МЕНЮ СНЯТО — там же, 25.08.2026, вместе с ореолом.

   Что стояло: буквам добавляли .32px контура их же цветом и отключали
   подтоньшение macOS. Это лечило дребезг контура на фотографии с жалюзи —
   шаг полоски совпадал с толщиной штриха Spectral на 17 px. За шапкой
   первого экрана давно не та фотография, а ровный материал коллекции:
   дребезжать не обо что, и утолщённый штрих только делал меню жирнее,
   чем на остальных страницах.

   Теперь меню над кадром набрано ровно так же, как на бежевых страницах:
   тот же вес 500, тот же тон --ink, та же разрядка. */

/* Бронзу при наведении приходится повторить: правило выше набрано из трёх
   классов и перебивает общее .nav a:hover — без этой строки пункт на первом
   экране раздвигался бы, но цветом не откликался. Ореол ему остаётся. */
.header--over.is-over-photo .nav a:hover,
.header--over.is-over-photo .nav a[aria-current="page"] { color: var(--bronze); }

/* Рамка кнопки цвета --line на светлом снимке не видна совсем — на время
   первого экрана делаем её тоном самого текста, только приглушённым. */
.header--over.is-over-photo .listbtn { border-color: rgba(33, 29, 24, .3); }
.header--over.is-over-photo .listbtn:hover { border-color: var(--ink); }

/* Счётчик над снимком. Ореол цифре вредит — она от него расплывается, поэтому
   снимаем. А вот черта, наоборот, на светлом кадре пропадает: .34 хватает на
   бежевой странице, но не на фотографии. Там она плотнее. */
.header--over.is-over-photo .listbtn__count {
  text-shadow: none;
  border-left-color: rgba(33, 29, 24, .45);
}

/* Бургер на телефоне — три тонкие линии, на светлом снимке теряются так же,
   как буквы. Тень им даёт filter: у линий нет текста, text-shadow не работает. */
.header--over.is-over-photo .burger span {
  filter: drop-shadow(0 0 6px rgba(246, 243, 238, .95));
}

/* Знак на первом экране лежит на голом снимке: дымки под шапкой больше нет.
   Ореол ему нужен по той же причине, что буквам, и делается тем же способом,
   что бургеру — знак это картинка, text-shadow на неё не действует.
   Тень мягкая и широкая: на кадре её не видно, а контур знака держит. */
.header--over.is-over-photo .logo__img {
  filter: drop-shadow(0 0 12px rgba(246, 243, 238, .8));
}

/* Заголовок только для поисковых машин: на экране его нет, но программа
   чтения с экрана и робот его видят. display:none не годится — тогда он
   пропадает и для них. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ---------- секции ---------- */

.section { padding: clamp(56px, 7vw, 96px) 0; }

/* Первый блок после первого экрана. Отступ сверху чуть меньше обычного:
   над ним не заголовок, а край фотографии во весь экран — воздуха и так хватает. */
.section--first { padding-top: clamp(44px, 5vw, 72px); }
.section--line { border-top: 1px solid var(--line); }
.section--dark { background: var(--dark); color: #ded7ca; }
.section--dark .h-section { color: #fdfbf7; }
/* правило системы: вес 300 живёт только на светлом фоне */
.section--dark .lead { font-weight: 400; color: #ded7ca; }
.section--dark .eyebrow { color: var(--bronze-dim); }

.section__head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px;
  margin-bottom: clamp(28px, 4vw, 46px);
}

.section__head p { margin: 10px 0 0; max-width: 54ch; color: var(--muted); font-size: 16px; }

/* Шапка блока предметов на главной. Утверждена Стасом 31.07.2026 на листе
   7-Сайт/превью-заголовок-блока.html, вариант Д: титул с курсивным акцентом
   на двух словах, крупная подводка, ссылка по нижней линии текста.
   Значения — из настроек, которые он прислал: титул 74, подводка 21,
   воздух под шапкой 55. Верхние границы клэмпов равны этим числам и держатся
   на всей его ширине окна (от 1200 px), ниже размеры ужимаются пропорционально.
   Правило системы про курсив соблюдено: акцент ровно на двух словах. */
.section__head--lead {
  gap: 40px;
  margin-bottom: clamp(34px, 4.6vw, 55px);
}

.section__head--lead .eyebrow { margin-bottom: 18px; }

.section__head--lead .h-section { font-size: clamp(30px, 6.2vw, 74px); }

.section__head--lead .section__sub {
  margin: 18px 0 0;
  max-width: 66ch;
  font-size: clamp(17px, 1.8vw, 21px);
  line-height: 1.62;
  color: var(--muted);
}

/* ---------- блок «О компании» ----------
   Утверждён 02.08.2026, вариант Б2 «журнальная шапка».
   Эталон — 7-Сайт/превью-о-нас-масштаб.html, числа Стас довёл ползунками
   лично и прислал кнопкой 02.08.2026 (вторая доводка, под новый текст).
   Перенесены один в один, верхние границы клэмпов равны его значениям и
   держатся на всей ширине его окна (от 1200 px):

     титул 91 / межстрочное 1.02 · подводка 32,5 / межстрочное 1.2 ·
     бровка 12,5 с разрядкой .25em, отбита на 17 · колонка подводки 49 % ·
     межколонник шапки 0 · воздух до кадров 68 · высота ряда 605 ·
     доля крупного кадра 69 % · зазор 45 · подпись 14,5 с разрядкой .4em ·
     над блоком 116 · под блоком 108

   Межколонник 0 — не оплошность: колонки стоят вплотную, заголовок и
   подводка держатся разной кеглей, а не зазором.

   Блок идёт в ширине витрины (1500, класс shell--shop), а не текстовой
   колонки: кадры одной линией с предметами ниже. Разделительной линии сверху
   нет намеренно — над блоком стоят карточки разделов, лишняя черта дробит. */
/* Фон блока: зона утоплена относительно страницы. Не плашка и не тёмная
   полоса — мягкий радиальный переход от почти-бумаги сверху к более глубокому
   тёплому тону у нижнего края. Разница с --paper небольшая, около четырёх
   процентов светлоты: блок читается как отдельное место, но не кричит.
   Границы у фона нет — он растворяется в странице, поэтому линии не нужны. */
.section--about {
  padding: clamp(64px, 8vw, 116px) 0 clamp(64px, 7.5vw, 108px);
  background: radial-gradient(150% 130% at 50% -15%, #f5f0e7 0%, #ece5d8 100%);
}

/* Подпись справа («Её выбирают дизайнеры…») снята 28.08.2026 по слову Стаса —
   в шапке блока остался один титул, поэтому колонка одна. Вернётся подпись —
   вернуть 1fr 49%. */
.about__head {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0;
  align-items: end;
}

.about__head > * { min-width: 0; }

.about__head .eyebrow {
  font-size: 12.5px;
  letter-spacing: .25em;
  margin-bottom: 17px;
}

/* Мера строки та же, что была у левой колонки шапки (1fr при 1fr 49%) —
   иначе после снятия подписи титул растянулся бы во всю полосу и курсив
   «создаёт интерьеры» перестал бы уходить на вторую строку. */
.about__title { font-size: clamp(34px, 6.1vw, 91px); line-height: 1.02; max-width: 51%; }

.about__sub {
  margin: 0;
  max-width: 52ch;
  font-size: clamp(19px, 2.2vw, 32.5px);
  line-height: 1.2;
  color: var(--read);
}

.about__sub p { margin: 0 0 14px; }
.about__sub p:last-child { margin: 0; }

.about__grid {
  display: grid;
  grid-template-columns: 69% 1fr;
  gap: clamp(14px, 3vw, 45px);
  margin-top: clamp(34px, 5vw, 68px);
  height: clamp(340px, 40vw, 605px);
}

.about__grid > * { min-width: 0; min-height: 0; }

.about__side {
  display: grid;
  grid-template-rows: 1fr 1fr;
  gap: clamp(14px, 3vw, 45px);
  min-height: 0;
}

.about__side > * { min-height: 0; }

.about__ph {
  position: relative;
  margin: 0;
  height: 100%;
  min-height: 0;
  overflow: hidden;
  background-size: cover;
  background-position: var(--focus, 50% 50%);
}

.about__ph img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--focus, 50% 50%);
}

/* Подпись материала лежит на кадре по нижнему краю. Заглавными и с разрядкой —
   как всё служебное в системе; подложка нужна, чтобы буквы читались на светлом
   участке снимка, поэтому это градиент в прозрачность, а не плашка. */
.about__mat {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  margin: 0;
  padding: 14px 16px;
  font-size: 14.5px;
  font-weight: 500;
  letter-spacing: .4em;
  text-transform: uppercase;
  color: #f2ece0;
  background: linear-gradient(to top, rgba(20, 17, 13, .55), rgba(20, 17, 13, 0));
}

/* СРЕДНИЕ ЭКРАНЫ. На 1024 ряд меню упирался в знак (замер 28.08.2026 дал
   зазор −2, то есть слово «ПАРТНЁРАМ» налезало на «Unigue»). Здесь буква
   и разрядка ужимаются, зазор становится 93. */
@media (max-width: 1380px) {
  .nav { gap: 46px; }
  .nav, .header__side { --nav-left: 90px; }
  .header__side { gap: 46px; }
  .nav a { --nav-open: .335em; letter-spacing: .28em; }
}

@media (max-width: 1140px) {
  .nav { gap: 30px; }
  .nav, .header__side { --nav-left: 0px; }
  .header__side { gap: 30px; }
  .nav a { --nav-open: .215em; font-size: 11.5px; letter-spacing: .16em; }
  .header__side { gap: 22px; }
}

@media (max-width: 900px), (max-height: 500px) {
  .about__head { grid-template-columns: 1fr; align-items: start; }
  .about__title { max-width: none; }
  .about__grid { grid-template-columns: 1fr; height: auto; }
  .about__ph { height: 72vw; }
  .about__side { grid-template-rows: auto auto; }
}

/* ---------- блок «Как это сделано» ----------
   Третий блок главной по сценарию восьми блоков (0-База/Контракты.md,
   раздел 2): стоит сразу за первым экраном и отвечает на вопрос, который
   родила фотография, — из чего это сделано. Состав по контракту: короткая
   фраза и макро-фото фактуры, больше ничего.

   Почему он намеренно не похож на блок «О компании», хотя оба про материалы:
   там интерьерные кадры комнат, подписи лежат НА снимке, шапка в две колонки
   и свой тёплый фон; здесь фактура вплотную, ряд равных кадров, подписи под
   ними обычным текстом и фон страницы. Два одинаковых по приёму блока на одной
   странице читались бы как повтор.

   Титул 56 — ступенька ниже «О компании» (91) и блока предметов (74): у этого
   блока работают кадры, а не буквы. */
/* ── ФИРМЕННЫЙ ФОН БЛОКА (утв. Стасом 8.09.2026) ──
   #dfd5c5 — тёплый песочный, тот же, что утверждён 3.09.2026 для карточки
   OLIVIA. Полоса идёт во всю ширину экрана, поэтому блок читается
   отдельным разворотом, а не куском общей страницы. */
.section--made {
  background: #dfd5c5;
  padding-top: clamp(64px, 7vw, 104px);
  padding-bottom: clamp(58px, 6.5vw, 96px);
}
.section--made .made__head { margin-bottom: clamp(30px, 4vw, 52px); }

/* 20ch ставит титул в две строки, курсив целиком уходит на вторую — как
   в блоке «О компании». Верхняя граница клэмпа держится от 1270 px. */
.made__title { font-size: clamp(34px, 5.6vw, 72px); max-width: 18ch; }

.made__sub {
  margin: 18px 0 0;
  max-width: 58ch;
  font-size: clamp(17px, 1.8vw, 21px);
  line-height: 1.62;
  color: var(--muted);
}

.made__grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(12px, 2vw, 30px);
}

.made__item { margin: 0; min-width: 0; }

/* Пропорция 3:4 задана и здесь, и в долях обрезки исходника (MADE_TILES
   в build.py). Менять — только парой: иначе браузер дорежет кадр сам и
   подобранная фактура съедет. */
/* ⛔ ОБРЕЗКИ ПО КРАЮ ЗДЕСЬ НЕТ, И ЭТО ВАЖНО (8.09.2026).
   Волосяная линия вокруг кадра рисуется на самой площадке. Пока стояла
   обрезка, любая линия срезалась ею начисто — четыре захода «сделай
   заметнее» не давали на экране ничего. Кадр вписан в площадку точно
   (object-fit: cover), поэтому обрезка не нужна. */
.made__ph {
  position: relative;
  aspect-ratio: 3 / 4;
  overflow: visible;
  background-size: cover;
  background-position: 50% 50%;
  box-shadow: 0 0 0 1px rgba(52, 40, 22, .55);
}

.made__ph img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ── ПОДПИСИ ПОД КАДРАМИ (утв. Стасом 8.09.2026) ──
   Было: имя мелким капсом вразрядку и серая фраза — читалось служебной
   биркой. Стало: имя антиквой строчными, тем же почерком, что заголовок
   блока и имена вещей на плитках витрины. Под именем волосяная черта во
   всю колонку — четыре одинаковые черты держат ряд снизу.
   Черта темнее прежней: на песочном фоне прежняя растворялась. */
.made__item figcaption { display: block; margin-top: 22px; }
.made__mat {
  display: block; margin: 0 0 13px; padding-bottom: 13px;
  border-bottom: 1px solid #c5b8a1;
  font-family: var(--display); font-size: clamp(23px, 2vw, 29px); font-weight: 300;
  letter-spacing: .005em; text-transform: none; color: var(--ink); line-height: 1.05;
}
/* Фраза набрана КУРСИВОМ АНТИКВЫ — тем же начертанием, каким в заголовке
   стоит «ручная работа». Прямое имя и курсивная фраза дают контраст,
   которого не было: раньше обе строки шли одной сухой гарнитурой.
   Тон опущен под песочный фон, иначе не дотягивал до порога читаемости
   (было 4,19 при норме 4,5 — стало 5,28). */
.made__note {
  display: block; margin: 0; max-width: 27ch;
  font-family: var(--display); font-style: italic; font-weight: 400;
  font-size: clamp(17px, 1.45vw, 20px); line-height: 1.48; letter-spacing: .004em;
  color: #5b5245; min-height: calc(1.48em * 3);
}

/* ---------- тихий контакт внизу главной ----------
   Контракт, раздел 2, блок 8: «напишите нам» вместо «оставьте заявку».
   Форма с внутренних страниц не убрана — там человек уже смотрит вещь. */
.quiet { max-width: 62ch; }

.quiet__ways {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 30px;
}

.link-arrow {
  font-size: 13px;
  font-weight: 500;
  letter-spacing: .16em;
  text-transform: uppercase;
  border-bottom: 1px solid var(--line);
  padding-bottom: 4px;
  white-space: nowrap;
  transition: border-color .2s;
}

.link-arrow:hover { border-color: var(--ink); }

/* ---------- галерея проекта ---------- */

/* Раздел «Проекты»: наша мебель в жилой квартире. Раскладка идёт рядами,
   а не одной общей сеткой, и это осознанно. В одной сетке двадцать
   вертикальных кадров 2:3 читаются как склад фотографий: одинаковый ритм
   без пауз. Ряды дают ритм 4 · широкий · 3 · 3 · 4 · широкий · 4 — два
   горизонтальных кадра работают вдохом между плотными рядами.
   Тип ряда задан классом из build.py (PROJECT_ROWS), высоту кадра держит
   aspect-ratio: без него ряд ждёт загрузки и прыгает. */
.proj { display: grid; gap: clamp(26px, 3.4vw, 52px); }

.proj__head { margin-bottom: clamp(26px, 3vw, 40px); }

.proj__note {
  margin: 12px 0 0;
  max-width: 54ch;
  color: var(--muted);
  font-size: 16px;
}

.proj__row {
  display: grid;
  gap: clamp(12px, 1.6vw, 24px);
}

.proj__row--quartet { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.proj__row--trio    { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.proj__row--wide    { grid-template-columns: minmax(0, 1fr); }

/* Площадка кадра. Пропорции взяты у оригиналов, а не назначены: съёмка идёт
   вертикально 2:3 и горизонтально 3:2, и если задать общую рамку — вырежется
   половина кадра. Заглушка на время загрузки лежит фоном (lqip из build.py),
   поэтому на её месте не белая дыра. */
.proj__ph {
  position: relative;
  margin: 0;
  overflow: hidden;
  aspect-ratio: 2 / 3;
  background-size: cover;
  background-position: 50% 50%;
}

.proj__row--wide .proj__ph { aspect-ratio: 3 / 2; }

.proj__ph img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ---------- сетка предметов ---------- */

.grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
}

.grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

/* Короткий ряд в «Похожих предметах». Родственников бывает меньше четырёх:
   обеденных столов у нас четыре, кроватей две. Линии сетки нарисованы фоном
   самой сетки, поэтому пустые ячейки закрашивались бежевой плитой во всю
   ширину — рядом с одной карточкой это читалось как поломка. Ряд становится
   короче, карточка остаётся ровно того же размера, что и в полном ряду. */
.grid--n1 { grid-template-columns: minmax(0, 1fr); width: 25%; }
.grid--n2 { grid-template-columns: repeat(2, minmax(0, 1fr)); width: 50%; }
.grid--n3 { grid-template-columns: repeat(3, minmax(0, 1fr)); width: 75%; }

/* То же самое, но для витрины каталога и раздела — она идёт по три в ряд.
   Понадобилось 27.08.2026, когда разделы стали называться по печатным
   каталогам и измельчали: в «Кабинете» и «Туалетных столиках» на вкладке
   «в наличии» стоит одна вещь, и справа от неё лежала бежевая плита в 923
   точки. Ставит классы applyFilters() в app.js — число видимых карточек
   меняется на лету переключателем и фильтрами, из сборки его не угадать. */
.grid--vit1 { grid-template-columns: minmax(0, 1fr); width: 33.34%; }
.grid--vit2 { grid-template-columns: repeat(2, minmax(0, 1fr)); width: 66.67%; }

/* Карточка доведена 28.07.2026 по разбору со Стасом. Раскладку он утвердил
   как есть: три в ряд, белая карточка, тонкие линии сетки. Переделано только
   внутреннее устройство — и переделано не на вкус, а по типографике, которую
   он утвердил 25.07.2026 (4-Стиль/Превью-типографика-финал.html). Расхождений
   с эталоном было пять: площадка под предметом была белой вместо тёплой,
   артикул стоял над названием вместо своего места под типом, метка наличия
   жалась справа от цены, между ними шла лишняя линия, а отступы между всеми
   строками были одинаковые по 7 точек вместо 18 · 4 · 12 · 10 · 8.
   Лист подбора, по которому это утверждено: 7-Сайт/превью-карточки.html. */

.card {
  position: relative;
  background: var(--card);
  display: flex;
  flex-direction: column;
}

.card__ph {
  position: relative;
  /* ⭐ 3:2 вместо 4:3 — утв. Стасом 28.08.2026 вместе с подписью плитки.
     Считано по всем 224 карточкам витрины: при 4:3 вещь занимала по высоте
     55 % площадки, при 3:2 занимает 62 %, воздух над предметом упал со 151
     точки до 111. Ниже 3:2 не идём: на 16:10 в потолок высоты упираются
     десять вещей (стеллаж, вешалка, бар, витрина) и делаются мельче
     расчётного размера до 14 %. */
  aspect-ratio: 3 / 2;
  /* Раскладка flex, а не grid, и это важно. В grid высоту строки задаёт сам
     снимок, поэтому ограничение max-height в процентах браузеру не от чего
     считать — он его молча пропускает, и высокий предмет вылезает за низ
     площадки. На этом срезало ножки у стульев LOCCA и PACE. Во flex процент
     считается от высоты самой площадки, и ограничение работает. */
  display: flex;
  /* предметы прижаты к низу площадки: так они стоят на одной поверхности,
     а не висят каждый на своей высоте */
  align-items: flex-end;
  justify-content: center;
  padding: 22px 22px 20px;
  /* тёплая площадка из эталона: она отделяет вещь от карточки и убирает вид
     товара на подложке магазина. Работает только потому, что фон снимков
     вырезан в build.py — иначе белый фон файла встал бы прямоугольником */
  background: #efeae1;
  overflow: hidden;
}

/* --k — во сколько раз увеличить предмет, чтобы вещи в ряду весили одинаково.
   Считается по площади предмета в точках, см. optical_weight() в build.py.
   76 % — запас, чтобы самая узкая вещь с большим коэффициентом не вылезла
   за края площадки. */
.card__ph img {
  max-width: calc(76% * var(--k, 1));
  max-height: calc(76% * var(--k, 1));
  width: auto;
  object-fit: contain;
}

/* У части предметов в базе вместо снимка на белом — кадр интерьера: комната,
   ковёр, окно. Вырезать там нечего, и ставить такой кадр «предметом» посреди
   площадки нельзя — он повиснет прямоугольником. Он занимает площадку целиком,
   как кадр раздела. Определяет это build.py: убирать почти нечего — значит
   снимок интерьерный. */
.card--photo .card__ph { padding: 0; background: none; }
.card--photo .card__ph img {
  width: 100%;
  height: 100%;
  max-width: none;
  max-height: none;
  object-fit: cover;
}

/* ---------- ПОДПИСЬ ПЛИТКИ — УТВЕРЖДЁННЫЙ ЭТАЛОН (28.08.2026) ----------

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

   Прежние шесть уровней типографики от 28.07.2026 этим решением отменены.
   Эталон — 7-Сайт/превью-карточка-витрины.html, диван OLIVIA. */

.lb {
  /* карточка перестаёт быть «фото плюс белая полка»: низ взят на полтона
     светлее площадки, ступенька между ними почти пропадает, и вещь с подписью
     лежат на одном листе бумаги */
  background: #f4efe7;
  padding: 34px 34px 36px;
  display: flex;
  flex-direction: column;
  flex: 1;
}

.lb-name {
  font-family: var(--display);
  font-weight: 300;
  font-size: 40px;
  line-height: 1.05;
  letter-spacing: .012em;      /* почти без разрядки: разрядка в имени —
                                  это витрина торгового центра */
  color: var(--ink);
  margin: 0;
  font-feature-settings: 'liga' 1, 'clig' 1, 'kern' 1;
  text-rendering: optimizeLegibility;
}

/* коллекция курсивом той же антиквы — она подписывает вещь, а не маркирует.
   У складских предметов вне обеих коллекций строки просто нет */
.lb-coll {
  font-family: var(--display);
  font-style: italic;
  font-weight: 300;
  font-size: 20px;
  line-height: 1.2;
  letter-spacing: .01em;
  color: var(--bronze);
  margin-top: 10px;
  /* курсив наклонён вправо, поэтому его левый край оптически «отступает» от
     края имени. Полторы точки влево — и обе строки встают на одну вертикаль */
  margin-left: -1.5px;
  font-feature-settings: 'liga' 1, 'clig' 1, 'kern' 1;
}

/* Цена набрана той же антиквой, что имя: у Cormorant цифры старостильные —
   единица ростом со строчную букву, семёрка с хвостом ниже строки. В книге так
   набирают числа внутри текста, и цена перестаёт выглядеть ценником.
   margin-top: auto прижимает её к низу, поэтому ряд идёт ровной линией
   независимо от длины имени. */
.lb-price {
  font-family: var(--display);
  font-weight: 400;
  font-size: 25px;
  line-height: 26px;
  letter-spacing: .015em;
  color: var(--ink);
  white-space: nowrap;
  font-feature-settings: 'kern' 1;
  margin-top: auto;
  padding-top: 32px;
}
.lb-rub { color: var(--muted); margin-left: 5px; font-size: 19px; }
.lb-price--ask { color: var(--muted); }
.lb-price small { font-size: .72em; color: var(--muted); }

.price {
  font-family: var(--text);
  font-weight: 500;
  font-size: 21px;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.price small { font-size: 15px; font-weight: 400; color: var(--muted); letter-spacing: 0; }

/* «Цена по запросу» вместо числа. Кегль мельче и тон приглушённый: это не
   цена, и выглядеть как цена оно не должно. Строка стоит на том же месте,
   поэтому ряд карточек не разъезжается. */
.price--ask {
  font-size: 17px;
  font-weight: 400;
  color: var(--muted);
  letter-spacing: 0;
}

/* метка наличия */
.stock {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--text);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: .20em;
  text-transform: uppercase;
  color: var(--stock);
}

.stock::before {
  content: '';
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--stock);
}

/* Метка предмета под заказ. Зелёный на сайте значит «можно забрать сейчас»
   и остаётся только у наличия — иначе метка перестаёт что-либо сообщать.
   Заказ помечен бронзой: она в системе уже есть как акцент. */
.stock--order { color: var(--bronze); }
.stock--order::before { background: var(--bronze); }

/* Кнопка «в список» на карточке. В покое — только знак: белая рамка была
   самым магазинным пятном на витрине. Рамка приходит с наведением на карточку
   и только там, где есть мышь. В утверждённом эталоне карточки сердечка нет
   вовсе, поэтому его вид ничем не связан. */
.fav {
  position: absolute;
  top: 12px;
  right: 12px;
  z-index: 3;
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  border: 1px solid transparent;
  background: none;
  color: #b3aa9c;
  transition: color .2s, border-color .2s, background-color .2s;
}

.fav:hover { color: var(--ink); border-color: var(--ink); }
.fav[aria-pressed="true"] { color: var(--bronze); border-color: var(--bronze); }
.fav svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 1.6; }
.fav[aria-pressed="true"] svg { fill: currentColor; }

/* ссылка-перекрытие всей карточки */
.card__link { position: absolute; inset: 0; z-index: 1; }

/* ---------- наведение на карточку ----------

   Утверждено Стасом 28.07.2026 на листе 7-Сайт/превью-карточки.html, числа
   он подобрал ползунками сам: увеличение +5 %, время 1,2 с, тень 20,
   разгон — та же кривая, что у знака при загрузке.

   Три правила, за которые тут заплачено отладкой:
     1. Всё живёт в @media (hover: hover). На сенсорном экране наведение
        залипает после касания — карточка осталась бы поднятой до следующего
        тычка по другой.
     2. Тень НЕ анимируется свойством box-shadow: браузер пересчитывал бы её
        каждый кадр, а на каталоге таких карточек 51 — это ровно тот путь,
        которым уже приходил фриз. Тень лежит отдельным слоем, меняется
        только прозрачность.
     3. Кривая с мягким разгоном. cubic-bezier(.2,.6,.2,1) Стас забраковал
        на гармошке словом «очень резко» — причина в быстром старте.
     4. Карточка держит подъём до конца затухания. Разбор Стаса 28.07.2026:
        «перевожу курсор на соседнюю — тень резко обрывается». Гасла она как
        раз плавно, а обрывал её z-index: он менялся скачком, и не успевшая
        догореть тень тут же уходила под белый фон соседних карточек. Теперь
        карточка опускается обратно не сразу, а через 1,2 с — ровно когда
        тени уже не видно. При наведении подъём мгновенный, задержки нет. */

@media (hover: hover) {
  /* Приход и уход идут разным временем. Правило простое: свойства, записанные
     в самой .card, работают на УХОД, а те, что в .card:hover, — на приход.
     Приход — утверждённые 1,2 с. Уход — 1,8 с: Стасу нужно, чтобы соседняя
     карточка «отпускала» мягче, чем берёт. */
  .card {
    z-index: 1;
    transition: z-index 0s linear 1.8s;
  }

  .card::before {
    content: '';
    position: absolute;
    inset: 0;
    box-shadow: 0 36px 92px rgba(33, 29, 24, .22);
    opacity: 0;
    transition: opacity 1.8s cubic-bezier(.32, .04, .18, 1);
    pointer-events: none;
  }

  .card:hover {
    z-index: 2;
    transition-delay: 0s;
  }
  .card:hover::before {
    opacity: 1;
    transition-duration: 1.2s;
  }

  .card__ph img { transition: transform 1.8s cubic-bezier(.32, .04, .18, 1); }
  .card:hover .card__ph img {
    transform: scale(1.05);
    transition-duration: 1.2s;
  }

  /* движение карточки медленное и почти незаметное: имя темнеет, лист под
     подписью светлеет на полтона. Никаких выездов и кнопок */
  .lb { transition: background 1.4s cubic-bezier(.32, .04, .18, 1); }
  .lb-name { transition: color 1.2s cubic-bezier(.32, .04, .18, 1); }
  .card:hover .lb { background: #f8f4ee; }
  .card:hover .lb-name { color: #100d09; }
}

/* ---------- разделы на главной ---------- */

/* Блок 4 сценария: три карточки — Диваны, Столы, Кресла. Кадр в карточке
   живой интерьерный, а не предмет на белом. Перестроено 26.07.2026 по разбору
   Стаса, кадры им же утверждены. Что нельзя вернуть:
     линии между карточками — из витрины получался прайс-лист;
     счётчик «8 предметов» под подписью — язык склада, а у мелкой категории
       он ещё и кричит, что выбора нет;
     заголовок над блоком — три вещи и ссылка «Весь каталог» объясняют себя сами.
   Ссылка стоит ПОД карточками: поставишь сверху — из-под первого экрана будет
   выглядывать строка со ссылкой, а выглядывать должен верх фотографий. */

/* Оформление утверждено Стасом 26.07.2026 — вариант «В» листа сравнения
   7-Сайт/превью-разделы.html. Главное в нём не украшение, а масштаб: блок
   выходит из колонки 1280 и идёт во всю ширину окна, кадры вырастают почти
   вдвое. Поля по краям — только чтобы снимки не липли к рамке окна.
   Состав варианта целиком описан в build.py, над INDEX_TILES. */
.cats-wide {
  width: 100%;
  padding: 0 clamp(20px, 2.4vw, 40px);
}

/* ГАРМОШКА. Наводишь на карточку — она раздвигается, соседние уступают место.
   Утв. Стасом 27.07.2026, эталон 7-Сайт/превью-анимации.html, лист 2.

   Ряд собран на flex, а не на grid: ширину меняем через flex-grow, и соседи
   ужимаются сами. Растягивать карточку через scaleX нельзя — кадр исказится,
   диван станет шире, чем он есть.

   Первая версия (в 1.4 раза, 0,55 с, кривая .2 .6 .2 1) забракована: «очень
   резко». Резкость шла от быстрого старта кривой, а не только от скорости —
   поэтому сменили и то и другое.

   С 29.07.2026 карточек пять, и гармошка стала не украшением, а частью
   решения: пятая доля экрана узка, и раскрытие возвращает предмету размер.
   Поэтому силу подняли — см. flex-grow ниже. */
.cats {
  display: flex;
  gap: clamp(14px, 1.4vw, 20px);
}

.cat {
  display: block;
  flex: 1 1 0;
  min-width: 0;
  transition: flex-grow 820ms cubic-bezier(.34, .04, .26, 1);
}

/* Только там, где есть настоящая мышь. На сенсорном экране hover «залипает»
   после касания: карточка осталась бы раздвинутой до следующего тычка. */
/* 1.40 — утв. Стасом 29.07.2026 ползунком в «превью-разделы-пять.html».
   До этого стояло 1.22 при трёх карточках. Считать эффект надо от доли ряда,
   а не от самого числа: при трёх карточках 1.22 давало карточке 37,9 % ряда
   вместо 33,3 — прибавка почти пять пунктов. При пяти то же 1.22 дало бы
   23,4 % вместо 20 — втрое слабее на глаз, движение почти пропадало.
   1.40 возвращает прибавку к прежним пяти пунктам (25,9 % вместо 20). */
@media (hover: hover) {
  .cats .cat:hover { flex-grow: 1.40; }
}

/* Карточка вертикальная: снимок горизонтальный, в 4:5 он обрезается по бокам,
   зато предмет крупный. Какую часть кадра держать — переменная --focus,
   её печатает build.py из INDEX_TILES, в CSS значения не дублируем.
   Фон под кадром — заглушка из build.py, чтобы на её месте не было белой дыры. */
/* contain: paint — обещание браузеру, что за пределы рамки карточка не рисует.
   Тогда при прокрутке и при наведении он перерисовывает только её саму,
   а не всю полосу страницы. Кадры тут крупные, экономия заметная. */
/* Высота задана числом, а не пропорцией 4/5: карточка теперь тянется вместе с
   окном, и при пропорции блок на широком мониторе вырастал бы до полутора
   тысяч точек. Нижняя граница держит кадр вертикальным на планшете, верхняя
   не даёт ему перерасти экран на большом мониторе.

   515 px — утв. Стасом 29.07.2026 ползунком в «превью-разделы-пять.html» на
   окне шириной ~1710 px, отсюда множитель 30vw (1710 × 0.30 = 513). До этого
   стояло clamp(380px, 44vw, 660px) под три карточки. Понижать пришлось из-за
   ширины: пятая доля экрана — это ~310 px, и при прежних 660 карточка стала
   бы колонной 1:2,1. При 515 пропорция 1:1,66 — близко к прежней 1:1,34. */
.cat__ph {
  position: relative;
  height: clamp(340px, 30vw, 560px);
  overflow: hidden;
  contain: paint;
  background: #e9e4da 50% 50% / cover no-repeat;
}

.cat__ph img {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
  object-position: var(--focus, 50% 50%);
  transition: transform .7s cubic-bezier(.2, .6, .2, 1);
}

/* Наведение: кадр чуть наезжает. Затемнения не делаем — плёнки поверх фото
   гасят свет и цвет, ради которых кадр и выбран (то же правило, что на первом
   экране). Движение видно и без них. */
.cat:hover .cat__ph img { transform: scale(1.035); }

/* Строка над кадром: слово и «смотреть →». Выравнивание по baseline —
   по линии, на которой стоят буквы: слово антиквой и мелкие капсы разного
   роста, по верхнему краю они бы прыгали.

   Номера 01/02/03 сняты 27.07.2026 (Стас: «нужны ли вот эти 01, 02, 03,
   это зачем?»). Разделов три, считать нечего, а мелкая бронзовая цифра
   читается как пункт списка. Правило .cat__num удалено вместе с ними —
   если номера когда-нибудь вернутся, восстанавливать надо и разметку
   в build.py, и стиль здесь. */
.cat__head {
  display: flex;
  align-items: baseline;
  gap: 18px;
}

/* 48px — размер утверждён Стасом 29.07.2026 ползунком в листе подбора
   «превью-разделы-пять.html», на окне ~1710 px. До того стояло 44 (27.07),
   ещё раньше 52. Веса не трогаем: эталон типографики держит Cormorant
   в 300–400 и запрещает жирные начертания, поэтому «посерьёзнее» здесь
   добывается только кеглем.
   Множитель снижен с 3.6vw до 2.8vw вместе с переходом на пять карточек:
   3.6vw упирался в потолок уже на 1220 px, и на среднем экране слово не
   помещалось в узкую карточку рядом со «смотреть →». 2.8vw даёт потолок 48
   ровно на 1710 px, а ниже слово мельчает вместе с карточкой. */
.cat__name {
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(28px, 2.8vw, 48px);   /* Cormorant ниже 26px не опускается */
  letter-spacing: .02em;
  color: var(--ink);
  margin: 0;
}

/* «смотреть →» лежит в разметке всегда, показывается при наведении и при
   переходе с клавиатуры. Уезжает вправо на 8px, чтобы движение было заметным
   без затемнения кадра. */
.cat__go {
  margin-left: auto;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--bronze);
  white-space: nowrap;
  opacity: 0;
  transform: translateX(-8px);
  transition: opacity .35s, transform .35s;
}

.cat:hover .cat__go,
.cat:focus-visible .cat__go { opacity: 1; transform: none; }

/* Волосяная линия между словом и кадром. Это НЕ линия между карточками —
   те запрещены: разделители рисуют сетку-таблицу. Эта живёт внутри карточки
   и связывает подпись с её снимком. */
.cat__rule {
  height: 1px;
  background: var(--line);
  margin: 16px 0 22px;
  transition: background .35s;
}

.cat:hover .cat__rule { background: var(--bronze-dim); }

/* На телефоне и планшете наведения нет — надпись там просто видна всегда,
   иначе половина оформления пропадает у тех, кто смотрит с телефона. */
@media (hover: none) {
  .cat__go { opacity: 1; transform: none; }
}

.cats__foot {
  display: flex;
  justify-content: flex-end;
  margin-top: clamp(22px, 2.6vw, 32px);
}

/* ---------- плитки категорий (внутри каталога) ---------- */

/* Плитки разделов. Колонок четыре, а не пять: 27.08.2026 разделов стало
   одиннадцать (они названы по печатным каталогам), и при пяти колонках
   последний ряд был одна плитка «Кабинет» плюс пустая полоса в четыре
   ячейки — фон сетки читался как поломка.

   Хвост ряда закрывает последняя плитка. Правило написано через nth-child,
   чтобы не зависеть от того, сколько разделов сейчас: она растягивается
   ТОЛЬКО когда сама стоит третьей в своём ряду (одна пустая ячейка справа)
   или первой (пустых три). Станет разделов ровно на четыре — ни одно
   из правил не сработает, и ряд останется ровным сам по себе. */
.tiles {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
}

/* Хвост ряда закрывает последняя плитка: правило написано через nth-child,
   чтобы не зависеть от числа разделов. Сейчас их пять — ряд полный, ни одно
   из правил не срабатывает; они держат вёрстку, если разделов станет иначе. */
.tiles > .tile:last-child:nth-child(5n + 1) { grid-column: 1 / -1; }
.tiles > .tile:last-child:nth-child(5n + 4) { grid-column: span 2; }

.tile {
  background: var(--card);
  padding: 22px 20px 24px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  min-height: 240px;
  transition: background .25s;
}

.tile:hover { background: #fbf9f5; }

.tile__ph { flex: 1; display: grid; place-items: center; overflow: hidden; }
.tile__ph img { max-height: calc(130px * var(--tk, 1)); width: auto; object-fit: contain; }

/* Место под две строки держим всегда: «Журнальные столы и комоды» в одну
   строку не влезает ни в одном окне, и без резерва эта плитка задирала
   подпись выше соседних — ряд читался ступеньками, а кадр в ней обрезался.
   3.44em = две строки при line-height 1.72. */
.tile__name {
  font-family: var(--display); font-weight: 400; font-size: 26px;
  letter-spacing: .04em; color: var(--ink);
  /* Место под две строки держим у всех плиток, а текст в нём прижимаем К НИЗУ.
     Иначе у однострочных имён («Диваны») под подписью повисала пустая строка,
     и низ ряда читался дырявым, а у двухстрочных («Журнальные столы и комоды»)
     подпись задиралась выше соседних. Прижатый низ выравнивает последнюю
     строку у всех пятерых по одной линии. 3.44em = две строки при lh 1.72. */
  min-height: 3.44em;
  display: flex;
  align-items: flex-end;
}

/* Строка «8 в наличии · 22 под заказ» у разных разделов занимает то одну
   строку, то две: у кроватей числа короткие и всё влезает, у диванов —
   переносится. Плитка растёт снизу вверх, поэтому название раздела вставало
   на разную высоту, и ряд подписей ехал ступеньками (поймано 14.08.2026 на
   скрине Стаса). Держим место под две строки всегда — ряд встаёт в линию.
   min-height, а не height: раздел с очень длинной строкой не обрежется. */
/* line-height задан явно: у страницы он 1.72, и две строки давали 45 точек,
   а зарезервированные 2.9em считались от него же и не сходились. */
.tile .meta { display: block; line-height: 1.5; min-height: 3em; }

/* ==========================================================================
   ДВЕ КОЛЛЕКЦИИ — вход наверху каталога и своя страница у каждой
   Сделано 24.08.2026, этап 3 плана перестройки.
   Язык взят у створок первого экрана (утв. Стасом 20.08.2026): фактура
   материала во всю полосу, поверх — имя коллекции, линия и «Смотреть
   коллекцию». Значения кегля, разрядки и цвета скопированы из .stvor,
   уменьшен только рост полосы: на главной створка это весь экран,
   здесь — вход в раздел.
   ========================================================================== */

.colls {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  margin-bottom: clamp(40px, 4vw, 64px);
}

.coll {
  position: relative;
  display: block;
  min-height: clamp(190px, 21vw, 280px);
  overflow: hidden;
}

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

/* Тень под подписью. Кожа City Edition светлая, и белое имя на ней читалось
   мутным пятном — поймано снимком 24.08.2026 на экране 1710×1017. Плёнки
   поверх всего кадра здесь нет (её Стас забраковал 20.08.2026 на первом
   экране): затемнение живёт только в нижней трети, где стоит текст, и
   на самом материале не читается. */
.coll__mat::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(20, 16, 10, .52) 0%,
                                      rgba(20, 16, 10, .18) 38%,
                                      rgba(20, 16, 10, 0) 66%);
}

.coll__cap {
  position: relative;
  z-index: 2;
  min-height: clamp(190px, 21vw, 280px);
  padding: clamp(22px, 2.6vw, 38px);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
}

.coll__name {
  font-family: var(--display);
  font-weight: 300;
  font-size: clamp(30px, 3.2vw, 46px);
  line-height: 1;
  letter-spacing: .06em;
  margin: 0;
  color: #f7f2e9;
  text-shadow: 0 2px 40px rgba(20, 16, 10, .5);
  transition: letter-spacing 1000ms cubic-bezier(.22, .61, .36, 1);
}
.coll:hover .coll__name { letter-spacing: .082em; }

.coll__rule {
  height: 1px;
  margin: 18px 0 0;
  background: rgba(247, 242, 233, .5);
  transition: background-color 700ms ease;
}
.coll:hover .coll__rule { background: var(--bronze); }

.coll__go {
  margin: 14px 0 0;
  font-family: var(--text);
  font-size: 12.5px;
  font-weight: 500;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: rgba(247, 242, 233, .88);
}

/* ---------- полоса наверху страницы коллекции ---------- */

.colhead {
  position: relative;
  overflow: hidden;
  min-height: clamp(210px, 24vw, 330px);
  display: flex;
  align-items: flex-end;
}

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

/* То же затемнение снизу, что и у полос каталога: имя коллекции обязано
   читаться и на светлой коже, и издалека — правило со страницы «Бренд». */
.colhead__mat::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(20, 16, 10, .55) 0%,
                                      rgba(20, 16, 10, .20) 42%,
                                      rgba(20, 16, 10, 0) 72%);
}

.colhead__in {
  position: relative;
  z-index: 2;
  padding-top: clamp(40px, 6vw, 90px);
  padding-bottom: clamp(24px, 3vw, 46px);
}

.colhead__eyebrow {
  font-family: var(--text);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: rgba(247, 242, 233, .82);
  margin: 0 0 14px;
  text-shadow: 0 2px 30px rgba(20, 16, 10, .5);
}

.colhead__name {
  font-family: var(--display);
  font-weight: 300;
  font-size: clamp(38px, 5vw, 72px);
  line-height: 1;
  letter-spacing: .05em;
  margin: 0;
  color: #f7f2e9;
  text-shadow: 0 2px 40px rgba(20, 16, 10, .5);
}

/* ---------- слова компании о коллекции ---------- */

/* Боковое поле здесь обязано остаться от .shell — оба класса висят на одном
   узле, и короткая запись padding у .colintro затирала его нулями. На широком
   экране этого не видно: полоса и так уже окна. На телефоне текст коллекции
   ложился вплотную к обоим краям (замер 26.08.2026, обе коллекции). */
.colintro { padding: clamp(32px, 4vw, 54px) var(--gut) clamp(8px, 1.2vw, 16px); }

.colintro__tag {
  font-family: var(--display);
  font-weight: 300;
  font-size: clamp(24px, 2.6vw, 34px);
  line-height: 1.2;
  color: var(--ink);
  margin: 0 0 22px;
}

.colintro__text { max-width: 62ch; }
.colintro__text p { margin: 0 0 16px; }
.colintro__text p:last-child { margin-bottom: 0; }

/* Витрина под текстом коллекции идёт без своего заголовка, поэтому воздуха
   ей нужно меньше сверху, чем странице раздела. */
.pagehead--col { padding-top: clamp(28px, 3.4vw, 46px); }

/* Заголовок общей витрины в каталоге — она идёт под двумя коллекциями. */
.shophead { margin-bottom: clamp(22px, 2.4vw, 34px); }
.shophead .h-section { margin-bottom: 14px; }

/* ---------- телефон: полосы друг под другом ---------- */

@media (max-width: 860px) {
  .colls { grid-template-columns: minmax(0, 1fr); }
  .coll, .coll__cap { min-height: 210px; }
  .colhead { min-height: 190px; }
}

/* ---------- хлебные крошки ---------- */

.crumbs {
  padding: 20px 0;
  font-size: 14px;
  color: var(--muted);
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

/* Над карточкой предмета крошки тише: 20 сверху и снизу съедали 64 точки
   первого экрана, а на 15-дюймовом ноуте кнопка «В избранное» из-за этого
   не помещалась (21.08.2026, замер на 1710×1017). */
.shell--item .crumbs { padding: 11px 0; font-size: 12.5px; }

.crumbs a:hover { color: var(--ink); }
.crumbs span { color: var(--line); }

/* ---------- заголовок раздела ---------- */

.pagehead { padding: clamp(16px, 2vw, 26px) 0 clamp(34px, 4vw, 52px); }
.pagehead .lead { margin-top: 18px; }

/* ---------- панель фильтров ---------- */

/* Переключатель витрины: в наличии · под заказ · все предметы.
   Набран словами, а не кнопками-плашками: ряд чипов ниже и так пёстрый,
   вторая полоса плашек превратила бы верх витрины в панель управления.
   Включённая вкладка бронзовая с волосяной линией под ней — тот же язык,
   что у текущего пункта меню в шапке. */
.modes {
  display: flex;
  flex-wrap: wrap;
  gap: 28px;
  margin-bottom: 4px;
}

.mode {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  padding: 0 0 9px;
  border: 0;
  border-bottom: 1px solid transparent;
  background: none;
  font-family: var(--text);
  font-weight: 500;
  font-size: 13px;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--muted);
  transition: color .25s, border-color .25s;
}

.mode:hover { color: var(--ink); }

.mode.is-on {
  color: var(--bronze);
  border-bottom-color: var(--bronze);
}


/* Врезка вкладки «Под заказ»: что это, срок, оплата, цена, как заказать. */
.ordernote {
  margin-top: 22px;
  padding-top: 22px;
  border-top: 1px solid var(--line);
}

.ordernote__cols {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 30px;
  margin-top: 26px;
}

.ordernote__cols h3 {
  font-family: var(--text);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 8px;
}

.ordernote__cols p { font-size: 16px; }

.ordernote__how { margin-top: 26px; color: var(--read); }
.ordernote__how a { border-bottom: 1px solid var(--line); }

@media (max-width: 720px) {
  .ordernote__cols { grid-template-columns: 1fr; gap: 20px; }
  .modes { gap: 20px; }
}

.filters {
  padding: 18px 0;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  margin-bottom: 34px;
}

/* Ряд фильтров: материалы отдельной строкой, коллекция со сбросом и
   сортировкой — второй. В одну строку они не помещаются. */
.filters__row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
}

.filters__row + .filters__row { margin-top: 12px; }

.filters__label {
  font-family: var(--text);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--muted);
  margin-right: 6px;
}

.chip {
  border: 1px solid var(--line);
  background: transparent;
  padding: 8px 15px;
  font-size: 15px;
  transition: border-color .2s, background .2s;
}

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

.filters__spacer { margin-left: auto; }

.select {
  border: 1px solid var(--line);
  background: transparent;
  padding: 8px 12px;
  font-size: 15px;
  font-family: inherit;
}


.empty-note {
  padding: 60px 0;
  text-align: center;
  color: var(--muted);
}

/* ---------- карточка товара ---------- */

/* Доли колонок и зазор — с листа доводки, утв. Стасом 15.08.2026.
   Снимок занимает 47 % полосы: не половину и не две трети. Остальное держит
   правая колонка, где имя, цена и характеристики. */
/* --act: одна ширина на все блоки правой колонки — пояснение под ценой, ряд
   образцов, кнопки, мессенджеры, описание. Пока каждый жил своей шириной,
   правый край колонки ломался четыре раза сверху вниз. 450 — из утверждённой
   доводки 15.08.2026: кнопка во всю колонку читалась интерфейсом магазина. */
.product {
  --act: 320px;
  /* Ступени воздуха. Внутри смысловой группы — --air-in, между группами —
     --air. Пока все зазоры были 24–28, карточка читалась одним длинным
     списком: имя, цена, образцы, кнопки и описание стояли на равном
     расстоянии и ничем не отличались друг от друга по важности. */
  --air: 28px;
  --air-in: 10px;
  display: grid;
  /* Правая колонка — РОВНО 450, ширина кнопки и всего, что в ней стоит;
     кадр забирает остаток полосы. Пока колонка задавалась долей (47 %, потом
     60 %), её ширина не совпадала с содержимым: справа оставалось от 76 до
     267 точек пустоты, и правый край страницы ломался ступенькой против ряда
     «Похожих». Теперь оба края отвесные, а кадр вырос до 960 — предмет стал
     главным на странице, как и должно на карточке товара. Утверждённые 47 %
     (доводка 15.08.2026) отменены: Стас 21.08.2026 дал переделать композицию. */
  grid-template-columns: minmax(0, 1fr) var(--act, 450px);
  gap: clamp(28px, 4vw, 64px);
  align-items: start;
  padding-bottom: clamp(48px, 6vw, 80px);
}

/* Площадка та же, что в карточке каталога: тёплая, из утверждённой
   типографики. Пока здесь был белый фон, предмет на странице выглядел иначе,
   чем он же в каталоге — человек переходил по карточке и попадал будто к
   другой вещи. */
.product__ph {
  background: #efeae1;
  border: 1px solid var(--line);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  /* Поля срезаны с 60/54 (21.08.2026): при широкой площадке предмет занимал
     56 % её ширины и терялся в бежевом поле. */
  padding: 28px 28px 24px;
  /* Площадка держит пропорцию 1,65 (утв. 15.08.2026), а не растёт по снимку.
     Пока высоту задавал сам снимок, вещи стояли в кадрах разной величины:
     диван упирался в бока и ложился внизу пустого поля, стул упирался в верх
     и казался вдвое крупнее. То же решение, что в плитке каталога, только
     пропорция своя — там 4:3. */
  aspect-ratio: 1.65;
  /* Потолок по высоте окна (21.08.2026). На 13-дюймовом ноуте (1512×860) кадр
     в пропорции 1,65 не влезал в первый экран на 34 точки, а ряд миниатюр
     уходил под нижний край на 157 — человек открывал карточку и не знал, что
     кадров несколько. 380 = шапка 257 + крошки 44 + верхняя треть миниатюр:
     ряд обязан выглядывать из-под кадра, иначе о нём никто не узнает.
     На высоком экране потолок не срабатывает и пропорция остаётся ровно 1,65. */
  max-height: calc(100svh - 380px);
}

/* Крупность считается долей площадки, а не высотой в точках: у длинного дивана
   первым кончается бок, у стула — верх, и ограничение по одной стороне
   работает только для половины каталога. 86 % — доля, утверждённая Стасом,
   --k — оптический вес предмета из optical_weight(), тот же, что в плитке.
   min(…, 100 %) — потолок: вес доходит до 1.3, и без него узкая вещь вылезла бы
   за поля площадки. Ровно так в июле срезало ножки стульям LOCCA и PACE. */
.product__ph img {
  max-width: min(calc(86% * var(--k, 1)), 100%);
  max-height: min(calc(86% * var(--k, 1)), 100%);
  width: auto;
  object-fit: contain;
}

/* ---------- карусель кадров (20.08.2026) ---------- */

/* Фабрика снимает вещь с нескольких сторон — карточка показывает все кадры,
   а не один. Липнет при прокрутке вся обёртка целиком: миниатюры должны
   ехать вместе с площадкой, иначе они уплывают вверх и листать нечем. */
/* Страница предмета листается ровно, без залипаний (21.08.2026, слово
   Стаса: «я хочу, чтобы статично всё было»). Липкая колонка снимков стояла
   с 20.08 и была снята в тот же день, когда он её увидел: залипание всегда
   кончается рывком — кадр стоит, потом догоняет страницу, и на глаз это
   пляска. Возвращать sticky на карточке нельзя ни площадке, ни карусели. */
.product__col { align-self: start; }
.product__ph--gal {
  position: relative;
  top: auto;
  /* Пальцем кадр листается вбок (app.js, setupGallery). Вертикаль забирает
     себе браузер — pan-y отдаёт ему прокрутку страницы целиком, поэтому
     свайп по фотографии никогда не «залипает» и скролл не тормозит.
     На мыши это свойство не действует, десктоп не затронут. */
  touch-action: pan-y;
}

/* Ряд миниатюр обязан быть ровно той же ширины, что кадр над ним.
   Поймано Стасом 25.08.2026: правый край ряда торчал за правый край
   площадки — 17 точек в окне 900 × 1000 и до 238 в невысоком окне 1440 × 700.
   ⚠️ На УЗКОМ экране (≤ 900 px) это лечится не здесь, а снятием потолка
   высоты у самой площадки — см. блок @media ниже. Правка 25.08 закрыла
   только широкий экран, и в окне 900 × 1000 вылет 17 точек жил до 26.08.2026.
   На всех четырёх карточках с каруселью сразу, эталон EMBER включительно:
   поломка живёт с 21.08.2026, с того дня, когда площадке поставили потолок
   по высоте окна.
   Почему так вышло. Площадка держит пропорцию, и когда она упирается в
   max-height, ширина у неё СЖИМАЕТСЯ — а ряд миниатюр остаётся во всю ширину
   колонки, потому что пропорции у него нет и потолок его не касается.
   Лечим не ряд, а обёртку: тем же числом ограничиваем её целиком, и площадка
   с рядом всегда одной ширины. Числа те же, что у потолка площадки:
   380 точек по высоте, пропорция 1,65 (на узком экране 4/3, см. ниже). */
.product__gal { max-width: calc((100svh - 380px) * 1.65); }

/* Кадры лежат в разметке все сразу и переключаются показом: листание идёт
   без запроса на сервер, а браузер тянет соседние кадры лениво. */
.gal__pic { display: none; }
.gal__pic.is-on { display: block; }

/* Чертёж — не предмет: у него нет ни тени, ни полей, и доля площадки своя.
   По оптическому весу предмета его равнять нельзя, иначе размеры мельчают
   до нечитаемости. */
.product__ph .gal__pic--cad {
  max-width: min(calc(96% * var(--k, 1)), 100%);
  max-height: min(calc(96% * var(--k, 1)), 100%);
}

/* Интерьерный кадр — не предмет на площадке, а фотография комнаты, и живёт
   он по другим правилам: занимает площадку ЦЕЛИКОМ, до самых краёв рамки.
   Вписывать его по полям, как предмет, нельзя — снимок повис бы картинкой
   посреди бежевого поля, а это ровно то «дёшево», за которое забракована
   не одна раскладка. Кадр приходит в пропорции площадки (1,65), поэтому
   cover почти ничего не срезает; он тут страховка от кадра другой формы. */
.product__ph .gal__pic--int {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  max-height: none;
  object-fit: cover;
}

/* Стрелки проявляются при наведении на площадку: на бежевом поле постоянные
   стрелки читаются как элемент интерфейса и спорят с предметом. */
.gal__arr {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 14%;
  border: 0;
  background: none;
  padding: 0;
  cursor: pointer;
  color: var(--ink);
  font-size: 30px;
  line-height: 1;
  opacity: 0;
  transition: opacity .2s ease;
}
.gal__arr--l { left: 0; }
.gal__arr--r { right: 0; }
.product__ph--gal:hover .gal__arr { opacity: .45; }
.gal__arr:hover { opacity: 1; }
.gal__arr:focus-visible { opacity: 1; outline: 1px solid var(--ink); outline-offset: -6px; }

/* Ряд миниатюр под площадкой: те же кадры, тот же порядок. Квадрат у каждой
   свой, предмет внутри вписан — иначе низкий табурет растянется на всю
   клетку и станет крупнее кресла. */
.gal__thumbs {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 9px;
  margin-top: 10px;
}
.gal__thumb {
  background: #efeae1;
  border: 1px solid var(--line);
  padding: 7px 6px;
  cursor: pointer;
  /* Миниатюра повторяет пропорцию площадки, а не квадрат: квадратный ряд под
     широкой площадкой читался чужой сеткой, приклеенной снизу. 4:3 — середина
     между площадкой 1,65 и квадратом: предмет ещё узнаётся, ряд уже тонкий. */
  aspect-ratio: 4 / 3;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: border-color .18s ease;
}
.gal__thumb img { max-width: 100%; max-height: 100%; object-fit: contain; }
/* Миниатюра интерьера заполняет клетку целиком — в ряду белых кадров она
   сразу читается как фотография комнаты, а не как ещё один ракурс вещи.
   При contain у неё остались бы поля сверху и снизу, и в ряду она выглядела
   бы мельче соседей — то есть неважнее, хотя она про другое. */
.gal__thumb--int { padding: 0; overflow: hidden; }
/* Позиция карусели, которой у выбранной версии вещи нет. У короткой OLIVIA
   фабрика не снимала ни вида сверху, ни вида сзади: показывать там кадр
   длинной значило бы поставить под её ценой другой диван. Ряд при этом
   собирается сам — сетка сдвигает оставшиеся миниатюры. */
.gal__thumb.is-gone { display: none; }
.gal__thumb--int img { width: 100%; height: 100%; max-width: none; max-height: none; object-fit: cover; }

.gal__thumb:hover { border-color: var(--muted); }
.gal__thumb.is-on { border-color: var(--ink); }

/* Примечание о съёмке живёт при кадрах, а не в правой колонке (21.08.2026).
   В колонке оно вставало четырьмя строками серого между образцами и кнопкой:
   верх карточки набирался из трёх мелких абзацев подряд и читался тяжело. */
.gal__note {
  margin: 18px 0 0;
  font-size: 13px;
  line-height: 1.62;
  color: var(--muted);
  /* 460 — 63 знака в строке; на 640 выходило 88, вдвое длиннее нормы чтения */
  max-width: 460px;
}

/* Пока новый снимок скачивается, старый приглушён. Только opacity: любое
   другое свойство на этой площадке роняет прокрутку. */
.product__ph img { transition: opacity .22s ease; }
.product__ph img.is-swap { opacity: .25; }

/* ---------- размер и материал (план исполнений, 31.08.2026) ----------

   Ряд образцов ниже — про цвет, он меняет кадры. Этот блок — про материал
   и длину, он меняет цену. Держится в тех же числах, что и весь эталон
   карточки: ширина колонки 320, воздух --air между группами, кегли мелкие.
   Кнопка не плашка цвета и не картинка: тут выбирают не вид, а условие
   сделки, и его надо прочитать словами вместе с ценой. */

.plan { margin: var(--air) 0 0; max-width: var(--act, 450px); }

.plan__head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 11px;
}

.plan__label {
  font-size: 11.5px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--muted);
}

.plan__now { font-size: 14.5px; color: var(--ink); }

.plan__sizes,
.plan__mats {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  max-width: var(--act, 450px);
}

/* Воздух между длиной и материалом — --air-in: это одна группа «исполнение»,
   а не две. Подписей над рядами нет, зазор и делит их. */
.plan__sizes { margin-bottom: 12px; }

.plan__opt {
  display: grid;
  gap: 3px;
  min-height: 44px;
  align-content: center;
  padding: 7px 8px;
  border: 1px solid var(--line);
  border-radius: 1px;
  background: none;
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: border-color .18s ease, box-shadow .18s ease;
}

.plan__opt:hover { border-color: var(--muted); }

/* Выбранное — бронзовая линия по кругу. Заливкой не берём: залитая кнопка
   в колонке спорит с главной кнопкой карточки. */
.plan__opt.is-on {
  border-color: var(--bronze);
  box-shadow: inset 0 0 0 1px var(--bronze);
}

.plan__opt:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--paper), 0 0 0 3px var(--ink);
}

/* Имя материала стоит в одну строку и переносом не ломается. Померено:
   самое длинное — «Полукожа с тиснением», 138,7 точки при кегле 13,
   в кнопку помещается 139. На двух строках кнопка вырастает на треть,
   и ряд уносит главную кнопку карточки за первый экран Стаса. */
.plan__t {
  font-size: 13px;
  line-height: 1.25;
  color: var(--ink);
  white-space: nowrap;
}
.plan__p { font-size: 12.5px; line-height: 1.2; color: var(--muted); }
.plan__opt.is-on .plan__p { color: var(--ink); }

/* На узком экране запрет переноса снимаем. Померено на iPhone SE: колонка
   там 284 вместо 320, места под «Полукожа с тиснением» не хватает, и кнопки
   правого столбца вылезали за край блока на 12 точек. Высота там ничего
   не решает — первый экран телефона всё равно листается. */
@media (max-width: 900px) {
  .plan__t { white-space: normal; }
}

.plan__opt--size { justify-items: center; text-align: center; }
.plan__opt--size .plan__t { font-size: 14px; }

/* ⛔ Выбрали ткань — ряда кожаных образцов НЕТ ВОВСЕ (утв. Стасом 1.09.2026).
   До этого ряд гас и не нажимался, а почему — было написано мелкой строкой
   под ним: шесть серых плиток читались сломанными кнопками. Теперь на месте
   ряда стоит одна строка про палитру тканей.

   Запрет «ничего не скрыто» (21.08.2026) этим не нарушен: у ткани цветов
   на сайте нет вообще, и мы говорим об этом прямо. Прячется не выбор,
   а ряд, которому нечего показывать. */
.finish.is-off .finish__head,
.finish.is-off .finish__row { display: none; }

/* Строка встала НА МЕСТО ряда, и свой верхний отступ ей больше не нужен:
   воздух сверху даёт сам блок. Без этого при ткани над строкой стояло
   44 точки пустоты. */
.finish.is-off .finish__note { margin-top: 0; }

/* ---------- исполнения (конфигуратор, 20.08.2026) ---------- */

.finish { margin: var(--air) 0 0; max-width: var(--act, 450px); }
.finish__head { margin-bottom: 10px; }

.finish__head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 13px; }

.finish__label {
  font-size: 11.5px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--muted);
}

.finish__now { font-size: 14.5px; color: var(--ink); }

/* Ряд образцов ровно в ширину кнопки «Добавить в избранное» — 450 (21.08.2026,
   слово Стаса: «конфигуратор должен быть шириной в кнопку»). Раньше образцы
   стояли по своей ширине и ряд обрывался посреди колонки: правый край гулял,
   и блок читался незаконченным. Сетка из трёх равных долей делит эти 450 сама,
   поэтому образец подстраивается под ширину, а не ширина под образец. */
.finish__row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  /* Сверху больше, чем по горизонтали: подпись «ТКАНЬ» стояла ровно между
     двумя рядами и читалась подписью к чужому. */
  gap: 18px 16px;
  max-width: var(--act, 450px);
}

/* ⭐ Ряд по четыре в строку — когда цветов больше шести (2.09.2026).
   По три в строке двенадцать образцов занимают втрое больше места, и кнопка
   «Добавить в подборку» уходит под экран на 147 точек (замерено на экране
   Стаса 1710 × 1017). По четыре образец мельче — 68 точек вместо 96, — но
   это по-прежнему кусок кожи с фактурой, а не плашка цвета. */
.finish__row--4 {
  grid-template-columns: repeat(4, 1fr);
  /* Три ряда образцов вместо двух — воздух между ними ужимаем, иначе кнопка
     «Добавить в подборку» не дотягивает до низа экрана 14 точек (замерено). */
  gap: 12px 14px;
}

/* Образец цвета, которого нет у выбранного материала, из ряда уходит:
   у пяти светлых цветов нарисована только кожа с тиснением. */
.finish__opt.is-gone { display: none; }

/* Название материала стоит строкой над своими образцами и переносит ряд:
   у кресла три кожи и три ткани, и без разделения человек читает шесть
   кружков как шесть цветов одного материала. */
.finish__group {
  grid-column: 1 / -1;
  margin: 2px 0 -6px;
  font-size: 11.5px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--muted);
}

.finish__opt {
  display: block;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: var(--muted);
  cursor: pointer;
  line-height: 0;
}

/* Образец — кусок настоящей обивки, вырезанный из кадра этого исполнения
   (21.08.2026). Плоскую заливку цветом Стас забраковал: «квадратики, ноль
   премиальности» — плашка цвета читается интерфейсом, а кожа и ткань узнаются
   фактурой, зерном и переплетением. Пропорция 3:2 — так отрез материала
   выглядит в мебельном деле, квадрат из него делает плитку кафеля.
   Тень — не украшение: она отделяет материал от бумаги страницы и делает
   образец предметом, который лежит, а не пятном, которое напечатано. */
.finish__chip {
  display: block;
  width: 100%;
  aspect-ratio: 3 / 2;
  border-radius: 1px;
  background-size: cover;
  background-position: center;
  box-shadow: 0 1px 2px rgba(33, 29, 24, .16),
              0 10px 18px -12px rgba(33, 29, 24, .5);
  transition: transform .2s ease, box-shadow .2s ease;
}

.finish__opt:hover .finish__chip {
  transform: translateY(-2px);
  box-shadow: 0 2px 4px rgba(33, 29, 24, .18),
              0 14px 22px -12px rgba(33, 29, 24, .55);
}

/* Выбранный — тонкая бронзовая обводка с зазором. Рамка вплотную читалась бы
   краем самого материала, зазор бумагой отделяет образец от метки. */
.finish__opt.is-on .finish__chip {
  box-shadow: 0 0 0 2px var(--paper), 0 0 0 3px var(--bronze),
              0 1px 2px rgba(33, 29, 24, .16),
              0 10px 18px -12px rgba(33, 29, 24, .5);
}

.finish__opt:focus-visible .finish__chip {
  box-shadow: 0 0 0 2px var(--paper), 0 0 0 3px var(--ink),
              0 1px 2px rgba(33, 29, 24, .16);
}

.finish__note {
  margin: 16px 0 0;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--muted);
  max-width: 440px;
}

/* Кегли правой колонки — с листа доводки, утв. 15.08.2026.
   Имя предмета крупнее прежнего (66 против 54), а строка типа и цена, наоборот,
   тише: на странице вещи главное слово одно — её имя. */
/* Артикульная строка тише имени: 15 капсом растягивалось на 526 точек
   против 205 у самого имени. */
.product .meta { font-size: 11.5px; }
.product__name { font-size: clamp(28px, 2.8vw, 40px); margin: 7px 0 0; }
.product__name + .muted { font-size: 16px; }

/* Цена и метка наличия — одна строка (21.08.2026). Шапка карточки шла шестью
   уровнями подряд: артикул · имя · тип · метка · цена · пояснение. Стас:
   «сверху очень тяжело», и отдельно про строку типа — «убери чуть пониже».
   Тип уехал в опись, метка осталась при цене: кто смотрит цену, тот сразу
   видит, забирать сегодня или ждать поставку. */
.product__pricerow {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 4px 18px;
  /* Цена — начало второй группы: она не про то, ЧТО это, а про то, ПОЧЁМ. */
  margin: calc(var(--air) - 12px) 0 6px;
}

.product__pricerow .product__price { margin: 0; }

.product__price {
  font-family: var(--text);
  font-weight: 500;
  /* Цена крупнее прочих строк колонки, но не спорит с именем предмета. */
  font-size: 18px;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  margin: 22px 0 6px;
}

.product__price small { font-size: 15px; font-weight: 400; color: var(--muted); letter-spacing: 0; }

/* Пояснение под ценой не тянется во всю колонку: мелкая серая строка на
   тысячу точек читается тяжелее, чем та же строка в две — глаз теряет начало
   следующей. Ширина по кнопке, чтобы правый край верха карточки был один. */
.product__pricerow + .muted { max-width: var(--act, 450px); }

/* Предмет под заказ: цены нет, есть заявка. Строка стоит на месте цены,
   но набрана спокойнее — она не число, и притворяться числом ей нечем. */
.product__price--ask { font-weight: 400; color: var(--ink); }

/* Коллекция в строке артикула на плитке. Отбита тоном, а не отдельной
   строкой: шесть уровней карточки — утверждённый эталон, седьмого там нет. */
.card__col { color: var(--muted); }

/* Кнопки не во всю колонку: чёрный прямоугольник на всю ширину читался как
   интерфейс магазина. 450 точек — утв. 15.08.2026. */
.product__actions { display: grid; gap: 10px; margin: var(--air) 0 var(--air-in); max-width: var(--act, 450px); }

/* Кнопка 3D-модели и подпись под ней — одна ячейка сетки кнопок: свой
   зазор 7 px, чтобы подпись читалась как часть кнопки, а не как строка
   карточки. Подпись говорит, в какой программе откроется файл, что внутри
   и сколько весит: архивы до 184 МБ, и качать вслепую нельзя. */
.model-dl { display: grid; gap: 7px; }

.model-note {
  margin: 0;
  font-size: 13px;
  line-height: 1.45;
  color: var(--muted);
}

.product__msg { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 28px; }

/* В карточке предмета две кнопки мессенджеров делят ширину главной кнопки
   пополам: по содержимому они кончались на 320, и правый край колонки ломался
   третий раз подряд. Внизу страницы, в блоке заявки, кнопок три-четыре —
   там сетка из двух колонок увела бы телефон на отдельную строку, поэтому
   правило живёт только внутри .product. */
.product .product__msg {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  max-width: var(--act, 450px);
  margin-bottom: var(--air);
}

/* Надпись — по центру своей кнопки (21.08.2026). В блоке заявки внизу кнопки
   стоят по содержимому, и слово в них само занимает всю ширину; здесь кнопки
   растянуты в половину колонки, и слово с отступом 16 висело у левого края,
   пока справа оставалась пустота. */
.product .product__msg .msg-link { justify-content: center; text-align: center; }

/* ⭐ КНОПКА «СВЯЗАТЬСЯ С НАМИ» НА КАРТОЧКЕ (31.08.2026).
   На её месте стоял ряд из двух мессенджеров — ватсап и телеграм; указывать
   их на сайте нельзя. Кнопка идёт в ширину колонки действий, то есть ровно
   как «Добавить в подборку» над ней, и раскрывает заявку под собой.
   Раскрытая форма не должна двигать соседние блоки: она стоит последней
   в колонке, ниже неё только описание. */
.contact { max-width: var(--act, 450px); margin-bottom: var(--air); }

.contact__box {
  margin-top: 14px;
  padding: 18px 18px 20px;
  border: 1px solid var(--line);
  background: #fbf8f4;
}

.contact__box .form { margin: 0; }

.contact__max {
  margin: 14px 0 0;
  font-size: 14.5px;
  color: var(--muted);
}

.contact__max a { border-bottom: 1px solid var(--line); }

.msg-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  border: 1px solid var(--line);
  padding: 10px 16px;
  font-size: 15px;
  transition: border-color .2s;
}

.msg-link:hover { border-color: var(--ink); }

/* ---------- описание и характеристики в правой колонке (21.08.2026) ---------- */

/* Описание переехало из блока под карточкой в правую колонку, к предмету.
   Причина: колонка со снимками липкая, она стоит на месте, пока читаешь
   правую. Пока описание висело ниже, правая колонка кончалась раньше
   площадки, слева оставалось пустое поле в пол-экрана, а текст читался уже
   без предмета перед глазами. Заголовка «Описание» здесь нет — линия сверху
   отделяет текст от кнопок, а что это за текст, видно по нему самому. */
.product__desc {
  border-top: 1px solid var(--line);
  padding-top: calc(var(--air) - 10px);
  max-width: var(--act, 450px);
  color: var(--read);
  font-size: 16px;
}

.product__desc p { margin: 0 0 14px; }
.product__desc p:last-child { margin-bottom: 0; }

/* Опись стоит открыто (21.08.2026). Полдня она простояла под кнопкой
   «Характеристики», и Стас забраковал: «убери скрытую информацию». Причина
   не только в прятанье — раскрытие двигает страницу, а он хочет, чтобы на
   карточке ничего не ездило. Взамен опись стала короче: артикул и коллекция
   стоят строкой над именем, второй раз их не печатаем. */
/* Опись идёт ровно в ширину кадра — её линии продолжают его край, и левая
   колонка кончается одним отвесом, а не лесенкой из трёх разных ширин.
   Расползтись паре «метка — значение» не даёт фиксированная колонка метки:
   при доле в процентах значение на широком кадре уезжало от своей подписи
   на треть полосы. */
.product .specs { margin-top: var(--air); border-top: 1px solid var(--line); }
/* Метка капсом мельче значения, её базовая линия компенсируется 5 точками:
   без этого первая строка описи стояла на 6 точек выше своего значения. */
.product .specs tr:first-child td { padding-top: 16px; }
.product .specs tr:first-child th { padding-top: 21px; }

/* таблица характеристик */
.specs { width: 100%; border-collapse: collapse; margin: 8px 0 0; }

.product .specs th, .product .specs td { font-size: 15px; padding: 8px 0; }

.specs th, .specs td {
  text-align: left;
  /* строки плотнее прежнего (10 вместо 13): таблица читается описью,
     а не списком пунктов. Утв. 15.08.2026 */
  padding: 10px 0;
  border-bottom: 1px solid var(--line);
  font-size: 16.5px;
  vertical-align: top;
}

/* Метка строки набрана капсом 11,5 с трекингом, а не тем же кеглем, что
   значение (21.08.2026). Двумя одинаковыми колонками опись читалась как два
   столбца текста, между которыми глаз выбирает; капс сразу говорит «это
   подпись, читай справа». Кегль значений — утверждённые 16,5, не тронут. */
.specs th {
  font-weight: 500;
  color: var(--muted);
  /* Метке хватает своей ширины: значение теперь у правого края, наехать
     друг на друга им негде. 230 — минимум под «ИЗГОТОВЛЕНИЕ НА ЗАКАЗ». */
  width: 175px;
  padding-right: 30px;
  font-size: 10.5px;
  letter-spacing: .14em;
  text-transform: uppercase;
  padding-top: 15px;
  line-height: 1.45;
}
/* Значения описи — вторичные данные, тон читателя, а не тон имени.
   Прижаты к правому краю (21.08.2026): метка слева, значение справа, между
   ними воздух — так набирают спецификацию в мебельных каталогах, и правый
   край описи становится отвесом заодно с краем кадра. Пока значение стояло
   сразу за меткой, справа от него до края кадра оставалось полполосы пустоты. */
.product .specs td { text-align: right; }
.specs td { font-weight: 500; color: var(--read); font-variant-numeric: tabular-nums; }

/* Блоки под карточкой — «Описание», «Материалы и уход», «Доставка и оплата».
   Заголовок стоит слева отдельной колонкой, текст справа (утв. 15.08.2026).
   Прежде заголовок висел строкой над текстом, и при полосе в полторы тысячи
   точек правая половина блока оставалась пустой: строка чтения всё равно
   держится 60 знаков, шире её делать нельзя. */
.block {
  padding: 30px 0;
  border-top: 1px solid var(--line);
  display: grid;
  /* Пара «заголовок + текст» стоит по центру полосы, а не жмётся к левому
     краю (утв. 15.08.2026, вариант А). Для этого вторая колонка фиксирована
     по ширине строки чтения — 60 знаков из раздела 6 типографики. Была
     minmax(0, 1fr): такая колонка тянется до правого края, и центрировать
     нечего, а текст всё равно упирался в свои 60 знаков и оставлял справа
     треть полосы пустой. Ширину группы держат колонки, justify-content
     ставит её посередине. */
  grid-template-columns: 410px minmax(0, 60ch);
  justify-content: center;
  /* зазор только между колонками: общий развалил бы абзацы одного блока */
  gap: 0 clamp(28px, 4vw, 64px);
  align-items: start;
}

/* всё, кроме заголовка, идёт во вторую колонку — иначе второй абзац
   «Материалов и ухода» уезжает под заголовок, в левую */
.block > :not(h3) { grid-column: 2; }

.block h3 { font-size: 32px; margin-bottom: 14px; }
.block p { margin: 0 0 14px; max-width: 60ch; }
.block p:last-child { margin-bottom: 0; }

/* Позиции, снятые не на белом, а в комнате: вырезать нечего, оптический вес
   к ним неприменим — считать «сколько занимает предмет» не по чему. Кадр
   занимает площадку по высоте целиком, полей нет.
   Растягивать его на всю ширину нельзя: у всех четырёх кадр мелкий
   (380×209 у TRAVERT), и на 720 точках он поплывёт. */
.product__ph--photo { padding: 0; }

.product__ph--photo img {
  max-width: 100%;
  max-height: 100%;
  height: 100%;
  object-fit: contain;
}

/* «Похожие предметы» внизу страницы вещи — 46 (утв. 15.08.2026). Правило
   именное, а не общее для всех шапок: заголовок блока предметов на главной
   стоит на своих 74 (контракт 5ж), «Посмотрите предметы» в проектах — на 42. */
.section--similar .h-section { font-size: clamp(28px, 3.4vw, 46px); }

/* пометка-заглушка: честно говорим, что данных пока нет */
.stub {
  border-left: 2px solid var(--bronze);
  padding: 14px 0 14px 18px;
  color: var(--muted);
  font-size: 16px;
  background: transparent;
  max-width: 60ch;
}

/* ---------- контентные страницы ---------- */

.prose { max-width: 60ch; }
.prose h2 { font-size: clamp(28px, 3.4vw, 42px); margin: 46px 0 14px; }
.prose h2:first-child { margin-top: 0; }
.prose p { margin: 0 0 16px; }
.prose ul { margin: 0 0 18px; padding-left: 20px; }
.prose li { margin-bottom: 8px; }

/* ---------- правовые страницы: лист документа ----------

   Политика и условия использования 3D-моделей — не статьи. Их открывают
   в том числе юрист заказчика и проверяющий, и с первого экрана должно быть
   видно, что это бумага, а не пост. Первая версия была набрана обычной
   колонкой текста, и Стас поймал это сразу: «выглядит как чат в мессенджере».

   Признаки документа собраны вместе, по одному они не работают:
   лист с полями поверх бежевой страницы · реквизитная шапка · содержание
   сбоку · номер и линия у каждого раздела · подпись внизу листа.

   Типографика не своя, а сайта. Заголовок раздела опущен с 42px до 30:
   двенадцать заголовков подряд крупной антиквой и читались как лента. */

/* Ширина листа задана числом, а не долей окна: строка внутри держится
   62ch, и если пустить лист во всю колонку 1280, справа остаётся мёртвое
   поле в четверть листа. 820 — ширина, при которой линии разделов кончаются
   почти там же, где строка текста, и лист читается собранным. */
.doc-wrap {
  display: grid;
  grid-template-columns: 210px minmax(0, 820px);
  justify-content: center;
  gap: clamp(32px, 3.4vw, 52px);
  align-items: start;
  /* Боковые поля берутся у .shell и обязаны здесь повториться: этот блок
     идёт в CSS ниже, и сокращённая запись padding обнуляла их. На широком
     окне это незаметно (лист и так центрируется), а на телефоне лист
     упирался рамкой прямо в края экрана. */
  padding: 10px var(--gut) clamp(70px, 9vw, 120px);
}

/* Содержание. Липкое, отступ сверху = высота шапки (223px на широком окне)
   плюс воздух: иначе первый пункт уезжает под шапку при прокрутке. */
.doc-toc { position: sticky; top: 248px; padding-top: 6px; }
.doc-toc ol { list-style: none; margin: 14px 0 0; padding: 0; display: grid; gap: 11px; }

.doc-toc a {
  display: grid;
  grid-template-columns: 22px minmax(0, 1fr);
  font-size: 15px;
  line-height: 1.34;
  color: var(--muted);
  transition: color .2s;
}

.doc-toc a:hover { color: var(--ink); }
.doc-toc__n { color: var(--bronze-dim); font-variant-numeric: tabular-nums; }

/* Сам лист */
.doc {
  background: var(--card);
  border: 1px solid var(--line);
  padding: clamp(32px, 4vw, 60px) clamp(24px, 4.4vw, 68px) clamp(38px, 4.6vw, 68px);
}

.doc__title { margin-top: 12px; }

.doc__lead {
  margin: 20px 0 0;
  font-weight: 300;
  font-size: 21px;
  line-height: 1.6;
  color: var(--read);
  max-width: 54ch;
}

/* Реквизиты бланком: подпись капсом, значение крупнее и цветом чернил */
.doc__req {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 18px 26px;
  margin-top: 32px;
  padding-top: 24px;
  border-top: 1px solid var(--line);
}

.req { display: grid; gap: 6px; }

.req__k {
  font-size: 12px;
  font-weight: 500;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--muted);
}

.req__v { font-size: 17px; line-height: 1.35; color: var(--ink); font-variant-numeric: tabular-nums; }

/* Раздел: номер висит в своей колонке слева, над разделом волосяная линия */
/* scroll-margin-top обязателен: шапка липкая и высотой 223 точки. Без него
   переход по содержанию ставит раздел ровно под шапку, и человек попадает
   на середину текста, не видя заголовка. */
.doc__sec {
  display: grid;
  grid-template-columns: 46px minmax(0, 1fr);
  margin-top: 34px;
  padding-top: 30px;
  border-top: 1px solid var(--line);
  scroll-margin-top: 250px;
}

/* Номер сидит на базовой линии заголовка, а не по верху блока: заголовок
   30px с интерлиньяжем 1.22, базовая линия первой строки идёт на 27-й точке,
   отсюда и отступ. Кегль 15 — мельче номер рядом с антиквой 30 пропадает. */
.doc__num {
  font-size: 16px;
  letter-spacing: .1em;
  line-height: 1;
  padding-top: 16px;
  color: var(--bronze);
  font-variant-numeric: tabular-nums;
}

.doc__h {
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(26px, 2.3vw, 30px);
  line-height: 1.22;
  letter-spacing: 0;
  color: var(--ink);
}

.doc__body > * { margin: 0; max-width: 62ch; }
.doc__body > * + * { margin-top: 14px; }
.doc__body h2 + * { margin-top: 16px; }
.doc__body strong { font-weight: 500; color: var(--ink); }
.doc__body a { border-bottom: 1px solid var(--line); }
.doc__body a:hover { border-color: var(--bronze); }

/* Маркер списка — короткое бронзовое тире вместо точки: в документе
   точка-пуля выглядит как презентация, тире — как перечень условий. */
.doc__body ul { list-style: none; padding: 0; display: grid; gap: 10px; }
.doc__body li { position: relative; padding-left: 26px; }

.doc__body li::before {
  content: '';
  position: absolute;
  left: 0;
  top: .78em;
  width: 14px;
  height: 1px;
  background: var(--bronze-dim);
}

/* Подпись листа */
.doc__foot {
  margin-top: 40px;
  padding-top: 24px;
  border-top: 1px solid var(--line);
  display: flex;
  flex-wrap: wrap;
  gap: 10px 28px;
  justify-content: space-between;
  font-size: 15px;
  color: var(--muted);
}

/* На узком экране липкое содержание бесполезно, а списком над документом
   оно лезет вперёд названия. Убираем совсем: документность там держат
   лист, реквизитная шапка, номера и линии. */
@media (max-width: 1120px) {
  .doc-wrap { grid-template-columns: minmax(0, 820px); }
  .doc-toc { display: none; }
}

@media (max-width: 760px) {
  .doc__req { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .doc__sec { grid-template-columns: minmax(0, 1fr); }
  .doc__num { padding-top: 0; margin-bottom: 8px; }
}

/* Печать: документ должны уметь распечатать и приложить к договору.
   Со страницы уходит всё, что к бумаге отношения не имеет. */
@media print {
  /* .header-space — распорка под шапкой: шапки на печати нет, пустого места
     под неё тоже быть не должно, иначе первый лист начинается с дыры */
  .header, .header-space, .footer, .crumbs, .doc-toc, .modal { display: none !important; }
  body { background: #fff; color: #000; font-size: 11.5pt; }
  .doc-wrap { display: block; padding: 0; }
  .doc { border: 0; padding: 0; background: #fff; }
  .doc__h { break-after: avoid; }
  .doc__sec { break-inside: auto; }
}

.cols {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
}

.cols > div { background: var(--card); padding: 28px 24px; }
.cols h3 { font-size: 26px; margin-bottom: 10px; }
.cols p { margin: 0; font-size: 16px; color: var(--muted); }

/* шаги «как работаем» */
.steps { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1px; background: var(--line); border: 1px solid var(--line); }
.steps > div { background: var(--paper); padding: 26px 22px 30px; }
.steps .meta { display: block; margin-bottom: 12px; color: var(--bronze); }
.steps h3 { font-size: 26px; margin-bottom: 8px; }
.steps p { margin: 0; font-size: 16px; color: var(--muted); }

.section--dark .steps { background: #33301f; border-color: #33302a; }
.section--dark .steps > div { background: var(--dark); }
.section--dark .steps p { color: #a49b8c; }
.section--dark .steps h3 { color: #fdfbf7; }

/* ---------- формы ---------- */

.form { display: grid; gap: 14px; max-width: 440px; }

.field { display: grid; gap: 7px; }

.field label { font-size: 14px; letter-spacing: .04em; color: var(--muted); }

.field input, .field textarea {
  font: inherit;
  font-size: 17px;
  padding: 13px 15px;
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--ink);
  border-radius: 0;
}

.field input:focus, .field textarea:focus { outline: none; border-color: var(--bronze); }

.check {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  font-size: 14px;
  color: var(--muted);
  line-height: 1.5;
}

.check input { margin-top: 3px; accent-color: var(--bronze); }

/* Ссылка на политику внутри галочки. Подчёркивание тонкой линией — как у всех
   текстовых ссылок сайта. Клик по ней галочку не трогает: браузер не передаёт
   нажатие с ссылки на поле, даже если она лежит внутри <label>. */
.check a, .form__note a { color: inherit; border-bottom: 1px solid var(--line); }
.check a:hover, .form__note a:hover { color: var(--ink); border-color: var(--bronze); }

.form__ok {
  border: 1px solid var(--stock);
  color: var(--stock);
  padding: 14px 16px;
  font-size: 16px;
}

/* Заявка не дошла. Цвет глиняный, а не зелёный: зелёный на сайте значит
   «всё хорошо», и сообщением о беде им красить нельзя. Форма при этом
   ОСТАЁТСЯ на месте — человек должен видеть, что его слова не пропали
   и кнопку можно нажать ещё раз. */
.form__ok--беда {
  border-color: #9a4127;
  color: #9a4127;
}

/* ---------- страница «Дизайнерам»: две кнопки ----------
   Вся страница — два входа: кабинет партнёра и библиотека 3D-моделей.
   Заявка живёт под ними и раскрывается по нажатию.

   ⛔ ЧТО СТОИТ В КНОПКЕ И ПОЧЕМУ (разобрано 9.09.2026 по слову Стаса:
   «разберись, что где должно быть в кнопке, смотри как человек, который
   заходит и думает, куда нажать»). До этого разбора я дважды делал вид
   вместо смысла — сперва подменил кнопки картинками, потом навесил на них
   штрихи и приподнимание. Оба раза заворот.

   На страницу приходят трое, и кнопка обязана ответить каждому:
     1. партнёр, у которого доступ уже есть, — ему нужен ВХОД и больше ничего;
     2. дизайнер, который слышит о нас впервые, — ему нужно понять, ЧТО он
        получит внутри, иначе он не нажмёт; для него «Получить доступ»;
     3. дизайнер, пришедший за моделями, — ему нужен КАТАЛОГ.

   Отсюда состав кнопки, сверху вниз, ровно по порядку чтения:
     • имя — куда я попаду;
     • одна строка — что там внутри;
     • действия — главное первым, второе рядом и без стрелки.

   ⭐ ГЛАВНОЕ РЕШЕНИЕ: кнопки РАЗНЫЕ ПО ВЕСУ. Две одинаковые белые плитки
   не отвечают на вопрос «куда нажать» — глазу не за что зацепиться.
   Кабинет — закрытая дверь и главная цель страницы, поэтому он тёмный
   (цвет подвала и страницы «Бренд»). Библиотека моделей открыта всем,
   она светлая. Разница видна с одного взгляда, без единой картинки.

   Контраст надписей померен ДО постановки: на тёмном имя 14,2 : 1,
   строка 7,7 : 1, действие 6,0 : 1 — все выше книжного порога 4,5. */

/* Страница короткая — без нижнего воздуха кнопки упираются прямо в подвал. */
.dsn { padding-bottom: clamp(70px, 9vw, 130px); }

.gates {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 26px;
  margin: 34px 0 0;
}

.gate {
  display: flex;
  flex-direction: column;
  padding: clamp(30px, 2.8vw, 40px) clamp(26px, 2.5vw, 36px) clamp(26px, 2.4vw, 34px);
  background: var(--card);
  border: 1px solid var(--line);
  text-align: left;
  transition: border-color .3s, background-color .3s;
}
/* Реакция на наведение самая скупая: человеку надо понять, что это
   нажимается, и только. Ни подъёма, ни тени, ни растущих линий —
   всё это Стас завернул 9.09.2026 словами «не гонись за анимацией». */
.gate:hover { border-color: var(--bronze); }

/* Тёмная — главная. */
.gate--dark {
  background: var(--dark);
  border-color: var(--dark);
}
.gate--dark:hover { background: #26221b; border-color: #26221b; }
.gate--dark .gate__t { color: #f0e9de; }
.gate--dark .gate__n { color: #b6ac9c; }
.gate--dark .gate__go { color: var(--bronze-dim); }

/* Верх кнопки: имя и строка «что внутри». */
.gate__body { flex: 1 1 auto; }

.gate__t {
  display: block;
  font-family: var(--display);
  font-weight: 300;
  font-size: clamp(28px, 2.9vw, 38px);
  line-height: 1.1;
  color: var(--ink);
}

.gate__t--none { display: block; min-height: calc(clamp(28px, 2.9vw, 38px) * 1.1); }        /* пустое место вместо имени кабинета:
   слово «Партнёрам» уже стоит заголовком страницы, второй раз его не пишем (24.08.2026) */

.gate__n {
  display: block;
  margin-top: 12px;
  font-size: 16px;
  line-height: 1.55;
  color: var(--muted);
  max-width: 42ch;
}

/* Действия внизу кнопки: глаз читает сверху вниз и заканчивает здесь.
   Отступ большой — между «что это» и «что я нажму» должна быть пауза. */
.gate__acts {
  display: flex;
  align-items: center;
  gap: 22px;
  flex-wrap: wrap;
  margin-top: clamp(26px, 2.6vw, 36px);
}

/* ⛔ ГЛАВНОЕ ДЕЙСТВИЕ — ОБВЕДЁННАЯ КНОПКА, ВТОРОЕ — ПРОСТО СЛОВО
   (9.09.2026, слово Стаса: «чтобы нормально выглядело войти и получить
   доступ и чтобы каши визуальной не было»).

   Каша была из-за того, что оба действия набирались одинаково: один цвет,
   один кегль, одна разрядка, и отличались только стрелкой. Человек видел
   два равных ряда капса и не понимал, что из этого главное.

   Теперь разница видна до чтения: «Войти» и «Открыть каталог» стоят
   в рамке — это кнопка; «Получить доступ» набрано тише и без рамки —
   это запасной путь для того, у кого доступа ещё нет.

   Стрелки у обрамлённого действия нет намеренно: рамка и так говорит
   «нажми», стрелка рядом с ней — второй знак о том же. */
.gate__go {
  display: inline-block;
  padding: 14px 26px;
  border: 1px solid currentColor;
  font-size: 12px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--bronze);
  transition: background-color .3s, color .3s, border-color .3s;
}
.gate__go:hover { background: var(--bronze); color: #fff; border-color: var(--bronze); }

.gate--dark .gate__go { color: #e8e0d3; border-color: rgba(232, 224, 211, .4); }
.gate--dark .gate__go:hover { background: #e8e0d3; color: var(--dark); border-color: #e8e0d3; }

/* Второе действие в кнопке кабинета: «Получить доступ» — новым,
   у кого входа ещё нет (Стас, 24.08.2026). Набрано тише главного
   и без рамки, но не серым: серое читается как выключённая кнопка.

   ⛔ У НЕГО СВОЙ КЛАСС, А НЕ КЛАСС КНОПКИ С ДОБАВКОЙ (9.09.2026).
   Пока он назывался «кнопка + второе», на него садились ВСЕ правила
   кнопки, и дважды подряд вылезала дичь: сперва светлая черта по низу
   без всякого наведения, потом заливка бронзовым прямоугольником при
   наведении — слово тонуло в плашке. Слово Стаса: «это что за трешак,
   когда навожу мышку». Лечение не заплаткой, а разводом: элемент ведёт
   себя иначе, значит и класс у него свой. */
.gate__link {
  display: inline-block;
  background: none;
  border: 0;
  border-bottom: 1px solid transparent;
  padding: 4px 0;
  font: inherit;
  font-size: 11.5px;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--bronze);
  cursor: pointer;
  transition: border-color .3s, color .3s;
}
.gate--dark .gate__link { color: var(--bronze-dim); }
.gate__link:hover { border-bottom-color: currentColor; }
.gate--dark .gate__link:hover { color: #e8e0d3; }

.apply { max-width: 440px; margin: 30px 0 0; }

@media (max-width: 760px) {
  .gates { grid-template-columns: minmax(0, 1fr); gap: 18px; }
}

/* Согласие на обработку данных — строкой под кнопкой, а не галочкой.
   Так же законно, но человеку на одно действие меньше. */
.form__note {
  margin: -2px 0 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--muted);
}

.cta-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 420px);
  gap: clamp(28px, 4vw, 56px);
  align-items: start;
}

/* Правила модального окна убраны 11.08.2026: само окно снято вместе с кнопкой
   «Запросить стоимость», и рисовать стало нечего. */

/* ---------- мой список ---------- */

.listrow {
  display: grid;
  grid-template-columns: 120px minmax(0, 1fr) auto;
  gap: 22px;
  align-items: center;
  padding: 18px 0;
  border-bottom: 1px solid var(--line);
}

.listrow__ph {
  background: var(--card);
  border: 1px solid var(--line);
  height: 96px;
  display: grid;
  place-items: center;
  padding: 8px;
}

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

.listrow h3 { font-size: 26px; letter-spacing: .04em; margin-bottom: 4px; }

/* Выбранное исполнение в избранном. Стоит отдельной строкой и бронзой: это
   не характеристика предмета, а решение человека, и в заявке менеджеру оно
   уходит вместе с именем вещи. */
.listrow__fin { margin-top: 5px; font-size: 13.5px; color: var(--bronze); }

.remove {
  background: none;
  border: 0;
  color: var(--muted);
  font-size: 14px;
  border-bottom: 1px solid var(--line);
  padding: 2px 0;
}

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

/* ---------- футер ---------- */

.footer {
  background: var(--dark);
  color: #b7ae9f;
  padding: clamp(48px, 6vw, 72px) 0 34px;
  font-size: 16px;
}

.footer a:hover { color: #fdfbf7; }

.footer__grid {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr 1.2fr;
  gap: 34px;
  padding-bottom: 40px;
  border-bottom: 1px solid #33302a;
}

/* В подвале фон тёмный, поэтому знак берётся светлой версией
   (assets/logo-light.svg): чёрная линия на тёмном просто не видна.
   Файл режется из вектора при сборке, красить фильтром больше не нужно. */
.footer__logo {
  display: block;
  width: 132px;
  margin-bottom: 18px;
}

.footer__logo .logo__img { width: 100%; }

.footer h4 {
  font-family: var(--text);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: #6f665a;
  margin: 0 0 16px;
}

.footer ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }

.footer__bottom {
  padding-top: 26px;
  display: flex;
  flex-wrap: wrap;
  gap: 16px 32px;
  justify-content: space-between;
  font-size: 14px;
  color: #6f665a;
}

/* Правовые ссылки в нижней строке подвала. Своя флекс-строка, чтобы на узком
   экране они переносились вместе и не разъезжались по одной. */
.footer__legal { display: flex; flex-wrap: wrap; gap: 8px 22px; }
.footer__legal a { border-bottom: 1px solid #4a453c; }

/* ---------- адаптив ---------- */

/* ==========================================================================
   ЗАГРУЗКА ГЛАВНОЙ — ЗНАК САДИТСЯ НА МЕСТО
   Утв. Стасом 27.07.2026, числа подобраны им лично ползунками.
   Эталон — 7-Сайт/превью-анимации.html, лист 1. Менять числа без него нельзя.

   Что происходит: экран бежевый и пустой, знак стоит крупным по центру.
   Постояв один, он уменьшается и едет вверх — ровно на своё место в шапке.
   Пока едет, под ним проступает фотография. Последними приходят телефон,
   меню и «Мой список», одной волной.

   ГЛАВНОЕ ПРАВИЛО, нарушение которого уже стоило Стасу испорченного просмотра:
   в покое всё показано полностью. Спрятанное состояние живёт ТОЛЬКО внутри
   первого кадра анимации. Прятать отдельным правилом opacity: 0 и показывать
   скриптом нельзя — при осечке скрипта человек видит застывший сломанный экран
   вместо страницы. Здесь скрипт всего один и он в <head>: ставит класс boot
   до первой отрисовки. Не выполнился — просто нет анимации, страница обычная.

   Всё заскоплено на .header--home и .hero--over: шаблон head() в build.py
   один на все 64 страницы, без этого шапка спряталась бы на каталоге и
   карточках предметов.
   ========================================================================== */

@keyframes boot-logo {
  from { transform: translateY(var(--boot-lift)) scale(3.1); }
  to   { transform: none; }
}

@keyframes boot-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* Насколько опустить знак, чтобы он встал ровно посреди экрана.
   Считается формулой, а не скриптом: скрипт в <head> работает до того, как
   появился <body>, померить ему ещё нечего. Половина высоты знака — это
   --logo-w × 0.373: пропорции вектора 539 × 402, отсюда 402/539/2.
   Пауза «знак стоит один» — это задержка анимации: fill-mode both держит
   первый кадр всё время задержки, отдельный кадр для этого не нужен. */
.boot .header--home .logo {
  --boot-lift: calc(50svh - var(--header-pad) - var(--logo-w) * .373);
  animation: boot-logo 1400ms cubic-bezier(.32, .04, .18, 1) 920ms both;
}

/* Створки первого экрана проступают ПОСЛЕ заставки со знаком. Ритм внутри
   экрана взят из эталона один в один: материал, через 640 мс имя, через 1060
   линия, через 1260 подпись; правая створка отстаёт от левой на 140–170 мс.
   Вся связка сдвинута на --boot-shift — столько знак стоит по центру и едет
   в шапку. В эталоне заставки со знаком нет, поэтому там сдвиг равен нулю;
   меняем ОДНО число, а не пересобираем задержки заново.

   fill-mode backwards, а не both: both удерживал бы конечный transform после
   конца анимации и наведение на створку перестало бы наезжать материалом. */
.boot .hero { --boot-shift: 1080ms; }

.boot .stvor__mat img {
  animation: mat-in 1600ms cubic-bezier(.22, .61, .36, 1) var(--boot-shift) backwards;
}
.boot .stvor--r .stvor__mat img { animation-delay: calc(var(--boot-shift) + 170ms); }

.boot .stvor__name {
  animation: text-in 1100ms cubic-bezier(.22, .61, .36, 1) calc(var(--boot-shift) + 640ms) backwards;
}
.boot .stvor--r .stvor__name { animation-delay: calc(var(--boot-shift) + 800ms); }

.boot .stvor__rule {
  animation: text-in 900ms ease calc(var(--boot-shift) + 1060ms) backwards;
}
.boot .stvor--r .stvor__rule { animation-delay: calc(var(--boot-shift) + 1200ms); }

.boot .stvor__go {
  animation: text-in 900ms ease calc(var(--boot-shift) + 1260ms) backwards;
}
.boot .stvor--r .stvor__go { animation-delay: calc(var(--boot-shift) + 1400ms); }

@keyframes mat-in {
  from { opacity: 0; transform: scale(1.06); }
  to   { opacity: 1; transform: scale(1); }
}

@keyframes text-in {
  from { opacity: 0; transform: translateY(34px); }
  to   { opacity: 1; transform: none; }
}

/* 1690 мс = 920 задержки + 55 % пути знака. Приходят одной волной,
   без каскада по пунктам меню: одно движение — один план. */
.boot .header--home .header__tel,
.boot .header--home .header__side,
.boot .header--home .nav,
.boot .header--home .burger {
  animation: boot-fade 700ms ease 1690ms both;
}

/* Дым анимацией НЕ трогаем. У него своя жизнь: он гаснет, когда кадр уходит
   из-под шапки (класс is-over-photo). Повесь сюда анимацию с fill both —
   она перебила бы это переключение и дым остался бы гореть навсегда.
   На бежевом фоне в первые секунды его всё равно не видно: он сам бежевый. */

/* Средний экран: «смотреть →» уходит, карточки остаются по пять.
   Появилось 29.07.2026 вместе с пятой карточкой — до того карточек было три
   и всё влезало до самого телефона.

   Считаем на ноутбуке 1200: пятая доля это (1200 − поля 58 − зазоры 67) / 5 =
   215 px. Слово «Кровати» кеглем 34 просит ~105 px, «смотреть →» ещё ~94, плюс
   зазор 18 — итого 217. Не помещается на два пикселя, и подпись переносится
   под кадр в тот самый момент, когда на карточку наводят мышь.
   Само слово при этом влезает с большим запасом, поэтому убираем приписку,
   а не ломаем ряд. Ниже 1080 ряд всё же перестраивается — там дело уже не
   в подписи, а в пропорции: карточка становится уже 1:2 и превращается
   в полосу. */
@media (max-width: 1280px) {
  .cat__go { display: none; }
}

/* От 1080 и ниже карточки идут по три в ряд (3 + 2) — ширина возвращается
   к трети экрана, как было при трёх карточках. Гармошка при этом жива:
   flex-grow работает внутри своей строки. Тот же порог, на котором
   перестраиваются остальные сетки сайта — см. следующий блок. */
@media (max-width: 1080px) {
  .cats { flex-wrap: wrap; }
  .cat { flex: 1 1 30%; }
}

@media (max-width: 1080px) {
  .grid, .grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* Короткий ряд «Похожих» на двух колонках: одна карточка — половина ширины,
     две и три занимают ряд целиком. */
  .grid--n1 { grid-template-columns: minmax(0, 1fr); width: 50%; }
  .grid--n2, .grid--n3 { grid-template-columns: repeat(2, minmax(0, 1fr)); width: 100%; }
  /* Колонку задаём заново: правило .grid с двумя колонками стоит в этом же
     блоке ниже по файлу и при равной силе перебивает базовое .grid--vit1. */
  .grid--vit1 { grid-template-columns: minmax(0, 1fr); width: 50%; }
  .grid--vit2 { grid-template-columns: repeat(2, minmax(0, 1fr)); width: 100%; }
  /* Фактуры встают по две. В столбик их не ставим даже на телефоне: это
     абстрактные куски поверхности, во всю ширину экрана они превращаются
     в длинную ленту непонятно чего.
     Между рядами воздуха больше, чем между столбцами: снизу у кадра стоит
     подпись, и с общим зазором она липла бы к следующему кадру. */
  .made__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    row-gap: 38px;
  }
  /* Галерея проекта: и четвёрка, и тройка встают по два. По три на планшете
     кадр становится уже 240 точек — предмет в интерьере на такой ширине уже
     не разглядеть, а ради этого раздел и заведён. */
  .proj__row--quartet,
  .proj__row--trio { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .tiles { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  /* Тот же хвост при трёх колонках: пустых ячеек справа две или одна. */
  .tiles > .tile:last-child:nth-child(5n + 1),
  .tiles > .tile:last-child:nth-child(5n + 4) { grid-column: auto; }
  .tiles > .tile:last-child:nth-child(3n + 1) { grid-column: 1 / -1; }
  .tiles > .tile:last-child:nth-child(3n + 2) { grid-column: span 2; }
  .steps, .cols { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .footer__grid { grid-template-columns: 1fr 1fr; }
}

/* ГРАНИЦА ТЕЛЕФОННОЙ РАСКЛАДКИ — ПО ШИРИНЕ ИЛИ ПО ВЫСОТЕ (26.08.2026).

   Было: только `max-width: 900px`. Айфон Pro Max, повёрнутый вбок, даёт
   932 × 430 — это шире 900, и сайт честно считал его компьютером: рисовал
   знак 298 и меню строкой в два ряда. Замер: шапка занимала 334 точки
   из 430 на главной (78 % экрана) и 257 из 430 на остальных страницах.
   Содержимому оставалась полоска в 96 точек.

   Теперь условие двумерное: экран УЖЕ 900 ИЛИ НИЖЕ 500 — раскладка
   телефонная. Обычный айфон в ландшафте (844 × 390) и так попадал под
   первое условие и был здоров: шапка 140 из 390.

   Порог 500 выбран числом, а не на глаз: самый низкий портрет, который мы
   меряем, — 320 × 568, он под правило не попадает; самый высокий ландшафт
   айфона — 430, попадает. Планшет в ландшафте (1024 × 768) остаётся
   компьютером, как и был.

   ⚠️ Это же число живёт ещё в трёх местах, и они обязаны совпадать:
   `narrow()`, закрытие шторки фильтров и закрытие меню в app.js. Разойдутся —
   получим мобильную сетку без порций «Показать ещё» либо наоборот. */

@media (max-width: 900px), (max-height: 500px) {
  /* Телефон уходит, слева встаёт бургер. Знак остаётся по центру,
     «Мой список» — справа: один ряд, ничего не переносится. */
  /* На телефоне знак мельче и поля уже. Замер 28.08.2026: с настольными
     числами повёрнутый Pro Max (932 × 430) отдавал шапке 29 % экрана —
     та же болезнь, что лечили 26.08. Со здешними числами 17 %. */
  .header { --logo-w: 84px; --header-pad: 12px; }
  /* Выключка по нижней линии слова — приём широкого экрана. На телефоне
     вместо слова стоит ромб, у него низа-линии нет, и значок с бургером
     висели ниже его середины. Здесь всё по центру. */
  .header__in { padding: var(--header-pad) var(--gut); align-items: center; }
  .nav, .header__side { padding-bottom: 0; transform: none; }
  .nav { margin-left: 0; }
  .nav a.nav-mob { display: inline-grid; }   /* на телефоне пункт в панели */
  .header__side .nav-r { display: none; }    /* а справа его нет */
  .logo { transform: none; }
  .header-space { height: var(--head-space, 124px); }
  /* МЕНЮ НА ТЕЛЕФОНЕ — ПАНЕЛЬ ВО ВЕСЬ ЭКРАН (14.08.2026).
     До этого меню выпадало полоской под шапкой: пункты по 12 точек высотой,
     половина экрана под ними пустая, и попасть пальцем можно было мимо.
     Теперь панель занимает всё, что ниже шапки, пункты набраны крупно
     антиквой, между ними волосяные линии.

     Панель ниже шапки по z-index: шапка остаётся сверху, и бургер в ней
     работает крестиком — закрыть можно там же, где открыл.
     --nav-top меряет app.js в момент открытия: высота шапки разная на
     главной и внутри, да ещё ужимается при прокрутке. */
  .nav {
    position: fixed;
    inset: var(--nav-top, 84px) 0 0;
    z-index: 55;
    background: var(--paper);
    /* ⛔ Панель во всю ширину — правило широкого экрана «меню в левый угол»
       (justify-self: start, 28.08.2026) сжимало её до ширины слов: шторка
       закрывала левую половину, справа просвечивала страница, пункты стояли
       посередине узкой колонки. Поймал Стас 11.09.2026 на 17 и 13 Pro Max.
       Возвращаем растяжку и пункты во всю строку. */
    justify-self: stretch;
    align-items: stretch;
    /* столбиком: сетка широкого экрана здесь не нужна */
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    gap: 0;
    padding: 10px var(--gut) 32px;
    overflow-y: auto;
    overscroll-behavior: contain;
    /* В покое панель убрана целиком: visibility, а не только прозрачность —
       иначе невидимое меню перехватывало бы тапы по странице. */
    opacity: 0;
    visibility: hidden;
    transform: translateY(-6px);
    transition: opacity .26s ease, transform .26s ease, visibility .26s;
  }
  .is-nav .nav { opacity: 1; visibility: visible; transform: none; }
  /* Страница за панелью не листается: палец должен листать меню, а не каталог
     под ним.
     ⚠️ Замок обязан стоять И на <html>, а не на одном body: прокручивается
     корневой элемент, и запрет на body его не держал — под открытым меню
     страница спокойно уезжала на 400 точек (замер 26.08.2026). Человек
     закрывал меню и оказывался не там, где был. */
  .is-nav, .is-nav body { overflow: hidden; }
  /* Высоту фиксируем тем же движением: без неё Safari на iPhone продолжает
     тянуть страницу по инерции, уже начатой пальцем. */
  .is-nav { height: 100%; }

  /* Пункт: антиква 27, зазоры такие, чтобы высота строки была не меньше 56 —
     это размер, в который палец попадает не целясь. */
  .nav a {
    font-family: var(--display);
    font-size: 27px;
    letter-spacing: .01em;
    /* Текущий раздел в панели отмечает бронза, а не разбег букв: разбег
       широкого экрана (.475em) раздувал «Коллекции» до края панели. */
    --nav-open: .01em;
    padding: 17px 0;
    border-bottom: 1px solid var(--line);
    transition: color .2s;
  }
  .nav a > span { justify-self: start; }
  /* Двойник, который на широком экране держит ширину при наведении, здесь
     не нужен: пункты стоят столбиком и толкать друг друга не могут. */
  .nav__ghost { display: none; }

  /* Номера и мессенджеров в панели нет: снято Стасом 14.08.2026 как
     отсебятина. В меню только пункты меню. */

  .burger { display: block; }
  /* Бургер становится крестиком: три черты сводятся в две накрест.
     Половина хода — 6 точек: черта 1 px и по 5 полей сверху и снизу. */
  .burger span { transition: transform .26s ease, opacity .2s ease; }
  .is-nav .burger span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
  .is-nav .burger span:nth-child(2) { opacity: 0; }
  .is-nav .burger span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

  /* Шапка при открытом меню всегда сплошная. На главной она прозрачная и
     лежит на фотографии — без этого крестик оказался бы на кадре, а панель
     начиналась бы стеклянной полосой. */
  .is-nav .header { --header-bg: var(--paper); background: var(--header-bg); }
  .is-nav .header--over::after { opacity: 0; }
  .header__tel { display: none; }
  /* Значок избранного на телефоне остаётся: он и держит правую сторону. */
  .product { grid-template-columns: minmax(0, 1fr); }

  /* На телефоне колонок нет, и опись, стоящая слева под снимками, оказывалась
     ВЫШЕ имени и цены — первое, что человек видит после фотографий, это была
     таблица размеров. Обёртка левой колонки распускается (display: contents),
     и порядок задаётся вручную: кадры, потом имя с ценой и образцами,
     опись последней. */
  .product__col { display: contents; }
  .product__gal, .product__ph { order: 1; }
  .product > div:last-child { order: 2; }
  .product .specs { order: 3; margin-top: 26px; }
  /* Примечание о съёмке — последним. Без своего порядка оно получало нулевой
     и вставало ПЕРЕД кадрами: человек открывал карточку и первым делом читал
     оговорку про визуализацию, ещё не увидев предмет (поймано 21.08.2026). */
  .product .gal__note { order: 4; margin-top: 14px; }
  /* Колонки нет — площадка занимает всю ширину, и пропорция 1,65 сделала бы
     из неё низкую полосу. Возвращаем 4:3, как в плитке. Долю предмета и
     оптический вес не трогаем: они в процентах и работают на любой ширине. */
  /* ⛔ Потолок высоты площадки на узком экране СНЯТ (26.08.2026), возвращать
     нельзя. Он придуман под широкий экран, где карточка обязана влезать
     в первый экран целиком; на телефоне карточку и так листают. А вреда
     от него было два. Первый: при высоте окна 568 (iPhone SE) он сжимал
     площадку до 251 точки из 320 — фотография съезжала в середину экрана
     с белыми полями по бокам. Второй, тот же самый по корню: площадка
     держит пропорцию и при упоре в потолок сжимается ПО ШИРИНЕ, а ряд
     миниатюр под ней остаётся во всю ширину колонки — правый край ряда
     торчал за край кадра на 17 точек в окне 900 × 1000.
     Прежде это лечили второй формулой на обёртке — потолком ширины с упором
     снизу. Две формулы обязаны были совпасть, и не совпали: обёртку упор
     держал во всю ширину, а площадку потолок высоты продолжал сжимать.
     Теперь правило одно: потолка высоты на узком экране нет, площадка равна
     ширине колонки, ряд миниатюр равен площадке. Замерено в девяти окнах
     от 360 × 640 до 1710 × 1017 — вылет ряда 0 в каждом. */
  .product__ph { position: static; aspect-ratio: 4 / 3; max-height: none; }
  .product__ph--gal { position: relative; }

  /* ⛔ SAFARI НЕ СЧИТАЕТ ВЫСОТУ ОТ aspect-ratio ОПРЕДЕЛЁННОЙ (26.08.2026).
     Поймано на живом айфоне Стасом, воспроизведено замером в самом движке
     Safari (webkit). Болезнь одна на две поломки, которые он увидел.

     Как ломалось. Высоту площадки задаёт aspect-ratio, а крупность предмета
     внутри — проценты (86 % площадки, см. .product__ph img). Chrome такую
     высоту считает готовой и проценты от неё берёт. Safari — нет: для него
     высота ещё «не решена», и процентный max-height он молча пропускает.
     Картинка встаёт натуральным размером и распирает площадку изнутри:
     у EMBER 306 × 666 вместо 263 × 219, площадка вытягивалась с 354 × 266
     до 354 × 708 — почти во весь экран, а под кадром оставалось пустое
     бежевое поле. Мерено на шести карточках: у ALTA 354 × 532, у ALBA
     354 × 389 — то есть болели ВСЕ 224 карточки, а не только те, что
     с каруселью.

     То же самое в клетке миниатюры: у неё тоже aspect-ratio, и картинка
     внутри вырастала до натуральных 880 точек при экране 390. Дальше сетка
     ряда — grid-auto-columns: 1fr — брала эту ширину за минимум клетки
     (голый 1fr это minmax(auto, 1fr), а auto = по содержимому), и ряд
     миниатюр превращался в полосы 880 × 660 каждая. Страницу от этого
     уносило вбок на 4953 точки.

     ⚠️ Атрибуты width/height у миниатюр НИ ПРИ ЧЁМ — замер сделан на живой
     странице, где они стоят, и с лечением ниже клетка встаёт правильной
     52 × 39. Снятие атрибутов лечило вид, а не причину.

     Лечение. Ряду — minmax(0, 1fr) вместо голого 1fr, клетке — нулевой
     минимум (то же правило, что уже записано в CLAUDE.md про кабинет).
     Площадке — вместо aspect-ratio явная высота в долях ширины родителя:
     .product объявлен контейнером, 75cqw = три четверти его ширины, то есть
     ровно те же 4:3. Высота становится определённой — и проценты внутри
     работают в обоих движках.

     Почему именно .product, а не .product__gal: у карточек без карусели
     обёртки .product__gal нет вовсе, и cqw уехал бы считаться от ширины
     экрана — площадка получала 293 вместо 266. .product есть у всех.

     @supports — страховка для старых Safari (cqw только с версии 16):
     не поддержал единицу — остаётся прежний aspect-ratio, то есть хуже,
     чем сейчас, не станет.

     Замер после лечения, движок Safari против Chrome, шесть карточек:
     совпадение до пикселя. EMBER 263 × 219, MOON 276 × 200, COMFY 284 × 204,
     ALBA 191 × 138, ALTA 184 × 188, POUF 224 × 224. Вылет вбок 0 везде,
     в трёх размерах телефона: 320 × 568, 390 × 844, 430 × 932.
     Chrome при этом не тронут: у него «до» и «после» одинаковы. */
  .gal__thumbs { grid-auto-columns: minmax(0, 1fr); }
  .gal__thumb { min-width: 0; min-height: 0; }
  @supports (height: 75cqw) {
    .product { container-type: inline-size; }
    .product__ph { aspect-ratio: auto; height: 75cqw; }
  }
  /* Потолок ширины обёртки здесь не нужен: он существует только затем, чтобы
     повторить сжатие площадки, а сжимать её больше нечему. Снимаем потолок
     широкого экрана, иначе он подрежет обёртку и ряд снова разойдётся с кадром. */
  .product__gal { position: static; max-width: none; }
  /* Стрелки на узком экране. Раньше это были полосы в 14 % ширины во всю
     высоту кадра, прозрачные на .35: с каждого края по 49 точек невидимой
     кнопки поверх фотографии — треть площадки, и тап по самому предмету
     попадал в стрелку. Теперь это две небольшие кнопки у краёв, каждая
     44 × 44 — размер пальца, — со светлой подложкой, чтобы читались на
     любом кадре. Листать при этом можно и просто проведя по фотографии. */
  .gal__arr {
    opacity: 1;
    width: 44px;
    height: 44px;
    top: 50%;
    bottom: auto;
    transform: translateY(-50%);
    border-radius: 50%;
    font-size: 22px;
    background: rgba(250, 248, 244, .82);
    box-shadow: 0 1px 6px rgba(33, 29, 24, .16);
  }
  .gal__arr--l { left: 8px; }
  .gal__arr--r { right: 8px; }

  /* Заголовок блока встаёт над текстом: колонка в 410 точек на такой ширине
     съела бы половину экрана. */
  .block { grid-template-columns: minmax(0, 1fr); }
  .block > :not(h3) { grid-column: auto; }
}

@media (max-width: 640px) {
  :root { --gut: 18px; }
  /* Телефон: кадры проекта в столбик во всю ширину. Пара кадров рядом даёт
     ширину 160 точек — это уже не фотография интерьера, а марка. */
  .proj__row--quartet,
  .proj__row--trio { grid-template-columns: minmax(0, 1fr); }
  .proj { gap: 22px; }
  /* Узкий экран: вместо полного знака остаётся одна монограмма. Надпись
     «Unigue» на такой ширине становится мелкой и нечитаемой, а ромб узнаётся
     в любом размере. Заодно освобождается место в ряду
     бургер + знак + «Мой список». */
  .logo__img--full { display: none; }
  .logo__img--mark { display: block; }
  /* Одна монограмма вместо надписи — шапка ниже втрое, распорка следом */
  .header-space { height: var(--head-space, 124px); }
  /* Здесь вместо надписи стоит монограмма, а она квадратная — половина её
     высоты это половина ширины, а не 0.373 от неё. Иначе знак сел бы мимо
     середины экрана. */
  .boot .header--home .logo {
    --boot-lift: calc(50svh - var(--header-pad) - var(--mark-w) * .5);
  }
  .header__in { column-gap: 10px; }
  /* Подпись «Избранное» уступает место знаку: остаётся сердце со счётчиком —
     тот же значок, что на карточках предметов.
     Зазоры вокруг черты здесь свои: на широком экране между словом и числом
     22 + 19 px, на телефоне столько воздуха съело бы половину свободного места
     в шапке рядом со знаком. */
  .listbtn { padding: 8px 10px; gap: 10px; }
  .listbtn__count { padding-left: 10px; }
  .listbtn__label { display: none; }
  .listbtn__icon { display: block; }
  .burger { padding: 8px 6px; }
  /* ВИТРИНА ПО ДВЕ КАРТОЧКИ В РЯД (14.08.2026). В один столбец каталог был
     длиной в 32 экрана: одна карточка занимала экран целиком. Внутренности
     карточки под половину ширины ужаты ниже, в разделе «телефон».
     .cols и .steps остаются в столбик — это текстовые блоки, им ширина нужна. */
  .grid, .grid--4, .tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .cols, .steps { grid-template-columns: minmax(0, 1fr); }
  /* На телефоне столбик один, короткому ряду сжиматься некуда */
  .grid--n1, .grid--n2, .grid--n3 { grid-template-columns: minmax(0, 1fr); width: 100%; }
  .grid--vit1, .grid--vit2 { grid-template-columns: minmax(0, 1fr); width: 100%; }
  /* РАЗДЕЛЫ — ВСЕ ПЯТЬ В ОДНОМ ЭКРАНЕ (утв. Стасом 14.08.2026, вариант А).
     До этого карточки шли в столбик во всю ширину: пять разделов — пять
     смахиваний, и человек с телефона не видел, что у нас есть кроме диванов.
     Теперь две в ряд, пятая во всю ширину — весь набор помещается на экран
     целиком, вместе с «Весь каталог →».

     Ряд собран на flex (гармошка с широкого экрана), поэтому доля задаётся
     через flex-basis, а не колонками сетки. calc с половиной зазора: два
     по 50 % плюс зазор между ними в строку не влезают.
     height: auto здесь обязателен: на широком экране высота карточки задана
     числом (clamp), а заданная высота сильнее пропорции — без сброса
     aspect-ratio ниже просто не сработает и кадр останется вытянутым. */
  .cats-wide { padding: 0 var(--gut); }
  .cats { flex-wrap: wrap; gap: 14px; }
  .cat { flex: 0 0 calc(50% - 7px); }
  .cat:last-child { flex-basis: 100%; }
  .cat__ph { height: auto; aspect-ratio: 5 / 4; }
  /* Широкая пятая карточка ниже: при 5:4 во всю ширину она одна съела бы
     треть экрана и набор снова не собрался бы в один вид. */
  .cat:last-child .cat__ph { aspect-ratio: 16 / 9; }
  /* «смотреть →» на телефоне убираем: строка узкая, слово от него съезжает,
     а на карточке во всю ширину и так ясно, что она нажимается. */
  .cat__go { display: none; }
  /* Было 34, когда карточка занимала всю ширину экрана. Теперь она в половину,
     и «Комоды и тумбы» в 34 не помещались в строку. 22 — минимум, ниже
     которого Cormorant опускать нельзя по эталону типографики (26 для
     парадного, но это подпись карточки, а не заголовок). */
  .cat__name { font-size: 22px; letter-spacing: .01em; }
  .cat:last-child .cat__name { font-size: 26px; }
  .cat__rule { margin: 7px 0 9px; }
  /* Высоту первого экрана на телефоне не режем: он везде ровно один экран.
     Створки на узком экране идут друг под другом, по половине экрана каждая —
     правило выше, в разделе первого экрана. */
  .section__head { flex-direction: column; align-items: flex-start; }
  .cta-grid { grid-template-columns: minmax(0, 1fr); }
  .listrow { grid-template-columns: 84px minmax(0, 1fr); }
  .listrow__ph { height: 74px; }
  .listrow .remove { grid-column: 2; justify-self: start; }
  .footer__grid { grid-template-columns: minmax(0, 1fr); }
}

/* ==========================================================================
   ТЕЛЕФОН — ПЛОТНАЯ РАСКЛАДКА
   Заведено 14.08.2026 по разбору со Стасом на iPhone 13 Pro Max.

   Что было: каталог длиной 32 экрана, раздел «Столы» 15, главная 10,
   карточка предмета 7,6. Всё оттого, что раскладка широкого экрана на
   телефоне просто вытягивалась в один столбец: ряд из четырёх карточек
   превращался в четыре экрана, пять разделов — в пять.

   Правило раздела: блок, который на широком экране виден целиком, на
   телефоне тоже должен помещаться в экран, а не разворачиваться в ленту.

   Раздел стоит последним в файле намеренно: правила здесь перебивают
   всё выше при равной силе селектора. Вид широкого экрана — утверждённый
   Стасом эталон, и ни одна строка отсюда до него не дотягивается:
   всё заперто в @media по ширине.
   ========================================================================== */

/* ---------- планшет и телефон: то, что нужно уже с 900 ---------- */

@media (max-width: 900px), (max-height: 500px) {
  /* Первый экран главной перестаёт быть медленным. На широком экране знак
     стоит по центру почти секунду, потом едет в шапку — это подпись бренда.
     На телефоне то же самое читается как «сайт не загрузился»: экран пустой,
     бежевый, посреди него значок. Сокращаем: пауза 250 вместо 920, ход 900
     вместо 1400, фотография проступает на 400-й миллисекунде вместо 1080-й. */
  .boot .header--home .logo { animation-duration: 900ms; animation-delay: 250ms; }
  /* Знак уезжает раньше — значит и створки проступают раньше. Меняем одно
     число: весь ритм внутри экрана сдвинут на него и едет следом. */
  .boot .hero--over { --boot-shift: 400ms; }
  .boot .stvor__mat img { animation-duration: 800ms; }
  /* Бургер в волне «приходят последними» больше не участвует: пока он
     проявлялся, первые полторы секунды тапать было некуда — кнопка есть,
     а нажать нельзя. Меню обязано работать с первого кадра. */
  .boot .header--home .burger { animation: none; }

  /* При открытом меню свечение с бургера и знака снимается: оно было
     нужно на фотографии, а под панелью шапка сплошная бежевая. */
  .is-nav .header--over.is-over-photo .burger span,
  .is-nav .header--over.is-over-photo .logo__img { filter: none; }

  /* Цели под палец: 44 точки — размер, в который попадают не целясь. */
  .listbtn { padding: 12px 15px; }
  .fav { width: 42px; height: 42px; top: 8px; right: 8px; }
  .chip { padding: 11px 16px; }
  .mode { padding: 4px 0 10px; }
}

/* ---------- отбор материала: шторка снизу ----------
   Утв. Стасом 14.08.2026, вариант А. Разметка одна на оба вида (build.py,
   filters_bar): на широком экране .filterbar и .filters__top/__foot скрыты,
   панель стоит в потоке, как стояла. */

.filterbar { display: none; }
.filters__top, .filters__foot { display: none; }

@media (max-width: 900px), (max-height: 500px) {
  /* Строка вместо полутора экранов чипов: кнопка с числом выбранных фильтров.
     Счётчик «Найдено N» снят 20.08.2026 вместе с остальными числами. */
  .filterbar {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 14px 0;
    border-top: 1px solid var(--line);
    border-bottom: 1px solid var(--line);
    margin-bottom: 22px;
  }

  .filterbar__btn {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    border: 1px solid var(--line);
    background: transparent;
    padding: 11px 18px;
    font-family: var(--text);
    font-size: 12.5px;
    font-weight: 500;
    letter-spacing: .18em;
    text-transform: uppercase;
    color: var(--ink);
  }

  /* Число выбранных фильтров. Пока ничего не выбрано, кружка нет вовсе —
     его печатает build.py со скрытым атрибутом, показывает app.js. */
  .filterbar__n {
    min-width: 20px;
    height: 20px;
    display: inline-grid;
    place-items: center;
    background: var(--bronze);
    color: var(--paper);
    border-radius: 50%;
    font-size: 11.5px;
    letter-spacing: 0;
  }


  /* Сама панель. Выезжает снизу — оттуда до неё дотягивается большой палец,
     сверху бы пришлось перехватывать телефон. */
  .filters {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 80;
    max-height: 86vh;
    overflow-y: auto;
    overscroll-behavior: contain;
    background: var(--paper);
    border-top: 1px solid var(--line);
    border-bottom: 0;
    box-shadow: 0 -18px 40px -20px rgba(33, 29, 24, .35);
    padding: 0 var(--gut) 18px;
    margin: 0;
    transform: translateY(101%);
    visibility: hidden;
    transition: transform .3s cubic-bezier(.22, .61, .36, 1), visibility .3s;
  }

  .is-filters .filters { transform: none; visibility: visible; }
  .is-filters body { overflow: hidden; }

  /* Затемнение под шторкой: без него панель висит над каталогом, и непонятно,
     что страница сейчас не листается. Рисуем его на body, а не на самой
     панели: у панели есть transform, а внутри трансформированного элемента
     position: fixed считается от него самого — плёнка легла бы поверх
     фильтров вместо страницы. */
  .is-filters body::after {
    content: '';
    position: fixed;
    inset: 0;
    z-index: 70;
    background: rgba(33, 29, 24, .38);
  }

  /* Шапка шторки липнет к её верху: крестик остаётся на виду, сколько бы
     материалов ни было в списке. */
  .filters__top {
    position: sticky;
    top: 0;
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: space-between;
    background: var(--paper);
    padding: 16px 0 14px;
    border-bottom: 1px solid var(--line);
    margin-bottom: 18px;
  }

  .filters__ttl {
    font-family: var(--text);
    font-size: 12.5px;
    font-weight: 500;
    letter-spacing: .22em;
    text-transform: uppercase;
    color: var(--muted);
  }

  .filters__x {
    border: 0;
    background: none;
    font-size: 28px;
    line-height: 1;
    color: var(--ink);
    /* Крестик закрытия шторки был 34 × 36 — промах по нему оставляет
       человека внутри фильтров. Поля доводят кнопку до 44 × 44, знак
       и его место в ряду прежние. */
    padding: 8px 12px;
    margin-right: -12px;
  }

  /* Внутри шторки чипы стоят своей сеткой: в свободном ряду они ломались
     на кривые строки, где в одном ряду три слова, в другом одно. */
  .filters__row {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 9px;
  }

  .filters__label {
    grid-column: 1 / -1;
    margin: 0 0 2px;
    font-size: 11.5px;
  }

  .filters__row + .filters__row { margin-top: 22px; }
  .filters__spacer { display: none; }
  .chip { padding: 13px 8px; font-size: 14px; text-align: center; }
  /* 16 точек — не вкус, а защита, та же что у полей формы ниже: Safari на
     iPhone сам увеличивает страницу, когда человек встаёт в поле мельче 16,
     и обратно масштаб уже не отдаёт. Тут стояло 15 — и каждый тап по выбору
     сортировки уводил страницу в зум (поймано замером 26.08.2026). */
  .select { grid-column: 1 / -1; padding: 13px 12px; font-size: 16px; }
  /* «Сбросить» — не материал и не коллекция, поэтому стоит отдельной строкой
     во всю ширину, а не четвёртым чипом в ряду коллекций. */
  .chip[data-filter-reset] { grid-column: 1 / -1; }

  .filters__foot {
    display: block;
    position: sticky;
    bottom: 0;
    background: var(--paper);
    padding: 16px 0 6px;
    margin-top: 24px;
    border-top: 1px solid var(--line);
  }

}

/* ---------- витрина порциями ---------- */

/* Карточка, не попавшая в текущую порцию. display с !important — по той же
   причине, что у [hidden]: .card { display: flex } перебил бы обычное
   правило, и «Показать ещё» ничего бы не резало. */
.is-cut { display: none !important; }

.more { margin-top: 22px; }
.more .btn { padding: 16px 22px; }

@media (min-width: 901px) and (min-height: 501px) {
  /* На широком экране порций нет: витрина там утверждена целиком. Кнопка
     скрыта и стилем тоже, не только скриптом. */
  .more { display: none; }
}

/* ---------- телефон ---------- */

@media (max-width: 640px) {
  /* Воздух между блоками. На широком экране 96 точек сверху и снизу — это
     верно для монитора, но на экране 926 точек высотой два таких отступа
     съедают пятую часть экрана. */
  .section { padding: clamp(38px, 9vw, 52px) 0; }
  .section--first { padding-top: clamp(28px, 6vw, 40px); }
  .section__head { margin-bottom: 26px; }
  .pagehead { padding: 10px 0 24px; }
  .pagehead .lead { margin-top: 12px; }

  /* КАРТОЧКА ПРЕДМЕТА В ВИТРИНЕ — под половину ширины экрана.
     Порядок строк и их смысл остаются утверждёнными (название · тип ·
     артикул · цена · наличие), меняются только кегли: в 195 точках ширины
     название в 26 и артикул с коллекцией в разрядку не помещались. */
  .card__ph { padding: 14px 12px 12px; }
  /* подпись плитки на телефоне: та же тройка, кегли по мобильной шкале сайта.
     Значения перенесены из утверждённого превью один в один */
  .lb { padding: 17px 14px 20px; }
  .lb-name { font-size: 25px; }
  .lb-coll { font-size: 15px; margin-top: 4px; }
  .lb-price { font-size: 15.5px; line-height: 20px; padding-top: 18px; }
  .lb-rub { font-size: 13.5px; }
  /* 12 точек, а не 10,5. Замер 26.08.2026: на каталоге в 230 местах текст
     был мельче 12 — с разрядкой .1em это уже не строка, а серая полоска.
     Разрядку заодно ужали: на мелком кегле она разбивает слово сильнее,
     чем помогает. Метка наличия (.stock) сюда же: её 224 штуки на витрине,
     это и была главная часть тех 230 мест. */
  .card__meta .meta { font-size: 12px; letter-spacing: .07em; line-height: 1.5; }
  .mode, .filters__label, .filterbar__n { font-size: 12.5px; }
  .card .price { font-size: 17px; margin-top: 7px; }
  .card .price small { font-size: 12px; }
  .card .stock { font-size: 12px; letter-spacing: .07em; margin-top: 6px; }
  .card__ph img { max-width: calc(84% * var(--k, 1)); max-height: calc(84% * var(--k, 1)); }

  /* «Похожие предметы» — тоже по две, как основная витрина. В один столбец
     блок из четырёх карточек тянулся на четыре экрана в самом низу страницы,
     куда никто не долистывал. */
  .grid--n1 { grid-template-columns: minmax(0, 1fr); width: 50%; }
  .grid--n2, .grid--n3 { grid-template-columns: repeat(2, minmax(0, 1fr)); width: 100%; }
  /* Колонку задаём заново: правило .grid с двумя колонками стоит в этом же
     блоке ниже по файлу и при равной силе перебивает базовое .grid--vit1. */
  .grid--vit1 { grid-template-columns: minmax(0, 1fr); width: 50%; }
  .grid--vit2 { grid-template-columns: repeat(2, minmax(0, 1fr)); width: 100%; }

  /* ПЛИТКИ РАЗДЕЛОВ В КАТАЛОГЕ — все пять в один экран, как разделы на
     главной: две в ряд, пятая во всю ширину. Раньше они шли столбиком по
     одной, и до переключателя «в наличии · под заказ» надо было листать
     два с половиной экрана. */
  .tile { min-height: 0; padding: 16px 14px 18px; gap: 9px; }
  .tile__ph img { max-height: calc(92px * var(--tk, 1)); }
  /* Место под две строки держим всегда: у половины разделов имя в два слова
     («Журнальные столы», «Обеденные стулья»), и без резерва подписи вставали
     на разной высоте — ряд ехал ступеньками. Та же причина, по которой резерв
     стоял у снятой строки .meta. 3.44em = две строки при line-height 1.72. */
  .tile__name { font-size: 19px; min-height: 3.44em; }
  .tile .meta { font-size: 10.5px; letter-spacing: .1em; }
  .tiles > .tile:last-child { grid-column: 1 / -1; }
  .tiles > .tile:last-child .tile__ph img { max-height: 118px; }

  /* Переключатель витрины: три слова в один ряд без переноса. */
  .modes { gap: 18px; margin-bottom: 2px; }
  /* Кегль 12,5, а не 11,5: мельче 12 на телефоне уже не читается.
     Поля 12 сверху и снизу — строка переключателя была 35 точек,
     это меньше подушечки пальца (норма 44). */
  .mode { font-size: 12.5px; letter-spacing: .1em; }

  /* ФАКТУРЫ «КАК ЭТО СДЕЛАНО» — четыре кадра в один экран.
     Пропорция 3:4 на широком экране даёт вертикальный кадр, но на телефоне
     при двух в ряд это 260 точек высоты на кадр, и блок разъезжался на два
     экрана. Квадрат держит фактуру узнаваемой и собирает блок в один вид. */
  .made__ph { aspect-ratio: 1 / 1; }
  .made__grid { row-gap: 24px; gap: 12px; }
  .made__item figcaption { margin-top: 14px; }
  .made__mat { margin-bottom: 9px; padding-bottom: 9px; font-size: 21px; }
  .made__note { min-height: 0; font-size: 17px; }
  .made__sub { font-size: 16px; }
  .section--made .made__head { margin-bottom: 24px; }

  /* Блок «О компании»: три интерьерных кадра в столбик занимали три экрана. */
  .about__ph { height: 56vw; }
  .about__grid { gap: 12px; }

  /* КАРТОЧКА ПРЕДМЕТА (страница вещи) — было 7,6 экрана.
     Снимок занимал экран целиком: 460 точек площадки плюс поля.
     Высоту теперь держит пропорция 4:3 из правила выше, здесь остаются
     только поля — 60 точек десктопа на телефоне съели бы всю площадку. */
  .product__ph { padding: 22px 20px 18px; }
  .product__name { margin: 8px 0 6px; }
  .product__price { margin: 16px 0 4px; }
  /* ⛔ Липкой кнопки здесь БОЛЬШЕ НЕТ, и возвращать её нельзя.
     Было: position: sticky; bottom: 0 — кнопка «Добавить в избранное»
     прилипала к низу экрана, пока человек читает карточку. Замысел был
     разумный (главное действие под рукой), но вышло два вреда:
     1. На телефоне 390 × 844 кнопка при открытии карточки стоит поверх
        ряда образцов исполнений — половина образцов не видна вовсе.
     2. Запрет эталона карточки от 21.08.2026, слово Стаса: «я хочу,
        чтобы статично всё было». Запрет писался про десктоп, но липкость
        на телефоне — та же липкость.
     Кнопка живёт в потоке, как на широком экране. */
  .product__actions { margin: 18px 0 8px; }
  .btn { padding: 16px 22px; }
  .msg-link { padding: 13px 16px; }

  /* Формы: поля под палец, кнопка во всю ширину. */
  .form { max-width: none; }
  .form .btn { width: 100%; }

  /* 16 точек в поле — не вкус, а защита: Safari на iPhone сам увеличивает
     страницу, когда встаёт в поле с текстом мельче 16, и обратно уже не
     отдаёт. Страница после этого «уезжает» вбок. */

  /* Хлебные крошки в одну строку с прокруткой: «Главная / Каталог / Кресла
     и стулья / ALBA» на 428 точках ломались на две строки. */
  .crumbs { padding: 14px 0; font-size: 13px; flex-wrap: nowrap; overflow-x: auto; }
  .crumbs::-webkit-scrollbar { display: none; }
  .crumbs > * { white-space: nowrap; }

  /* Подвал: ссылки крупнее, воздуха меньше. На телефоне подвал занимал
     1104 точки — 23 % высоты всей главной, больше экрана целиком (замер
     26.08.2026). Ссылка под палец должна быть 44 точки, но не 100: рост
     давала не сама ссылка, а зазоры между ними. */
  .footer__grid { gap: 20px; }


  /* Мой список: строка предмета компактнее, кнопка «Убрать» под палец. */
  .listrow { gap: 14px; padding: 14px 0; }
  .listrow h3 { font-size: 20px; }

  /* Коллекция уходит из карточки витрины: в 195 точках ширины строка
     «№ 01 · HT-SF2207 · FASHION METROPOLIS» разворачивалась на три строки и
     весила больше цены. Артикул остаётся, коллекция целиком есть на странице
     предмета и работает фильтром. */
  .card__col { display: none; }

  /* Подводки и длинные тексты. Кегль широкого экрана на 428 точках даёт
     четыре слова в строку: абзац из трёх предложений занимал пол-экрана. */
  .lead { font-size: 17px; line-height: 1.6; }
  .prose { max-width: none; }
  .prose h2 { font-size: 26px; margin: 32px 0 12px; }
  .prose p { font-size: 16.5px; line-height: 1.62; }
  .section__head p { font-size: 15px; }

  /* Характеристики предмета: было 13 точек полей в каждой строке при девяти
     строках — таблица занимала экран целиком. */
  .specs th, .specs td { padding: 9px 0; font-size: 15.5px; }
  .specs th { width: 42%; }
  /* На телефоне метке хватает трети ширины: фиксированные 230 из 354 съедали
     две трети строки, и значение вжималось в правый край в две строки. */
  .product .specs th { width: 120px; padding-right: 14px; font-size: 11px; }

  /* Карточки-колонки: «Доставка и оплата», «Контакты», «Дизайнерам».
     Заголовок в 26 антиквой при ширине экрана даёт две строки на два слова,
     а внутри карточки ещё 28 точек полей — три карточки занимали два экрана. */
  .cols > div { padding: 20px 18px; }
  .cols h3 { font-size: 21px; margin-bottom: 7px; }
  .cols p { font-size: 16px; line-height: 1.55; }
  .steps > div { padding: 20px 18px; }
  .steps h3 { font-size: 20px; }
  /* У двери «Партнёрам» полей нет с 9.09.2026: кадр идёт во всю ширину,
     подпись стоит под ним. Прежняя строка ужимала поля белой коробки,
     а коробки больше нет. */

  /* Правовые документы: лист остаётся листом, но поля и подводка ужимаются.
     Подводка в 21 давала четыре слова в строке и восемь строк на абзац. */
  .doc { padding: 24px 20px 30px; }
  .doc__lead { font-size: 17px; line-height: 1.6; }
  .doc__req { gap: 14px 18px; }
  .doc__body > * { max-width: none; }
  .doc__body { font-size: 16.5px; }
}

/* ==========================================================================
   РАЗМЕРЫ ПОД ПАЛЕЦ — ОДНО МЕСТО НА ВЕСЬ САЙТ (26.08.2026)

   ⛔ ПОЧЕМУ ОТДЕЛЬНЫМ БЛОКОМ, А НЕ ВНУТРИ «ДО 640».

   25–26.08.2026 всё это лежало в @media (max-width: 640px) — «узкий телефон».
   Замер в движке Safari показал, что до ЛАНДШАФТА телефона правила не
   доходят вовсе: повёрнутый айфон даёт 844 или 932 точки ширины, а это
   шире 640. В ландшафте у нас были: бургер 38 × 39, ссылки подвала 24,
   переключатель витрины 37, галочка согласия 12 × 12 и поля форм кеглем
   меньше 16 — то есть Safari при тапе в поле увеличивал страницу и обратно
   масштаб не отдавал.

   Условие здесь такое же, как у телефонной раскладки: экран УЖЕ 900 ИЛИ
   НИЖЕ 500. Портрет как был, ландшафт теперь тоже.

   Правило на будущее: НОВЫЙ РАЗМЕР ПОД ПАЛЕЦ ПИШЕМ ТОЛЬКО СЮДА.
   Разложишь по двум блокам — половина снова потеряется при повороте.
   Норма 44 × 44: это подушечка пальца, а не вкус.
   ========================================================================== */

@media (max-width: 900px), (max-height: 500px) {
  /* Формы: поле 16 точек — защита, а не вкус. Safari на iPhone увеличивает
     страницу, когда встаёт в поле с текстом мельче 16, и обратно масштаб
     уже не отдаёт: страница после этого «уезжает» вбок. */
  .field input, .field textarea { padding: 14px 14px; font-size: 16px; }

  /* Галочка согласия была 13 × 13 в портрете и 12 × 12 в ландшафте — попасть
     в неё пальцем почти нельзя, а без неё заявку не отправить. Сама клетка 22,
     и вся строка с текстом работает как кнопка: тап по словам «Согласен…»
     ставит галочку, потому что текст лежит внутри <label>. */
  .check input { width: 22px; height: 22px; margin-top: 1px; flex: 0 0 22px; }
  .check { gap: 12px; padding: 6px 0; }

  /* Переключатель витрины «в наличии · под заказ · все предметы»: строка была
     35 точек в портрете и 37 в ландшафте. */
  .mode { padding: 12px 0; }

  /* Телефон, почта и мессенджеры на «Контактах» — главное действие страницы.
     Своего класса у этих ссылок нет, берём по адресу: так правило не
     разъедется, если блок переверстают. */
  .cols a[href^="tel"], .cols a[href^="mailto"],
  .cols a[href*="wa.me"], .cols a[href*="t.me"] { display: inline-block; padding: 10px 0; }

  /* Хлебные крошки: строка была 22 точки, поле по 11 даёт ровно 44. */
  .crumbs a { display: inline-block; padding: 11px 0; }
  /* ⛔ Поле под палец получают только ССЫЛКИ, а разделитель «/» и последнее
     слово — нет. Коробки при этом растягиваются в одну высоту, и буквы
     ссылки оказывались на 11 точек ниже соседей: «Главная» проваливалась
     под «/ Коллекции». Выключка по центру ровняет буквы, поля не трогает.
     Померено 29.08.2026: разъезд 11 → 0 на четырёх страницах, 390 и 932. */
  .crumbs { align-items: center; }

  /* Подвал: ссылки под палец. Рост подвалу давали не ссылки, а зазоры между
     ними, поэтому зазор ужат, а поле ссылки увеличено. */
  .footer ul { gap: 2px; }
  .footer ul a { display: block; padding: 11px 0; }

  /* Сердечко на снимке витрины было 34 × 34, значок внутри прежний. */
  .fav { width: 44px; height: 44px; top: 6px; right: 6px; }
  .fav svg { width: 22px; height: 22px; }

  /* Бургер: было 34 × 39 при поле 8, в ландшафте 38 × 39. Поле 12 даёт 46. */
  .burger { padding: 12px; }

  /* Вход партнёра в кабинет: «Войти» было 78 × 22, «Получить доступ» 164 × 22.
     Это единственная дверь партнёра. baseline меняем на center: с полями
     строка по базовой линии разъезжается. */
  .gate__acts { align-items: center; gap: 12px 22px; }
  /* Обрамлённое действие держит свои боковые поля: без них рамка липнет
     к буквам. Высота под палец у обоих остаётся выше 44 — померено
     на телефоне 390 × 844. */
  .gate__acts .gate__go { display: inline-block; padding: 14px 24px; }
  .gate__acts .gate__link { padding: 13px 0; }

  /* «Все предметы →», «Все столы →» и прочие концовки блоков: было 27.

     Подчёркивание переезжает с border-bottom на text-decoration, и это не
     придирка к коду: border-bottom рисуется по краю ПОЛЯ, и от padding линия
     уехала бы на десять точек вниз от букв — вышла бы отдельная черта посреди
     пустоты. text-decoration идёт под буквами и полю безразлично. */
  .link-arrow {
    display: inline-block;
    padding: 11px 0;
    border-bottom: 0;
    text-decoration: underline;
    text-decoration-color: var(--line);
    text-underline-offset: 5px;
  }

  /* Правовые ссылки в подвале: «Обработка персональных данных» 218 × 25 и
     «Условия использования» 236 × 25 — на всех 17 страницах сразу. */
  .footer__legal { gap: 2px 22px; }
  .footer__legal a {
    display: inline-block;
    padding: 10px 0;
    border-bottom: 0;
    text-decoration: underline;
    text-decoration-color: #4a453c;
    text-underline-offset: 4px;
  }

  /* Кабинет партнёра, кнопки шага скидки: на широком экране 34 × 34.
     Ползунок на телефоне даёт около 20 точек на процент — пальцем в нужный
     не попасть, и кнопки становятся основным способом ввода, а не запасным.

     ⚠️ Селектор из ТРЁХ частей, и это не украшение. Весь блок кабинета в этом
     файле стоит НИЖЕ блока «размеры под палец», а специфичность у «.kb .класс»
     и там и там одинаковая — значит побеждает нижнее правило, то есть базовые
     34 точки. Замер 27.08.2026: с двумя частями кнопка так и оставалась 34 × 34
     на всех четырёх размерах телефона. Добавишь сюда новый размер под палец
     для кабинета — пиши его так же, через родителя. */
  .kb .skid .skid__step { width: 44px; height: 44px; flex: 0 0 44px; }
  .kb .skid .skid__range { height: 44px; }
}


/* ==========================================================================
   СТРАНИЦА «БРЕНД» — единственная тёмная страница сайта.
   Утверждена Стасом 22.08.2026 («страницу утверждаю»), перенесена из эталона
   7-Сайт/превью-бренд.html один в один. Свод устройства и чисел — CLAUDE.md,
   раздел «Страница „Бренд" — утверждённый эталон».

   Всё заперто классом .night на <body>: страница перекрашивает шапку, крошки,
   знак и подвал, и это не должно утечь на остальные 213 страниц.

   Жанр: полоса фактуры во всю ширину — тёмное поле с текстом — полоса —
   тёмное поле — полоса с подписью. Фотографий предметов целиком нет: как
   только в кадре читается стул или кресло, страница превращается в «текст
   с картинкой», а этот жанр Стас забраковал четырежды.

   Кадры — только фабричная HD-съёмка (папки 高清图 на копии флешки, 5500–9000
   точек), режет 5-Исходники/фактуры-бренда-hd.py. Кадры московской квартиры
   для макро не годятся: зерна нет, металл вне резкости.
   ========================================================================== */

/* ==========================================================================
   СТРАНИЦА «БРЕНД» — тёмная. Утверждена Стасом 22.08.2026 словами «страницу
   утверждаю», перенесена из эталона 7-Сайт/превью-бренд.html один в один.

   Все правила заперты классом .night на <body>: страница единственная тёмная
   на сайте, и перекраска шапки, подвала и крошек не должна утечь на остальные
   213 страниц. Свод устройства и чисел — CLAUDE.md, раздел «Страница „Бренд"».
   ========================================================================== */

/* ==========================================================================
   ПРЕВЬЮ страницы «Бренд», ПЯТЫЙ заход. Тёмная материальная комната.

   Четыре прошлых захода забракованы, и все четыре были одним жанром:
   текст плюс фотографии на светлом фоне. Менялась только расстановка —
   колонка, развороты, полосы во всю ширину, компактный разворот с коллажем.
   Пятый меняет не расстановку, а жанр.

   Правило страницы: ФОТОГРАФИЙ ПРЕДМЕТОВ ЗДЕСЬ НЕТ. Есть материал —
   поверхность самой страницы. Кожа со швом и бронзой, срез ореха,
   ворс букле: полосы во всю ширину окна, нарезанные из кадров московской
   квартиры в родном масштабе (5-Исходники/нарезать-фактуры-бренда.py).
   Как только в кадре читается целый предмет, страница снова становится
   «текстом с картинкой» — тем, что забраковано.

   Ритм: материал — темнота — материал — темнота — материал. Четыре подряд
   фактуры превратили бы приём в повтор, поэтому текстовые куски идут
   на чистом тёмном поле, а материал между ними работает паузой.

   Тёмное поле выбрано ещё и потому, что подвал сайта уже тёмный: страница
   и подвал сходятся в одно целое, границы между ними нет.
   ========================================================================== */

.night {
  --night: #0d0c0a;
  --night-2: #131110;
  --night-ink: #ece5da;
  --night-mute: #a2988a;
  --night-line: rgba(236,229,218,.13);
  --band: 1200px;
}

body.night { background: var(--night); }

/* ---------- шапка и крошки в темноте ---------- */

.night .header { background: var(--night) !important; border-bottom: 1px solid var(--night-line); box-shadow: none !important; }
.night .header__tel, .night .nav a, .night .header__fav,
/* ⛔ «ПАРТНЁРАМ» после переезда направо лежит ВНЕ .nav — правило .nav a
   его не касалось, и на тёмной странице слово оставалось почти чёрным
   на чёрном. Поймано глазами 29.08.2026 при переносе шапки-полосы. */
.night .header__side .nav-r { color: var(--night-ink) !important; }
/* Счётчик на тёмной странице: бронза по чёрному читается, оставляем её. */
.night .nav a[aria-current="page"] > span:first-child { color: var(--bronze); }
.night .listbtn { border-color: var(--night-line) !important; }
.night .logo__img--full { content: url(logo-light.svg); }
.night .logo__img--mark { filter: invert(1) brightness(1.6); }
.night .crumbs, .night .crumbs a, .night .crumbs span { color: var(--night-mute) !important; }

/* Меню на телефоне в темноте (11.09.2026). Панель была светлой, а пункты
   получали светлый цвет тёмной страницы — «Коллекции» и «Партнёрам» сливались
   с фоном, а три полоски и крестик, тёмные по умолчанию, пропадали на чёрной
   шапке. Поймал Стас. Панель тёмная, как сама страница. */
@media (max-width: 900px), (max-height: 500px) {
  .night .nav { background: var(--night); }
  .night .nav a { border-bottom-color: var(--night-line); }
  .night .burger span { background: var(--night-ink); }
}

.night .nband { max-width: var(--band); margin: 0 auto; padding: 0 28px; }

/* ---------- полоса материала ---------- */

.night .mat {
  position: relative;
  width: 100%;
  overflow: hidden;
  background: var(--night);
}

.night .mat img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Материал приглушён и уведён в темноту: он поверхность, а не снимок.
   Края растворяются, чтобы не было прямоугольной рамки фотографии. */
.night .mat img { filter: brightness(.86) contrast(1.04) saturate(.82); }
.night .mat--pause img { filter: brightness(.80) contrast(1.05) saturate(.80); }

.night .mat::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
}

/* верх и низ каждой полосы уходят в фон страницы — швов между секциями нет */
.night .mat--fade::after {
  background:
    linear-gradient(180deg, var(--night) 0%, rgba(13,12,10,0) 14%, rgba(13,12,10,0) 86%, var(--night) 100%);
}

/* под текстом темнее, чтобы читалось без плашки */
.night .mat--left::after {
  background:
    linear-gradient(90deg, rgba(13,12,10,.90) 0%, rgba(13,12,10,.62) 42%, rgba(13,12,10,.06) 78%),
    linear-gradient(180deg, var(--night) 0%, rgba(13,12,10,0) 20%, rgba(13,12,10,0) 80%, var(--night) 100%);
}

.night .mat--right::after {
  background:
    linear-gradient(270deg, rgba(13,12,10,.985) 0%, rgba(13,12,10,.965) 30%, rgba(13,12,10,.72) 50%, rgba(13,12,10,.10) 84%),
    linear-gradient(180deg, var(--night) 0%, rgba(13,12,10,0) 20%, rgba(13,12,10,0) 80%, var(--night) 100%);
}

.night .mat__in {
  position: relative;
  z-index: 2;
  max-width: var(--band);
  margin: 0 auto;
  padding: 0 28px;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.night .mat--h1 { height: 640px; }
.night .mat--pause { height: 400px; }
.night .mat--h4 { height: 600px; }

/* ---------- вход ---------- */

.night .lead {
  font-family: var(--display);
  font-weight: 300;
  font-size: clamp(28px, 3.4vw, 54px);
  line-height: 1.06;
  letter-spacing: -0.018em;
  color: var(--night-ink);
  margin: 0;
  max-width: 15ch;
}

.night .lead em { font-style: italic; color: #d8c39c; }

/* ---------- тёмное поле с текстом ---------- */

.night .dark { padding: 92px 0; }

.night .dark--tight { padding: 84px 0 96px; }

.night .say {
  font-size: 18px;
  line-height: 1.72;
  color: #d7cfc4;
  margin: 0 0 1.15em;
  max-width: 930px;
}

.night .say:last-child { margin-bottom: 0; }

.night .mark {
  font-family: var(--text);
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--night-mute);
  margin: 0 0 22px;
}

.night .year {
  font-family: var(--text);
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: #9a8663;
  margin: 34px 0 0;
}

/* ---------- принципы ---------- */

/* Принципы больше не таблица «ярлык | фраза»: столбик с линейками читался
   как строки прайса. Слова Ника целы до буквы, добавлены только двоеточие,
   запятые и один союз — текст идёт одной фразой и держит вес крупным кеглем. */
.night .pr__text {
  font-family: var(--display);
  font-weight: 300;
  font-size: clamp(22.5px, 2vw, 27px);
  line-height: 1.42;
  letter-spacing: -0.008em;
  color: var(--night-ink);
  margin: 0;
  max-width: 930px;
}

/* ---------- финал поверх материала ---------- */

.night .fin { max-width: 500px; }

.night .fin .mark { font-size: 14px; letter-spacing: .26em; color: #d9c9a6; margin-bottom: 28px; }

.night .fin p.say { color: #f0e9de; font-size: 20px; line-height: 1.66; max-width: none; }

.night .sign {
  font-family: var(--display);
  font-weight: 300;
  font-style: italic;
  font-size: clamp(26px, 2.6vw, 38px);
  line-height: 1.22;
  letter-spacing: -0.01em;
  color: var(--night-ink);
  margin: 56px 0 0;
}

/* подвал подхватывает ту же темноту, границы между страницей и низом нет */
.night .footer { background: var(--night) !important; padding-top: 0 !important; }
.night .footer .footer__grid { border-top: 1px solid var(--night-line); padding-top: 76px; }

/* ---------- телефон ---------- */

@media (max-width: 900px), (max-height: 500px) {
  .night .mat--h1 { height: 460px; }
  .night .mat--pause { height: 240px; }
  .night .mat--h4 { height: auto; padding: 64px 0; }
  .night .mat--left::after, .night .mat--right::after {
    background: linear-gradient(180deg, rgba(13,12,10,.58) 0%, rgba(13,12,10,.90) 62%, rgba(13,12,10,.94) 100%);
  }
  .night .mat--h1 img { object-position: 68% 50%; }
  .night .dark { padding: 76px 0; }
  .night .dark--tight { padding: 76px 0 96px; }
  .night .fin { max-width: none; }
}




/* ═══ КАБИНЕТ ПАРТНЁРА ═══════════════════════════════════════════════════
   Перенесено из утверждённого макета «превью-кабинет.html» 24.08.2026,
   значения скопированы из эталона один в один.
   Имена классов разведены с сайтом приставкой kb- (kb-card, kb-btn, kb-field,
   kb-eyebrow), а всё остальное заперто классом .kb на <body>.
   ⚠️ Одного замка .kb НЕ ХВАТАЕТ, и на этом уже обожглись 24.08.2026: у сайта
   класс .card это display:flex, у кабинета — обычная карточка. Замок поднимает
   специфичность только там, где свойство переопределено, а незаданные свойства
   сайта продолжают течь внутрь: кнопки в карточках растянулись во всю ширину.
   Поэтому тёзок с сайтом у кабинета быть не должно — только своя приставка.
   Шапка и подвал у кабинета свои, общей навигации внутри нет.
   ═════════════════════════════════════════════════════════════════════ */
body.kb {
  --display:'Cormorant Garamond',Georgia,serif;
  --text:'Spectral',Georgia,serif;
  --paper:#f6f3ee; --card:#fff; --ink:#211d18; --read:#3a352e;
  --muted:#8a8175; --line:#e4ddd1; --bronze:#8a6d3b; --dark:#1e1b15; --stock:#2f7d55;
}
.kb *, .kb *::before, .kb *::after {box-sizing:border-box}
body.kb {margin:0;background:var(--paper);color:var(--read);font-family:var(--text);font-size:17px;line-height:1.65}
.kb img {max-width:100%;display:block}
.kb a {color:inherit;text-decoration:none}
.kb button {font:inherit;color:inherit;cursor:pointer}
.kb .wrap {max-width:1180px;margin:0 auto;padding:0 26px}
.kb /* шапка кабинета — два пункта, .kb больше ничего */
.top {border-bottom:1px solid var(--line);background:var(--paper)}
.kb .top__in {max-width:1180px;margin:0 auto;padding:20px 26px;display:flex;align-items:center;gap:30px}
.kb .top__logo img {height:34px;width:auto}
.kb .top__nav {display:flex;gap:30px;margin-left:16px}
.kb .top__nav a {font-size:15px;letter-spacing:.02em;color:var(--muted);padding:4px 0;border-bottom:1px solid transparent}
.kb .top__nav a.on {color:var(--ink);border-color:var(--bronze)}
.kb .top__nav a.off {opacity:.42}
.kb .top__me {margin-left:auto;display:flex;align-items:center;gap:16px;font-size:15px;color:var(--muted)}
.kb .top__me span {color:var(--read)}
.kb .top__out {font-size:13px;letter-spacing:.06em;text-transform:uppercase}
.kb h1 {font-family:var(--display);font-weight:300;font-size:44px;line-height:1.1;color:var(--ink);margin:44px 0 6px}
.kb h2 {font-family:var(--display);font-weight:300;font-size:30px;color:var(--ink);margin:0 0 14px}
.kb h3 {font-family:var(--text);font-weight:500;font-size:18px;color:var(--ink);margin:0 0 10px}
.kb .sub {color:var(--muted);margin:0 0 34px}
.kb .kb-eyebrow {font-size:12px;letter-spacing:.18em;text-transform:uppercase;color:var(--bronze);margin:0 0 12px}
.kb .crumb {font-size:13.5px;color:var(--muted);margin:34px 0 -22px}
.kb .crumb a {border-bottom:1px solid var(--line)}
.kb .kb-card {background:var(--card);border:1px solid var(--line);padding:26px 28px}
.kb .kb-card+.card {margin-top:14px}
.kb .kb-card--wait {border-left:2px solid var(--bronze)}
.kb .kb-btn {display:inline-block;background:var(--dark);color:#f4efe6;border:0;padding:14px 26px;
     font-size:13px;letter-spacing:.13em;text-transform:uppercase}
.kb .kb-btn--ghost {background:none;color:var(--ink);border:1px solid var(--line)}
.kb .kb-btn--wide {width:100%;text-align:center}
.kb .kb-field {display:grid;gap:7px;margin-bottom:14px}
.kb .kb-field label {font-size:13px;letter-spacing:.05em;color:var(--muted)}
.kb .kb-field input, .kb .kb-field textarea {font:inherit;background:var(--card);border:1px solid var(--line);padding:13px 14px;color:var(--ink);width:100%}
.kb .kb-field textarea {min-height:176px;resize:vertical;line-height:1.5}
.kb .note {font-size:13px;color:var(--muted);line-height:1.5;margin:8px 0 0}
.kb /* вход */
.login {max-width:400px;margin:0 auto;padding:96px 0 120px;text-align:center}
.kb .login img {height:52px;width:auto;margin:0 auto 30px}
.kb .login h1 {font-size:34px;margin:0 0 30px}
.kb .login .field {text-align:left}
.kb /* деньги — полоса-сводка над списком объектов */
.money {display:grid;grid-template-columns:minmax(0,1.45fr) minmax(0,1fr);gap:1px;
       background:var(--line);border:1px solid var(--line);margin-bottom:12px}
.kb .money__main {background:var(--card);padding:30px 34px 28px}
.kb .money__main .k {font-size:13px;letter-spacing:.14em;text-transform:uppercase;color:var(--muted)}
.kb .money__main .v {font-family:var(--display);font-weight:300;font-size:clamp(46px,6.4vw,82px);line-height:.98;color:var(--ink);margin:10px 0 0;letter-spacing:-.01em}
.kb .money__main .n {font-size:17px;color:var(--bronze);margin-top:12px}
.kb .money__side {display:grid;grid-template-rows:1fr 1fr;gap:1px;background:var(--line)}
.kb .money__side>div {background:var(--card);padding:20px 26px;display:flex;align-items:baseline;justify-content:space-between;gap:16px}
.kb .money__side .k {font-size:13px;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
.kb .money__side .v {font-family:var(--display);font-size:30px;line-height:1;color:var(--read)}
.kb .money__act {background:var(--card);border:1px solid var(--line);border-left:2px solid var(--bronze);
            padding:15px 22px;margin:0 0 34px;font-size:15.5px;color:var(--read)}
.kb .money__act a {border-bottom:1px solid var(--bronze);color:var(--ink)}
.kb /* список объектов */
.row {background:var(--card);border:1px solid var(--line);padding:20px 24px;display:grid;
     grid-template-columns:minmax(0,1fr) 165px 165px 210px;gap:20px;align-items:center}
.kb .row+.row {margin-top:10px}
.kb .row__t {font-size:19px;color:var(--ink)}
.kb .row__c {font-size:14px;color:var(--muted);margin-top:3px}
.kb .row__n {font-size:13px;letter-spacing:.05em;text-transform:uppercase;color:var(--muted);margin-bottom:4px}
.kb .row__v {color:var(--ink)}
.kb .row__v b {font-weight:400;font-family:var(--display);font-size:32px;line-height:1}
.kb .row__v--dim {color:var(--muted);font-size:15px}
.kb .tag {display:inline-block;font-size:12px;letter-spacing:.08em;text-transform:uppercase;padding:5px 11px;border:1px solid var(--line);color:var(--muted)}
.kb .tag--go {border-color:var(--bronze);color:var(--bronze)}
.kb .tag--ok {border-color:var(--stock);color:var(--stock)}
.kb table {width:100%;border-collapse:collapse}
.kb th {font-weight:400;font-size:13px;letter-spacing:.05em;text-transform:uppercase;color:var(--muted);text-align:left;padding:0 0 12px;border-bottom:1px solid var(--line)}
.kb td {padding:15px 0;border-bottom:1px solid var(--line);vertical-align:top}
.kb td.r, .kb th.r {text-align:right}
.kb .dim {color:var(--muted);font-size:14px}
.kb .wait {color:var(--bronze);font-size:14px}
.kb .sum {margin-top:26px;border-top:1px solid var(--line);padding-top:20px}
.kb .sum div {display:flex;justify-content:space-between;padding:7px 0}
.kb .sum .big {border-top:1px solid var(--line);margin-top:12px;padding-top:16px;font-size:20px;color:var(--ink)}
.kb .sum .big b {font-weight:400;font-family:var(--display);font-size:30px}
.kb .two {display:grid;grid-template-columns:minmax(0,1.35fr) minmax(0,1fr);gap:18px;align-items:start}
.kb .ok {display:flex;gap:11px;padding:9px 0;border-bottom:1px solid var(--line);font-size:16px}
.kb .ok:last-child {border:0}
.kb .ok i {color:var(--stock);font-style:normal}
.kb .ok span {color:var(--muted);min-width:132px;font-size:14px}
.kb .log div {padding:11px 0;border-bottom:1px solid var(--line);font-size:16px}
.kb .log div:last-child {border:0}
.kb .log time {display:block;font-size:13px;color:var(--muted);margin-bottom:2px}
.kb /* строка с файлами — не карточки, .kb чтобы не спорила с документами */
.files {display:flex;flex-wrap:wrap;gap:26px;align-items:baseline;margin-top:30px;
       border-top:1px solid var(--line);padding-top:22px;font-size:16px}
.kb .files span {color:var(--muted);font-size:14px;letter-spacing:.05em;text-transform:uppercase}
.kb .files a {border-bottom:1px solid var(--line);color:var(--ink)}

/* ==========================================================================
   СКИДКА ЗАКАЗЧИКУ ИЗ ВОЗНАГРАЖДЕНИЯ ПАРТНЁРА (27.08.2026)

   Партнёр торгуется с заказчиком сам и отдаёт часть своей ставки. Деньги
   компании при этом не двигаются ни на рубль: скидка вычитается из его
   вознаграждения, а не из нашей цены.

   Регулятор стоит ВНУТРИ сводки .sum, а не отдельной карточкой: иначе
   строка «Ваше вознаграждение» печаталась бы на странице дважды — в расчёте
   и в блоке скидки, — и человек не знал бы, какая из них настоящая.

   Кнопки шага рядом с ползунком — не украшение: на телефоне 16 положений
   ползунка это 20 точек на шаг, пальцем в нужный процент попасть трудно.
   ========================================================================== */
.kb .sum .skid {display:grid;grid-template-columns:minmax(0,1fr) auto;gap:12px 16px;
     align-items:center;border-top:1px solid var(--line);margin-top:12px;padding-top:16px}
.kb .skid__set {display:flex;align-items:center;gap:12px;grid-column:1;min-width:0}
.kb .skid__step {width:34px;height:34px;flex:0 0 34px;background:none;border:1px solid var(--line);
     color:var(--read);font-size:19px;line-height:1;display:flex;align-items:center;justify-content:center}
.kb .skid__step:hover {border-color:var(--bronze);color:var(--bronze)}
.kb .skid__range {flex:1 1 auto;min-width:90px;max-width:250px;height:34px;margin:0;
     -webkit-appearance:none;appearance:none;background:none}
.kb .skid__range::-webkit-slider-runnable-track {height:2px;background:var(--line)}
.kb .skid__range::-moz-range-track {height:2px;background:var(--line)}
.kb .skid__range::-webkit-slider-thumb {-webkit-appearance:none;appearance:none;width:18px;height:18px;
     border-radius:50%;background:var(--bronze);margin-top:-8px;cursor:pointer}
.kb .skid__range::-moz-range-thumb {width:18px;height:18px;border:0;border-radius:50%;
     background:var(--bronze);cursor:pointer}
.kb .skid__range:focus-visible {outline:2px solid var(--bronze);outline-offset:4px}
.kb .skid__pct {grid-column:2;font-family:var(--display);font-size:26px;line-height:1;
     color:var(--ink);text-align:right;white-space:nowrap;font-variant-numeric:tabular-nums}
.kb .skid__rub {grid-column:2;color:var(--read);text-align:right;white-space:nowrap}
.kb .skid__lab {grid-column:1;font-size:14px;color:var(--muted)}
/* minmax(0, 1fr), а не 1fr. Голый 1fr — это minmax(auto, 1fr): колонка
   имеет право раздуться под содержимое, и на телефоне поле реквизитов
   растягивало карточку до 384 точек при полосе 338 — страница уезжала
   вбок на 20 точек (замер 26.08.2026, «Главная» и «Договор»). На сайте
   этот приём стоит везде, в кабинете его забыли. */
@media (max-width:900px){.kb .row{grid-template-columns:minmax(0,1fr);gap:12px}.kb .money{grid-template-columns:minmax(0,1fr)}.kb .two{grid-template-columns:minmax(0,1fr)}.kb h1{font-size:34px}
/* Поля кабинета — 16 точек, как и на сайте: мельче — и Safari на iPhone
   увеличивает страницу, стоит человеку встать в поле, а обратно масштаб
   не отдаёт. Тут стояло font:inherit, и в поле загрузки договора
   получалось 13,3 (замер 26.08.2026). */
.kb .kb-field input, .kb .kb-field textarea, .kb .field input {font-size:16px}

/* Строка скидки: на широком экране «подпись — ползунок — рубли» в один ряд,
   на телефоне рубли уходят под ползунок. minmax(0,1fr), а не 1fr: иначе
   ползунок с кнопками распирает карточку и страница уезжает вбок. */
.kb .skid__range {max-width:none}

/* Значение переносится ПОД подпись, а не рвётся посреди числа. Пара
   «flex-wrap + margin-left:auto» держит его у правого края — без второго
   перенесённое число встало бы слева и колонка сводки разъехалась. */
.kb .sum div {flex-wrap:wrap}
.kb .sum div > :last-child {margin-left:auto}

/* Деньги в сводке не переносим по строкам: «159 000 ₽» ломалось на «159» и
   «000 ₽» при ширине 390 — число читалось как два разных (замер 27.08.2026).
   Беда не от скидки, она была у любой суммы, просто теперь строк больше. */
.kb .sum div > span:last-child, .kb .sum b {white-space:nowrap}
.kb .sum div {gap:14px}

/* Шапка таблицы объекта: «КОЛ-ВО» налезало на «СТОИМОСТЬ». Лечится не полем,
   а кеглем с разрядкой: слово в капсе не сжимается ниже своей длины, и любое
   добавленное поле только распирало бы таблицу — на «Главной» кабинета мой
   первый заход с padding-right дал лишние 20 точек вылета (замер 27.08.2026).
   Здесь уменьшается сама длина слова. */
.kb th {font-size:11.5px;letter-spacing:.01em}
.kb th.r {padding-left:12px}

}

/* ==========================================================================
   ШАПКА КАБИНЕТА НА УЗКОМ ТЕЛЕФОНЕ (27.08.2026)

   Замер в движке Safari: страница кабинета уезжала вбок на 13 точек при
   ширине 375 (iPhone SE 2 и 8), на 28 при 360 и на 68 при 320. Виновата
   правая часть шапки — «Бак Геворгян · Выйти» шириной 134: вместе со знаком
   и двумя пунктами меню она в одну строку не встаёт. Держалось это на всех
   шести страницах кабинета, к скидке отношения не имеет.

   Граница померена, а не прикинута: до 388 точек не влезает, с 388 влезает.
   Поэтому порог здесь 388, и на 390 (iPhone 12–15) шапка остаётся прежней
   однострочной — лишние 15 точек высоты там ни к чему.
   ========================================================================== */
@media (max-width: 388px) {
  .kb .top__in { flex-wrap: wrap; gap: 6px 18px; padding-left: 18px; padding-right: 18px; }
  .kb .top__nav { margin-left: 0; }
  .kb .top__me { margin-left: auto; }
}

/* Совсем узкий телефон (iPhone SE 1, старый Android): ряд ползунка и сумма
   скидки встают своими строками во всю ширину. Замер 27.08.2026: в две
   колонки при 320 точках ряд вылезал за карточку. */
@media (max-width: 420px) {
  .kb .skid__set, .kb .skid__rub { grid-column: 1 / -1; }
}

/* знак в шапке кабинета: одна картинка, а не пара «полный + монограмма» */
.kb .kb-logo { height: 34px; width: auto; display: block; }
.kb .login .kb-logo { height: 52px; margin: 0 auto 30px; }

/* вход в кабинет: настоящая форма, а не ссылка (24.08.2026)
   Кнопка формы — <button>, и ему шрифт от страницы не достаётся сам:
   без font-family он встал бы системным на фоне антиквы всего кабинета. */
.kb .login form { text-align: left; }
.kb button.kb-btn { font-family: inherit; cursor: pointer; }
/* Служба входа подставляет сюда причину отказа. Пусто — блока нет вовсе. */
.kb .kb-beda { background: #f6ece6; border-left: 2px solid var(--bronze);
     padding: 12px 16px; margin: 0 0 20px; font-size: 15px; text-align: left; }

/* ==========================================================================
   ЛАНДШАФТ ТЕЛЕФОНА — ЭКРАН НИЗКИЙ (26.08.2026)

   Телефонная раскладка включается теперь и по высоте (см. пояснение у
   мобильного блока шапки). Но сама она посчитана под ПОРТРЕТ, где вертикали
   много. В ландшафте два места из неё вылезли за экран, оба замерены:

     · панель меню: пункты по 81 точке, четыре штуки не влезли в 306
       и «Контакты» оказались за краем — до них приходилось листать;
     · площадка фотографии: 876 × 657 при окне 430 — кадр выше экрана
       в полтора раза, предмет целиком не увидеть без прокрутки.

   Здесь обе высоты ужаты, и только они. Ширины не трогаем — иначе вернётся
   баг ряда миниатюр: площадка держит пропорцию, при упоре в потолок ВЫСОТЫ
   она сжимается ПО ШИРИНЕ, а ряд под ней остаётся во всю колонку.
   Поэтому высота задаётся самой площадке (height), а не потолком
   (max-height): ширина остаётся равной колонке, ряд совпадает с кадром.
   ========================================================================== */

@media (max-height: 500px) {
  /* Пункт меню: антиква 21 вместо 27, поля 11 вместо 17 — строка 55 точек.
     Ниже не опускаем: 55 это ещё размер, в который палец попадает не целясь. */
  .nav a { font-size: 21px; padding: 11px 0; }
  .nav { padding-bottom: 16px; }

  /* Кадр не выше 58 % окна: вместе с рядом миниатюр (104) это 353 из 430,
     то есть предмет и его ракурсы видны в одном экране.

     Высота и ширина считаются ОТ ОДНОГО ЧИСЛА --ph-h, и это не украшение.
     Ровно здесь 25.08.2026 разъехался ряд миниатюр: высоту площадки держала
     одна формула, ширину обёртки — вторая, и они не совпали. Пока обе растут
     из одной переменной, разойтись им нечем. 1.333 — та же пропорция 4:3,
     что у площадки на телефоне. */
  .product { --ph-h: 58svh; }
  .product__gal,
  .product .product__ph { max-width: calc(var(--ph-h) * 1.333); margin-inline: auto; }
  @supports (height: 75cqw) {
    .product__ph { height: min(75cqw, var(--ph-h)); }
  }
}


/* ==========================================================================
   «СВЯЗАТЬСЯ С НАМИ» — СВЯЗЬ И ЗАЯВКА СТОЯТ НА ДЕРЕВЕ (утв. 9.09.2026)

   Вторая тёмная страница сайта после «Бренда» и в том же языке: полоса
   материала во всю ширину, текст поверх неё. Слева имя раздела, телефон
   и почта, справа бланк заявки прямо на фактуре — это место Стас нарисовал
   сам поверх снимка.

   Почему так, а не плитками: прежняя страница была тремя белыми
   прямоугольниками в рамке и читалась таблицей, а светлый разворот без
   материала Стас забраковал словами «страница пустая».
   ========================================================================== */

.night .mat--svz { height: 760px; }

/* Вуаль ровная по всей ширине. Боковую (.mat--left) брать нельзя: слева
   текст, справа бланк, и хвост затемнения делал одну половину заметно
   темнее другой — разворот выглядел кривым. */
.night .mat--svz::after {
  background:
    linear-gradient(180deg, var(--night) 0%, rgba(13,12,10,.58) 20%, rgba(13,12,10,.58) 80%, var(--night) 100%);
}

.svz__in {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 470px;
  gap: 80px;
  align-items: center;
  width: 100%;
}

.svz__h1 {
  font-family: var(--display);
  font-weight: 300;
  font-size: clamp(34px, 4vw, 58px);
  line-height: 1.04;
  letter-spacing: -0.018em;
  color: var(--night-ink);
  margin: 0 0 38px;
}

/* ⛔ Подчёркиваний у телефона и почты НЕТ и они не возвращаются. Слова
   Стаса 9.09.2026: «линии нахуя, и такие глупые». Линия при наведении шла
   во всю ширину колонки, а не под словом, — ссылки стоят строчными
   (inline-block), меняется только цвет. */
.svz__tel {
  display: inline-block;
  font-family: var(--display);
  font-weight: 300;
  font-size: clamp(28px, 2.9vw, 40px);
  line-height: 1.1;
  color: #f0e9de;
  transition: color .25s;
}
.svz__mail {
  display: inline-block;
  margin-top: 14px;
  font-family: var(--display);
  font-weight: 300;
  font-size: clamp(21px, 1.9vw, 28px);
  color: #d7cfc4;
  transition: color .25s;
}
.svz__tel:hover, .svz__mail:hover { color: #e6cfa2; }

/* Бланк заявки лежит на дереве: своё тёмное поле, иначе поля ввода
   теряются в рисунке шпона. */
.svz__blank {
  background: rgba(11,10,8,.72);
  border: 1px solid rgba(236,229,218,.16);
  padding: 38px 36px 36px;
  backdrop-filter: blur(2px);
}
.svz__blank .mark { margin-bottom: 24px; }
.svz__blank .form { max-width: none; gap: 16px; }
.svz__blank .field label { color: #b3a998; }
.svz__blank .field input {
  background: rgba(236,229,218,.06);
  border-color: rgba(236,229,218,.20);
  color: #f2ece2;
}
.svz__blank .field input:focus { border-color: #b09468; background: rgba(236,229,218,.09); }
.svz__blank .check span { color: #cdc4b7; }
.svz__blank .check a { color: #e6cfa2; }
/* Кнопка на тёмном — светлая: обычная тёмная на дереве не видна вовсе. */
.svz__blank .btn { background: #ece5da; border-color: #ece5da; color: #17140f; }
.svz__blank .btn:hover { background: #e6cfa2; border-color: #e6cfa2; color: #17140f; }

@media (max-width: 1000px) {
  .night .mat--svz { height: auto; padding: 70px 0 64px; }
  .svz__in { grid-template-columns: minmax(0, 1fr); gap: 44px; }
  .svz__blank { padding: 30px 24px 28px; }
}

/* ==========================================================================
   ПОДВАЛ НА ТЕЛЕФОНЕ — ГРУППАМИ, А НЕ СТОЛБИКОМ (11.09.2026)
   Слово Стаса: «можно как-то для телефона, чтобы не такой длинный раздел
   был нижний, чтобы он был сгруппирован». Было: всё одним столбиком —
   знак, пять разделов, телефон, почта, три строки реквизитов, две ссылки
   на документы, 1093 точки при экране 956 (замер на 17 Pro Max).
   Стало: знак со строкой в одну полосу, разделы и связь двумя колонками,
   реквизиты одной мелкой строкой, документы ниже. Ссылки остаются
   под палец (44), укорачивают подвал зазоры и столбик, а не сами ссылки.
   Широкий экран и ландшафт не тронуты — там подвал и так в колонках.
   ========================================================================== */
@media (max-width: 640px) {
  .footer { padding-top: 40px; padding-bottom: 26px; }
  .footer .footer__grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 26px 18px;
    padding-bottom: 26px;
  }
  .night .footer .footer__grid { padding-top: 44px; }
  /* знак и строка под ним — одна полоса во всю ширину */
  .footer__grid > div:first-child {
    grid-column: 1 / -1;
    display: flex;
    align-items: center;
    gap: 18px;
  }
  .footer__logo { width: 84px; margin: 0; flex: none; }
  .footer__grid > div:first-child p { font-size: 15px; line-height: 1.4; }
  .footer h4 { font-size: 11px; margin-bottom: 4px; }
  .footer ul a { padding: 10px 0; font-size: 15px; white-space: nowrap; }
  /* Разделы слева на две строки сетки, справа связь и под ней реквизиты:
     пять ссылок разделов по высоте как раз равны связи плюс реквизитам,
     дыры в правой колонке нет. Реквизиты мелко — это справка, не действие. */
  .footer__grid > div:nth-child(2) { grid-column: 1; grid-row: 2 / span 2; }
  .footer__grid > div:nth-child(3) { grid-column: 2; grid-row: 2; }
  .footer__grid > div:last-child { grid-column: 2; grid-row: 3; }
  .footer__grid > div:last-child ul { gap: 3px; font-size: 13px; line-height: 1.45; color: #8a8174; }
  .footer__grid > div:last-child h4 { margin-bottom: 8px; }
  .footer__bottom { padding-top: 16px; gap: 4px 20px; font-size: 13px; }
  .footer__legal a { padding: 9px 0; }
}

/* ==========================================================================
   «ОТБОР МАТЕРИАЛА И РУЧНАЯ РАБОТА» НА ТЕЛЕФОНЕ (11.09.2026)
   Слово Стаса: четыре квадрата остаются два на два, «чуть уменьши текст,
   оцентруй, чтобы красиво выглядело». Было «очень кучно»: подпись 21
   и фраза 17 курсивом в три строки под кадром в 200 точек, между плитками
   12 — подпись одного кадра упиралась в кадр под ним.
   Стало: подпись по центру кадра, имя 18, под ним короткая черта вместо
   черты во всю колонку, фраза 14,5 во всю ширину кадра (при 22ch она шла в четыре строки). Воздуха между плитками
   больше: 16 между столбцами, 34 между рядами.
   Широкий экран не тронут — там утверждённая раскладка 8.09.2026.
   ========================================================================== */
@media (max-width: 640px) {
  .made__grid { column-gap: 16px; row-gap: 34px; }
  .made__item figcaption { margin-top: 14px; text-align: center; }
  .made__mat {
    font-size: 18px;
    margin: 0 auto 8px;
    padding-bottom: 9px;
    border-bottom: 0;
    position: relative;
  }
  .made__mat::after {
    content: "";
    position: absolute;
    left: 50%; bottom: 0;
    width: 22px; height: 1px;
    margin-left: -11px;
    background: #a8997f;
  }
  .made__note {
    margin: 0 auto;
    max-width: none;
    font-size: 14.5px;
    line-height: 1.45;
    text-wrap: balance;   /* строки фразы ровные по длине, без хвоста в одно слово */
  }
}
