/* Светосистемы — дизайн-система мокапа. Один шрифт, один акцент, волосяные линии вместо рамок. */

@font-face {
  font-family: 'Onest';
  src: url('fonts/Onest-var.ttf') format('truetype');
  font-weight: 100 900;
  font-display: swap;
}

:root {
  --bg: #f7f5f2;
  --surface: #ffffff;
  --field: #f1ede7;
  --ink: #17191b;
  --ink-2: #5c5c58;
  /* Приглушённый текст: раньше #8b8a84 давал 3,0–3,5:1 — ниже нормы 4,5:1
     для мелкого текста (это артикулы, счётчики фильтров, подписи). #6d6d66
     даёт 4,6:1 на поле, 4,9:1 на фоне страницы и 5,2:1 на белом */
  --ink-3: #6d6d66;
  --line: #e4dfd8;
  --line-strong: #cfc8be;
  --accent: #c4621b;
  --accent-soft: #f6e9dd;
  --dark: #131518;
  --dark-2: #1d2024;
  --ok: #2f6b4f;
  --r-sm: 6px;
  --r-md: 12px;
  --r-lg: 20px;
  --max: 1360px;
  --gap: 24px;
  --shadow-lift: 0 18px 40px -28px rgba(23, 25, 27, .35);
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: 'Onest', system-ui, -apple-system, 'Segoe UI', sans-serif;
  font-size: 15px;
  line-height: 1.55;
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
}

a { color: inherit; text-decoration: none; }
img { display: block; max-width: 100%; }
button { font: inherit; cursor: pointer; }

.wrap { max-width: var(--max); margin: 0 auto; padding: 0 32px; }

/* ---------- типографика ---------- */

h1, h2, h3 { margin: 0; font-weight: 600; letter-spacing: -0.025em; line-height: 1.08; }
h1 { font-size: clamp(2.1rem, 3.9vw, 3.4rem); letter-spacing: -0.035em; }
h2 { font-size: clamp(1.5rem, 2.4vw, 2.1rem); }
h3 { font-size: 1.05rem; letter-spacing: -0.01em; }

.label {
  font-size: .70rem;
  text-transform: uppercase;
  letter-spacing: .11em;
  color: var(--ink-3);
  font-weight: 500;
}

.lead { font-size: 1.06rem; color: var(--ink-2); max-width: 46ch; }
.muted { color: var(--ink-2); }
.small { font-size: .82rem; }
.mono { font-variant-numeric: tabular-nums; letter-spacing: -0.01em; }

/* ---------- шапка ---------- */

.topbar {
  background: var(--dark);
  color: #b9b7b1;
  font-size: .78rem;
}
.topbar .wrap { display: flex; gap: 28px; align-items: center; height: 40px; }
.topbar a:hover { color: #fff; }
.topbar .push { margin-left: auto; }
.topbar .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--ok); display: inline-block; margin-right: 7px; }

.header {
  position: sticky;
  top: 0;
  z-index: 40;
  background: rgba(247, 245, 242, .92);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}
.header .wrap { display: flex; align-items: center; gap: 28px; height: 72px; }

.brand { display: inline-block; font-weight: 600; letter-spacing: -0.03em; font-size: 1.12rem; }
.brand i { font-style: normal; color: var(--accent); }

.nav { display: flex; gap: 22px; font-size: .92rem; }
.nav a { color: var(--ink-2); padding: 4px 0; border-bottom: 1.5px solid transparent; }
.nav a:hover { color: var(--ink); }
.nav a.on { color: var(--ink); border-bottom-color: var(--accent); }

.head-actions { margin-left: auto; display: flex; align-items: center; gap: 10px; }

.search-inline {
  position: relative;                 /* якорь для панели подсказок, см. .sug */
  display: flex; align-items: center; gap: 8px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 8px 14px;
  min-width: 250px;
  color: var(--ink-3);
  font-size: .88rem;
}
.search-inline svg { flex: none; }

/* ---------- подсказки поиска (assets/suggest.js) ----------
   Панель растёт вниз от строки поиска и не двигает ни шапку, ни страницу.
   Ширина как у Arlight (413–490 px), но прижата к правому краю строки: наше
   поле стоит ближе к правому краю шапки, и панель, растущая влево, уходит под
   пункты меню, а не за край окна. Ниже 620 px модуль не работает вовсе —
   строка поиска там сжата, а Enter открывает страницу поиска. */
.sug {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 5;
  width: 480px; max-width: calc(100vw - 32px);
  text-align: left; font-weight: 400; color: var(--ink);
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-md); box-shadow: var(--shadow-lift);
  padding: 8px;
  max-height: min(70vh, 560px); overflow-y: auto;
  /* Колесо над панелью не должно уходить в страницу: без этого список
     прокручивался до конца, а дальше начинала ехать страница под ним
     (замер 14.10.2026: панель 533 из 533, дальше window.scrollY 160…1600) */
  overscroll-behavior: contain;
}
.sug[hidden] { display: none; }
.sug__row {
  display: flex; align-items: center; gap: 12px;
  padding: 8px 10px; border-radius: var(--r-sm);
}
.sug__row:hover, .sug__row.on { background: var(--bg); }
.sug__pic { flex: none; width: 48px; height: 48px; display: grid; place-items: center; }
.sug__pic img { max-width: 48px; max-height: 48px; object-fit: contain; mix-blend-mode: multiply; }
.sug__body { flex: 1 1 auto; min-width: 0; display: grid; gap: 3px; }
/* Название — в две строки, лишнее многоточием: строка панели должна быть
   одной высоты, иначе список прыгает */
.sug__body b {
  font-weight: 500; font-size: .9rem; line-height: 1.35;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
}
.sug__meta { font-size: .78rem; color: var(--ink-3); }
.sug__price { flex: none; text-align: right; white-space: nowrap; }
.sug__price b { font-size: .92rem; }
.sug__price em { display: block; font-style: normal; font-size: .74rem; color: var(--ink-3); margin-top: 2px; }
.sug__group {
  padding: 10px 10px 4px; font-size: .72rem; letter-spacing: .06em;
  text-transform: uppercase; color: var(--ink-3);
}
.sug__row--serie .sug__body b { -webkit-line-clamp: 1; }
/* Строка раздела или подраздела (placeRow в assets/suggest.js): вместо фото
   товара — кадр раздела, вместо цены — стрелка перехода. Название в одну
   строку: под ним стоит родитель, по которому видно, куда ведёт строка */
.sug__row--place .sug__body b { -webkit-line-clamp: 1; }
.sug__go { flex: none; display: flex; color: var(--ink-3); }
.sug__all {
  display: flex; align-items: center; gap: 8px;
  margin-top: 6px; padding: 10px; border-top: 1px solid var(--line);
  border-radius: 0 0 var(--r-sm) var(--r-sm); font-size: .86rem;
}
.sug__all:hover, .sug__all.on { background: var(--bg); }
.sug__all svg { color: var(--ink-3); }
.sug__all span { color: var(--ink-3); }
.sug__wait { padding: 12px 10px; font-size: .86rem; color: var(--ink-3); }

/* ---------- разделы и подразделы в выдаче поиска ----------
   Тот же ответ, что в подсказках, но на странице: кадр раздела, название,
   число позиций и родитель. Строки идут над товарами — сначала «куда»,
   потом «что» (renderPlaces в search.html) */
.places { margin: 0 0 26px; display: grid; gap: 8px; }
.places .label { margin: 0; }
.place {
  display: flex; align-items: center; gap: 14px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-sm); padding: 10px 14px;
  transition: border-color .18s;
}
.place:hover { border-color: var(--ink); }
.place__pic { flex: none; width: 44px; height: 44px; display: grid; place-items: center; }
.place__pic img { max-width: 44px; max-height: 44px; object-fit: contain; mix-blend-mode: multiply; }
.place__body { flex: 1 1 auto; min-width: 0; display: grid; gap: 3px; }
.place__body b { font-weight: 500; font-size: .95rem; }
.place__meta { font-size: .78rem; color: var(--ink-3); }
.place__go { flex: none; color: var(--ink-3); }

/* ---------- кнопки ---------- */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  padding: 12px 20px;
  font-size: .9rem;
  font-weight: 500;
  background: var(--ink);
  color: #fff;
  transition: transform .18s cubic-bezier(.2,.7,.3,1), background .18s, border-color .18s, color .18s;
}
.btn:hover { background: #000; }
.btn:active { transform: translateY(1px) scale(.995); }
.btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.btn.ghost { background: transparent; border-color: var(--line-strong); color: var(--ink); }
.btn.ghost:hover { border-color: var(--ink); background: transparent; }

.btn.accent { background: var(--accent); }
.btn.accent:hover { background: #a95214; }

.btn.sm { padding: 9px 14px; font-size: .84rem; }
/* Кнопка «Показать все» в подписи под блоком «Товары серии»: подпись — обычный
   текст, кнопка должна от него отступить и встать на одну строку с ним */
#serie-more .btn { margin-left: 10px; vertical-align: middle; }
.btn.block { width: 100%; }
/* Выключенная кнопка (в корзине это «отправлять нечего») не должна и выглядеть
   нажимаемой: гасим и отклик на наведение, оставшийся от вариантов кнопки */
.btn:disabled, .btn:disabled:hover { opacity: .45; cursor: default; background: var(--ink); }
.btn.ghost:disabled, .btn.ghost:disabled:hover { background: transparent; border-color: var(--line); }
.btn.accent:disabled, .btn.accent:disabled:hover { background: var(--accent); }

.link-accent { color: var(--accent); border-bottom: 1px solid var(--accent-soft); }
.link-accent:hover { border-bottom-color: var(--accent); }

/* ---------- секции ---------- */

/* Отступы у блоков одинаковые, и полоска-разделитель есть у каждого блока,
   кроме первого после шапки. Раньше полоска рисовалась правилом
   «.section + .section»: там, где между блоками встал hero (у него свой padding
   и класс), линия пропадала, и низ страницы шёл без разделителей
   (заказчик 13.10.2026: «идёт полоска, а ниже нету полосок») */
.section { padding: 76px 0; border-top: 1px solid var(--line); }
.section:first-of-type { border-top: 0; }
.sec-head { display: flex; align-items: flex-end; gap: 24px; margin-bottom: 34px; }
.sec-head .push { margin-left: auto; }

/* ---------- первый экран ---------- */

/* Hero раньше имел свой отступ (58 сверху, 0 снизу) — из-за него расстояние
   между блоками скакало: после hero было вдвое меньше, чем между секциями */
.hero { padding: 76px 0; }
.hero-grid { display: grid; grid-template-columns: 1.15fr .85fr; gap: 56px; align-items: center; }

.hero h1 { max-width: 20ch; }
.hero .lead { margin: 20px 0 30px; }

.bigsearch {
  position: relative;                 /* якорь для панели подсказок, см. .sug */
  display: flex; align-items: center; gap: 10px;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  padding: 7px 7px 7px 18px;
  box-shadow: var(--shadow-lift);
}
.bigsearch input {
  border: 0; outline: 0; background: transparent;
  font: inherit; flex: 1; min-width: 0; padding: 10px 0;
}
.bigsearch input::placeholder { color: var(--ink-3); }

.hero-side { position: relative; }
.hero-scene {
  position: relative;
  border-radius: var(--r-lg);
  background: linear-gradient(155deg, #f0eae1 0%, #e7ddd1 55%, #dbcfbd 100%);
  aspect-ratio: 4 / 3.4;
  overflow: hidden;
  display: grid;
  place-items: center;
}
.hero-scene::after {
  content: "";
  position: absolute; inset: 0;
  background: radial-gradient(44% 36% at 52% 42%, rgba(255, 186, 96, .5) 0%, rgba(255, 186, 96, 0) 72%);
}
.hero-scene img {
  position: relative;
  width: 72%;
  mix-blend-mode: multiply;
  filter: drop-shadow(0 32px 48px rgba(80, 55, 25, .3));
}
.hero-badge {
  position: absolute; left: 22px; bottom: 22px;
  background: rgba(255,255,255,.94);
  border-radius: var(--r-sm);
  padding: 10px 14px;
  font-size: .82rem;
  display: grid; gap: 2px;
}
.hero-badge b { font-size: 1rem; }

.stats { display: flex; gap: 46px; margin: 44px 0 0; padding: 26px 0 0; border-top: 1px solid var(--line); }
.stats div { display: grid; gap: 3px; }
.stats b { font-size: 1.7rem; font-weight: 600; letter-spacing: -0.03em; }

/* ---------- категории ---------- */

.cat-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--gap); }
.cat-tile {
  position: relative;
  border-radius: var(--r-md);
  overflow: hidden;
  background: var(--dark-2);
  aspect-ratio: 4 / 3;
  display: flex; align-items: flex-end;
  padding: 18px;
  color: #fff;
  transition: transform .25s cubic-bezier(.2,.7,.3,1);
}
.cat-tile img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; opacity: .42;
  transition: transform .5s cubic-bezier(.2,.7,.3,1), opacity .25s;
}
.cat-tile span { position: relative; font-weight: 500; font-size: 1rem; }
.cat-tile small { position: relative; display: block; opacity: .72; font-size: .78rem; }
.cat-tile:hover img { transform: scale(1.05); opacity: .55; }

.cat-list { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0 40px; margin-top: 28px; }
/* Отступы внутрь и такие же отрицательные наружу: подложка при наведении
   читается строкой, а не обрубком по краям текста, а ширина под текст
   остаётся прежней (10 в плюс, 10 в минус). Серая подложка — как в меню
   «Каталог» (.nmenu__panel a:hover), чтобы наведение выглядело одинаково */
.cat-list a {
  display: flex; justify-content: space-between; align-items: center;
  padding: 15px 10px; margin: 0 -10px;
  border-bottom: 1px solid var(--line);
  font-size: .95rem;
  transition: color .16s, border-color .16s, background .16s;
}
.cat-list a:hover { background: var(--field); color: var(--accent); border-bottom-color: var(--accent); }
.cat-list a em { font-style: normal; color: var(--ink-3); font-size: .82rem; }

/* Лента новинок на главной: карточки идут в строку, в кадре четыре, остальные
   достаются прокруткой (стрелки или палец). Полоса прокрутки скрыта — на неё
   показывают стрелки */
.new-rail { overflow-x: auto; scroll-snap-type: x proximity; scrollbar-width: none; }
.new-rail::-webkit-scrollbar { display: none; }
.new-rail .products { display: flex; gap: var(--gap); }
.new-rail .pcard { flex: 0 0 calc((100% - 3 * var(--gap)) / 4); scroll-snap-align: start; }
.sec-arrows { display: flex; align-items: center; gap: 10px; }
.sec-arrows .slider__arrow { width: 36px; height: 36px; }
.sec-arrows .slider__arrow:disabled { opacity: .35; cursor: default; border-color: var(--line); }
@media (max-width: 1200px) { .new-rail .pcard { flex: 0 0 calc((100% - 2 * var(--gap)) / 3); } }
@media (max-width: 980px) { .new-rail .pcard { flex: 0 0 calc((100% - var(--gap)) / 2); } }

/* ---------- карточка товара (плитка) ---------- */

.products { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--gap); }
/* Каталог, поиск и избранное показывают плитки в три столбца, остальные
   страницы — в четыре. Раньше это задавал инлайн-стиль в разметке, и он же
   перебивал медиазапросы: на телефоне вместо двух колонок оставалось три, а в
   узкой карточке обрезалась кнопка «В корзину». Теперь это обычный класс,
   поэтому правила ниже (1200, 980) работают. */
.products--3 { grid-template-columns: repeat(3, 1fr); }
.pcard {
  background: var(--surface);
  border-radius: var(--r-md);
  overflow: hidden;
  display: flex; flex-direction: column;
  transition: transform .25s cubic-bezier(.2,.7,.3,1), box-shadow .25s;
}
.pcard:hover { transform: translateY(-3px); box-shadow: var(--shadow-lift); }
.pcard:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Рамка по краю поля: тёмное фото (гирлянда, чёрный профиль) иначе сливалось
   с карточкой — на белом фоне видна только она сама, а не её край
   (заказчик 13.10.2026: «продумать момент для тёмных фото, чтобы не сливалось») */
/* Поле кадра — жёсткий квадрат. Раньше у картинки стоял `height: 100%` при
   родителе с `aspect-ratio: 1/1` и `height: auto`: процентная высота в таком
   родителе не разрешается, и высоту поля задавал сам кадр — вертикальный чертёж
   (1414×2000) растягивал поле с 305 до 424 px, а плитка прыгала при листании
   (заказчик 16.10.2026: «смотри как пляшет карточка»). Абсолютное позиционирование
   картинки и `overflow: hidden` высоту поля от содержимого больше не зависят. */
.pcard__media { position: relative; background: var(--field); aspect-ratio: 1 / 1;
  overflow: hidden; box-shadow: inset 0 0 0 1px rgba(24, 24, 16, .06); }
/* Отступ 16 px -> 10 px: фото в плитке было заметно мельче поля, а виноваты были
   не точки-миниатюры, а сам отступ (заказчик 13.10.2026: «картинка уменьшается,
   можно не уменьшать»). Широкий кадр всё равно не заполнит квадрат целиком —
   contain вписывает его по длинной стороне, обрезать не хотим */
.pcard__media img { position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: contain; padding: 10px; mix-blend-mode: multiply; }
/* z-index нужен, чтобы ярлык не накрывался фотографией: картинка идёт в разметке
   после ярлыка, и без z-index она перекрывала его там, где занимает всю ширину
   (на тёмных кадрах гирлянд «Новинку» совсем не было видно — заказчик 13.10.2026).
   Тень — чтобы ярлык читался и на светлых, и на тёмных кадрах */
.pcard__flag {
  position: absolute; top: 12px; left: 12px; z-index: 2;
  background: var(--ink); color: #fff;
  box-shadow: 0 1px 4px rgba(24, 24, 16, .28);
  font-size: .68rem; letter-spacing: .06em; text-transform: uppercase;
  padding: 5px 9px; border-radius: 4px;
}
/* Ярлык «Серия» на плитке серии: тот же угол, что у «Новинки», но спокойный —
   он не про новинку, а про то, что это не товар, а серия */
.pcard__flag.serie { background: rgba(19, 21, 24, .72); color: #fff; }
.pcard__flag.new { background: var(--accent); }
/* Стопка ярлыков в углу плитки. Ярлыков у позиции может быть два — «Новинка» и
   скидка акции, — а .pcard__flag стоит абсолютно в одной и той же точке, и вторая
   плашка ложилась бы ровно на первую. Контейнер раскладывает их в столбик, а
   вложенные ярлыки внутри него уже обычные (позицию задаёт сам контейнер).
   Плитка, где ярлык один, может обойтись без контейнера — правило не мешает */
.pcard__flags {
  position: absolute; top: 12px; left: 12px; z-index: 2;
  display: flex; flex-direction: column; align-items: flex-start; gap: 6px;
}
.pcard__flags .pcard__flag { position: static; }
/* Кнопки плитки (сердечко и весы) раскладывает .pcard__tools — здесь только
   размеры, иначе абсолютное позиционирование ставило обе иконки в одну точку */
.pcard__body { padding: 14px 16px 16px; display: flex; flex-direction: column; gap: 8px; flex: 1; }
.pcard__name { font-size: .92rem; line-height: 1.35; letter-spacing: -0.01em; }
.pcard__meta { color: var(--ink-3); font-size: .76rem; }
.pcard__price {
  margin-top: auto;
  padding-top: 12px;
  border-top: 1px solid var(--line);
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
}
.pcard__price b { font-size: 1.12rem; font-weight: 600; letter-spacing: -0.02em; }
/* Прежняя цена «до акции» — один класс на все места, где рисуется цена: плитка
   каталога и поиска, строка списка, быстрый просмотр, избранное, страница
   позиции (разметку собирает window.priceBox в lists.js). Раньше правило было
   привязано к «.pcard__price b s» и было мёртвым — зачёркнутой цены не было
   нигде, хотя стиль под неё уже стоял. На странице позиции её перебивает
   «.price-row s» (там цена крупнее) — так и задумано */
.price-old { font-weight: 400; color: var(--ink-3); font-size: .8rem; text-decoration-thickness: 1px; }
.pcard__price em { font-style: normal; color: var(--ink-3); font-size: .78rem; }
.pcard__actions { display: flex; gap: 8px; margin-top: 4px; }
.pcard__actions .btn { flex: 1; }

/* Карточка товара: цена и «В корзину» в одной строке — так карточка ниже и в
   сетке помещается больше позиций. Обёртку .pcard__buy ставят все места, где
   рисуется карточка: каталог, избранное, поиск, главная, страницы «для кого».
   Строка «минимальный объём закупки» уходит под них на всю ширину (order 3). */
.pcard__buy {
  /* Свободное место собирает эта строка — но только когда выше нет строки
     остатков: у карточек без неё (аксессуары на странице позиции) место иначе
     не собирается вовсе, и цены в ряду встают на разной высоте.
     Когда строка остатков есть, автоотступ снимается (правило ниже):
     с ним у обоих элементов место делилось бы, и остатки расходились на 10 px
     (заказчик 12.10.2026) */
  margin-top: auto;
  padding-top: 12px; border-top: 1px solid var(--line);
  display: flex; align-items: center; justify-content: space-between;
  gap: 6px 12px; flex-wrap: wrap;
}
/* Строка остатков есть — место собирает она, у покупки отступ убираем */
.pcard__avail + .pcard__buy { margin-top: 0; }
/* Характеристики — часть нижней группы, а не верхней: место собирается над ними.
   Иначе характеристики шли вровень с названием и метками, и в ряду плиток
   строка «20 Вт · 3 500 K · CRI 90» стояла ниже соседей, у которых метки нет
   (заказчик 10.10.2026). Автоотступ должен быть ровно у одного элемента —
   у двух место делится, и уровни снова разъезжаются */
.pcard__body > .pcard__specs { margin-top: auto; }
.pcard__body > .pcard__specs ~ .pcard__avail { margin-top: 0; }
.pcard__body > .pcard__specs ~ .pcard__buy { margin-top: 0; }
.pcard__buy .pcard__price {
  /* Основа 0, а не auto: ширину строки делят цена и кнопка, а содержимое
     цены — её забота. С основой auto ширина цены считалась по содержимому,
     и акционная цена с зачёркнутой прежней (90 px) выталкивала «В корзину»
     на вторую строку во всю ширину плитки (заказчик 17.10.2026). У обычной
     позиции раскладка та же: цена и так забирала всё свободное место */
  margin-top: 0; padding-top: 0; border-top: 0; flex: 1 1 0; order: 2;
  display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap;
}
/* Цена до акции — отдельной строкой над суммой: рядом с суммой, «за шт» и
   кнопкой она не помещается (305 px плитка: 90 + 100 + 40 + 100 + зазоры),
   а переносить её на вторую строку вместе с кнопкой — значит увести кнопку
   из строки цены. Строка занимает всю ширину блока, сумма и «за шт» встают
   под ней как обычно */
.pcard__buy .pcard__price .price-old { flex: 1 1 100%; }
.pcard__buy .pcard__actions { margin-top: 0; order: 3; align-self: flex-end; }
.pcard__buy .pcard__actions .btn { flex: none; padding: 9px 16px; }
/* Строка «минимальный объём закупки» идёт первой: тогда последней строкой в
   карточке всегда остаётся цена с кнопкой, и у соседних карточек кнопки стоят
   на одном уровне. Если оставить её под кнопкой, карточка с этой строкой
   поднимает кнопку выше остальных */
.pcard__buy .pcard__pack { order: 1; flex: 1 1 100%; }
/* Сумма за минимальный объём — тем же серым, что и подпись: это не цена
   позиции, и второй чёрной ценой она спорила с ценой за единицу ниже.
   На странице позиции (#p-pack) сумма остаётся тёмной — там она стоит внутри
   фразы «минимальный объём закупки, N ₽», а не отдельной строкой */
.pcard__buy .pcard__pack b { color: var(--ink-3); }
/* Счётчик количества по умолчанию растягивается на всю ширину и уезжает на
   вторую строку — задаём ему ту же ширину, что в списке каталога */
.pcard__buy .qty--card { width: 96px; }
.pcard__buy .qty--card button { width: 27px; }
.pcard__buy .qty--card input { width: 40px; }

/* ---------- быстрый заказ по файлу ---------- */

.filebox {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: 0;
  background: var(--surface);
  border-radius: var(--r-lg);
  overflow: hidden;
  border: 1px solid var(--line);
}
.filebox__text { padding: 46px; display: flex; flex-direction: column; gap: 18px; justify-content: center; }
.filebox__drop {
  padding: 46px;
  background: var(--accent-soft);
  display: grid; gap: 14px; align-content: center;
}
.drop-slot {
  border: 1.5px dashed rgba(196, 98, 27, .45);
  border-radius: var(--r-md);
  padding: 26px;
  text-align: center;
  display: grid; gap: 6px;
  background: rgba(255,255,255,.6);
}
.steps3 { display: grid; gap: 10px; margin: 4px 0 0; }
.steps3 div { display: flex; gap: 12px; align-items: center; font-size: .88rem; color: var(--ink-2); }
/* Номер шага — плашкой бренда: жёлтый как ЦВЕТ ТЕКСТА на белом даёт 1,7:1
   и не годится (правило контраста выше), а тёмный текст на жёлтой плашке —
   около 10:1. Раньше номер был жёлтым на белом */
.steps3 b {
  flex: none; width: 20px; height: 20px; display: grid; place-items: center;
  background: var(--accent); color: var(--accent-ink); border-radius: 50%;
  font-size: .76rem; font-weight: 600; line-height: 1;
}

/* ---------- каталог: фильтр + сетка ---------- */

.crumbs { display: flex; flex-wrap: wrap; align-items: baseline; gap: 9px; color: var(--ink-3); font-size: .82rem; padding: 22px 0 0; }
.crumbs a { color: var(--ink-3); border-bottom: 1px solid transparent; }
.crumbs a:hover { color: var(--ink); border-bottom-color: var(--accent); }
.crumbs [aria-current] { color: var(--ink); font-weight: 500; }

.cat-head { display: flex; align-items: flex-end; gap: 24px; padding: 18px 0 26px; }
.cat-head .push { margin-left: auto; display: flex; gap: 10px; align-items: center; }

.catalog-layout { display: grid; grid-template-columns: 288px 1fr; gap: 44px; align-items: start; padding-bottom: 80px; }

/* Панель фильтров бывает длиннее экрана — в «Источниках питания» 5542 px при
   экране 760 px. Закреплять такую панель нельзя: sticky держится только пока
   панель ниже колонки товаров (тогда высоту строки сетки задаёт она сама и
   sticky не работает вовсе — шапка фильтров уезжает вверх), а стоит раскрыть
   пару «аксессуаров», колонка товаров перерастает панель — и та рывком встаёт
   под шапкой. Положение панели не должно зависеть от того, что раскрыто в
   списке, поэтому прокручивается она вместе со страницей. Своя прокрутка внутри
   панели (max-height + overflow) тоже рассматривалась и отклонена: полоса
   прокрутки в колонке фильтров не нужна. */
/* ---------- каталог: дерево разделов в левой колонке ----------
   Дубль верхнего меню шапки: раздел → группа → подгруппа, выбранная ветка
   раскрыта, конечная папка подсвечена. Стоит в той же колонке, что и фильтры,
   поэтому дерево и панель обёрнуты в .cat-side — один элемент сетки: иначе
   сетка «288px 1fr» разложила бы их в две колонки */
.cat-side { display: grid; gap: 30px; align-content: start; }

.rtree { border-bottom: 1px solid var(--line); padding-bottom: 18px; }
/* «Разделы» — кнопка: сворачивает блок целиком. На узком экране он приходит
   свёрнутым (initTree в catalog.html), иначе дерево отодвигает фильтры */
.rtree__toggle {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 0 0 14px; border: 0; background: transparent; font: inherit;
  color: var(--ink); text-align: left; cursor: pointer;
}
.rtree__toggle b { font-weight: 600; font-size: 1rem; letter-spacing: -0.01em; }
.rtree__chev {
  flex: none; width: 7px; height: 7px; margin-top: -3px;
  border-right: 1.5px solid var(--ink-3); border-bottom: 1.5px solid var(--ink-3);
  transform: rotate(45deg); transition: transform .18s, border-color .16s;
}
.rtree__toggle .rtree__chev { margin-left: auto; }
.rtree.is-open .rtree__toggle .rtree__chev { transform: rotate(-135deg); margin-top: 3px; }
.rtree:not(.is-open) .rtree__back,
.rtree:not(.is-open) .rtree__body { display: none; }

/* Строка «наверх»: без выбранной папки — «Все разделы», с папкой — имя раздела */
.rtree__back { padding-bottom: 12px; font-size: .82rem; }
.rtree__back a { color: var(--ink-2); }
.rtree__back a:hover { color: var(--ink); }

.rtree__body { display: grid; }
/* Строка выровнена по базовой линии: имя может переноситься на две строки, и тогда
   счётчик должен стоять у первой, а не висеть посередине. Стрелка — по центру строки */
.rtree__item {
  display: flex; align-items: baseline; gap: 8px;
  padding: 7px 8px 7px 2px; font-size: .93rem; color: var(--ink-2);
}
.rtree__item .rtree__chev { align-self: center; }
.rtree__item:hover { color: var(--ink); background: var(--field); }
/* Колонка счётчика — фиксированной ширины. Иначе её ширина зависит от цифры
   («0» — 8 px, «147» — 25 px), имя получает то больше, то меньше места, и строка
   то влезает в одну, то переносится на две: список прыгал при каждой правке
   фильтров (заказчик 14.10.2026: «количество уменьшилось и влезло в строку»).
   40 px хватает на самый длинный счётчик дерева — «4 717» */
.rtree__item em {
  flex: none; width: 40px; margin-left: auto; text-align: right;
  font-style: normal; font-size: .78rem; color: var(--ink-3);
}
/* Выбранная папка — тёмный текст на акцентной заливке и полоса слева. Жёлтый
   как ЦВЕТ ТЕКСТА на белом даёт 1,7:1 (правило контраста выше), поэтому
   выбранное показано заливкой, а не цветом букв. Полужирный не берём: он шире
   обычного, и выбранная строка снова начинала переноситься (см. колонку счётчика) */
.rtree__item.is-on {
  color: var(--ink);
  background: var(--accent-soft); box-shadow: inset 2px 0 0 var(--accent);
}
.rtree__item.is-on em { color: var(--ink-2); }
.rtree__item.is-empty { color: var(--ink-3); }
.rtree__item--sub { padding-left: 22px; }
.rtree__item.is-on .rtree__chev { transform: rotate(-135deg); margin-top: 3px; }
/* Хвост подгрупп у длинных групп: у «Светодиодных лент» 301 подгруппа, а своей
   прокрутки в колонке фильтров по решению от 13.10 быть не должно */
.rtree__more {
  margin: 4px 0 6px 22px; padding: 0 0 2px;
  border: 0; border-bottom: 1px solid var(--line-strong);
  background: transparent; font: inherit; font-size: .82rem;
  color: var(--ink-2); text-align: left; cursor: pointer;
}
.rtree__item:focus-visible, .rtree__more:focus-visible,
.rtree__toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.rtree__more:hover { color: var(--ink); border-bottom-color: var(--accent); }

/* Заголовок панели фильтров и сброс рядом с ним — как в кабинете Arlight.
   Сброс только снимает фильтры (бренд, особенности, склады, характеристики,
   цену), раздел каталога остаётся: он виден и в крошке, и в адресе */
.filters__head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  padding-bottom: 16px; border-bottom: 1px solid var(--line);
}
.filters__head b { font-weight: 600; font-size: 1rem; letter-spacing: -0.01em; }
.filters__reset {
  border: 0; background: transparent; padding: 0;
  font: inherit; font-size: .82rem; color: var(--ink-3); cursor: pointer;
  border-bottom: 1px solid transparent; transition: color .16s, border-color .16s;
}
.filters__reset:hover { color: var(--ink); border-bottom-color: var(--accent); }
.filters__reset:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; border-radius: 2px; }

.filters { display: grid; gap: 0; }
.fgroup { border-bottom: 1px solid var(--line); padding: 20px 0; }
/* Отступ сверху у первой группы раньше снимался («padding-top: 0»), потому что
   над ней ничего не было. Теперь над ней заголовок панели с линией, а у
   сворачиваемых групп одинаковые отступы — первая слипалась с линией, и
   «Особенности» выглядело прижатым к верху. Отступ оставляем всем группам */
/* Группа фильтров — строка с названием и стрелкой, тело раскрывается по нажатию,
   как в кабинете Arlight: целиком раскрытая панель выходит на полтора экрана
   (в «Источниках питания» — 5 542 px при экране 760). Заголовок — кнопка, а не
   div: с клавиатуры работает сам, а aria-expanded сообщает состояние читалке.
   По умолчанию группы свёрнуты, раскрытые вручную помнит OPEN_GROUPS
   (catalog.html), панель пересобирается на каждую правку фильтра */
.fgroup__head {
  display: flex; align-items: center; width: 100%; margin-bottom: 14px;
  padding: 0; border: 0; background: transparent;
  font: inherit; text-align: left; color: var(--ink-2); cursor: pointer;
}
.fgroup__head b { font-weight: 500; font-size: .93rem; margin-right: auto; }
.fgroup__head i { font-style: normal; color: var(--ink-3); font-size: .78rem; margin-right: 10px; }
.fgroup__chev {
  flex: none; width: 7px; height: 7px; margin-top: -3px;
  border-right: 1.5px solid var(--ink-3); border-bottom: 1.5px solid var(--ink-3);
  transform: rotate(45deg); transition: transform .18s, border-color .16s;
}
.fgroup.is-open .fgroup__chev { transform: rotate(-135deg); margin-top: 3px; }
button.fgroup__head:hover b, button.fgroup__head:hover .fgroup__chev { color: var(--ink); }
button.fgroup__head:hover .fgroup__chev { border-color: var(--ink); }
.fgroup__head:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.fgroup:not(.is-open) .fgroup__head { margin-bottom: 0; }
/* Тело свёрнутой группы прячем целиком — свёрнутая группа и есть одна строка
   с названием. Правило убирали 13.10.2026, когда панель открывалась списком из
   32 пустых заголовков без единого значения (заказчик: «нет значений, пока не
   щёлкнешь по каждой группе»); 15.10.2026 вернули по его же просьбе: «надо чтобы
   они были свёрнуты, а по умолчанию открыты только метки, наличие и цена».
   Тело в обёртке .fgroup__body есть только у групп каталога: на странице поиска
   группы собраны без неё, и прятать там нечего */
.fgroup:not(.is-open) .fgroup__body { display: none; }
/* Метки, Наличие и Цена не сворачиваются: у них заголовок не кнопка,
   сворачивать нечего — палец и стрелка им не нужны */
.fgroup__head--plain { cursor: default; }
.fgroup__head--plain i { margin-right: 0; }
.check { display: flex; align-items: center; gap: 10px; padding: 5px 0; font-size: .89rem; color: var(--ink-2); cursor: pointer; }
.check:hover { color: var(--ink); }
.check input { appearance: none; width: 17px; height: 17px; border: 1px solid var(--line-strong); border-radius: 4px; flex: none; position: relative; }
.check input:checked { background: var(--ink); border-color: var(--ink); }
.check input:checked::after { content: ""; position: absolute; left: 5px; top: 2px; width: 5px; height: 9px; border: 2px solid #fff; border-top: 0; border-left: 0; transform: rotate(42deg); }
/* Часть отмечена, часть нет («Все» в корзине): без этого правила галочка в
   промежуточном состоянии выглядела бы пустой, как снятая */
.check input:indeterminate { background: var(--ink); border-color: var(--ink); }
.check input:indeterminate::after { content: ""; position: absolute; left: 4px; top: 7px; width: 9px; height: 2px; border: 0; border-radius: 1px; background: #fff; transform: none; }
.check input:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.check em { margin-left: auto; font-style: normal; color: var(--ink-3); font-size: .78rem; }

.range-row { display: flex; align-items: center; gap: 10px; }
.range-row input {
  width: 100%; border: 1px solid var(--line); border-radius: var(--r-sm);
  background: var(--surface); padding: 9px 11px; font: inherit; font-size: .86rem;
}
/* Ползунок диапазона цены: два range-инпута лежат друг на друге на общем треке.
   Так каждая ручка остаётся настоящим ползунком — мышь, клавиатура, чтение с
   экрана, — а выбранный отрезок рисует заливка под ними. События мыши ловят
   только сами ручки (у инпутов pointer-events выключен), иначе верхний
   перехватывал бы нажатия по всему треку и нижнюю ручку было не сдвинуть */
.price-range { position: relative; height: 26px; margin: 2px 0 30px; }
.price-range__track {
  position: absolute; left: 0; right: 0; top: 50%; height: 3px; margin-top: -1.5px;
  background: var(--line); border-radius: 2px;
}
.price-range__fill { position: absolute; top: 0; bottom: 0; background: var(--ink); border-radius: 2px; }
/* Риски цен под треком — как у Arlight: минимальная цена и круглые ступени.
   Первая подпись прижата к левому краю, последние (у самого правого края) —
   к правому, иначе они свисают за пределы колонки фильтров */
.price-range__ticks { position: absolute; left: 0; right: 0; top: 100%; }
.price-range__tick { position: absolute; font-size: .72rem; color: var(--ink-3); white-space: nowrap; }
.price-range__tick.tick--mid { transform: translateX(-50%); }
.price-range__tick.tick--end { transform: translateX(-100%); }
.price-range__in,
.range-box__in {
  position: absolute; left: 0; top: 0; width: 100%; height: 26px; margin: 0; padding: 0;
  background: transparent; border: 0; appearance: none; -webkit-appearance: none;
  pointer-events: none; cursor: pointer;
}
.price-range__in:focus,
.range-box__in:focus { outline: none; }
.price-range__in::-moz-range-track,
.range-box__in::-moz-range-track { background: transparent; border: 0; }
.price-range__in::-webkit-slider-thumb,
.range-box__in::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none; pointer-events: auto;
  width: 15px; height: 15px; border-radius: 50%;
  background: var(--surface); border: 2px solid var(--ink);
  box-shadow: 0 1px 3px rgba(23, 25, 27, .25); cursor: pointer;
}
.price-range__in::-moz-range-thumb,
.range-box__in::-moz-range-thumb {
  pointer-events: auto; width: 13px; height: 13px; border-radius: 50%;
  background: var(--surface); border: 2px solid var(--ink); cursor: pointer;
}
.price-range__in:focus-visible::-webkit-slider-thumb,
.range-box__in:focus-visible::-webkit-slider-thumb { outline: 2px solid var(--accent); outline-offset: 2px; }
.price-range__in:focus-visible::-moz-range-thumb,
.range-box__in:focus-visible::-moz-range-thumb { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ---------- модуль «Цена» ----------
   Цена, «Распродажа» и «Новинка» — одной карточкой вверху панели (заказчик
   19.10.2026). Карточка отделена от остальных групп рамкой и фоном: это
   быстрый отбор, а не ещё одна характеристика раздела. Поля «от» и «до» стоят
   по половине ширины, единица «руб.» — внутри поля справа, как в макете */
.fgroup--module {
  border: 1px solid var(--line); border-radius: var(--r-md);
  background: var(--surface); padding: 18px 14px 16px; margin-bottom: 10px;
}
/* Первый модуль отходит от линии заголовка панели: у обычных групп этот зазор
   даёт их padding-top, а у карточки свои отступы, и рамка примыкала к линии
   вплотную (заказчик 19.10.2026) */
#filters > .fgroup--module:first-child { margin-top: 16px; }
.fgroup--module .fgroup__head { margin-bottom: 12px; }
.fgroup--module .fgroup__head b { font-size: 1rem; font-weight: 600; color: var(--ink); }
.price-inputs { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
.price-input { position: relative; display: block; }
.price-input input {
  width: 100%; border: 1px solid var(--line); border-radius: var(--r-sm);
  background: var(--surface); padding: 9px 38px 9px 8px;
  font: inherit; font-size: .84rem; color: var(--ink);
  -moz-appearance: textfield;
}
.price-input input::-webkit-outer-spin-button,
.price-input input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.price-input input::placeholder { color: var(--ink-3); opacity: 1; font-size: .70rem; letter-spacing: -.015em; }
.price-input input:hover { border-color: var(--line-strong); }
.price-input input:focus { outline: none; border-color: var(--accent); }
.price-input input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.price-input span {
  position: absolute; right: 10px; top: 50%; transform: translateY(-50%);
  font-size: .78rem; color: var(--ink-3); pointer-events: none;
}
/* Ползунок под полями: поля для точного значения, ручки — чтобы задать
   диапазон одним движением. Отступ сверху отделяет его от полей */
.fgroup--module .price-range { margin: 20px 0 30px; }
/* Переключатели модуля: подпись слева, тумблер справа. Галочка настоящая
   (input внутри label) — работает с клавиатуры и читалкой, тумблер только
   рисует её состояние. Приглушённый ряд — в папке нечего включать */
.filter-switches { display: grid; gap: 2px; }
.switch-row {
  position: relative; display: flex; align-items: center; justify-content: space-between;
  gap: 12px; padding: 7px 0; font-size: .93rem; font-weight: 500;
  color: var(--ink); cursor: pointer;
}
.switch-row input { position: absolute; opacity: 0; width: 1px; height: 1px; margin: 0; }
.switch {
  position: relative; flex: none; width: 38px; height: 22px;
  border-radius: 999px; background: var(--line-strong);
  transition: background .18s;
}
.switch::after {
  content: ""; position: absolute; left: 2px; top: 2px;
  width: 18px; height: 18px; border-radius: 50%;
  background: var(--surface); box-shadow: 0 1px 2px rgba(23, 25, 27, .25);
  transition: transform .18s;
}
.switch-row input:checked + .switch { background: var(--accent); }
.switch-row input:checked + .switch::after { transform: translateX(16px); }
.switch-row input:focus-visible + .switch { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ---------- строки модуля «Размеры» ----------
   Подпись слева, два поля «от/до» справа. Колонка подписи фиксирована, чтобы
   поля во всех строках стояли на одной вертикали; длинные подписи
   («Монтажное отверстие, диаметр, мм») переносятся, а не растягивают строку.
   В 288 px колонки фильтров помещается 96 + 6 + 74 + 6 + 74 = 256 px */
.fgroup--sizes .fgroup__body { display: grid; gap: 2px; }
.size-row {
  display: grid; grid-template-columns: minmax(0, 88px) minmax(0, 1fr) minmax(0, 1fr);
  gap: 6px; align-items: center; padding: 10px 0;
}
.size-row__name {
  font-size: .84rem; line-height: 1.25; color: var(--ink-2);
}
.size-row__in {
  width: 100%; min-width: 0; border: 1px solid var(--line); border-radius: var(--r-sm);
  background: var(--surface); padding: 8px 5px;
  font: inherit; font-size: .78rem; color: var(--ink);
  -moz-appearance: textfield;
}
.size-row__in::-webkit-outer-spin-button,
.size-row__in::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.size-row__in::placeholder { color: var(--ink-3); opacity: 1; font-size: .72rem; }
.size-row__in:hover { border-color: var(--line-strong); }
.size-row__in:focus { outline: none; border-color: var(--accent); }
.size-row__in:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* У выбранного размера подпись темнее: поля с числом и так видно, но строку
   среди пяти-шести проще найти по контрасту подписи */
.size-row.is-on .size-row__name { color: var(--ink); }
/* ---------- модуль «Цвет и материал» ----------
   Внутри карточки — раскрывающиеся секции: заголовок, поиск, список
   с галочками и своей прокруткой. Строки — обычные .check, поэтому галочки,
   счётчики и приглушение недоступных значений те же, что в остальных группах.
   Цвета получают кружок .swatch, материалы — без него, как в макете */
.cm-group { border-top: 1px solid var(--line); }
.cm-group:first-child { border-top: 0; }
.cm-group__head {
  display: flex; align-items: center; width: 100%; gap: 8px;
  padding: 9px 0; border: 0; background: transparent;
  font: inherit; text-align: left; color: var(--ink-2); cursor: pointer;
}
.cm-group__head b { font-weight: 500; font-size: .88rem; margin-right: auto; }
.cm-group__head i { font-style: normal; font-size: .76rem; color: var(--ink-3); }
.cm-group__head:hover { color: var(--ink); }
.cm-group__head:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 2px; }
.cm-group__chev {
  flex: none; width: 7px; height: 7px; margin-top: -3px;
  border-right: 1.5px solid var(--ink-3); border-bottom: 1.5px solid var(--ink-3);
  transform: rotate(45deg); transition: transform .18s, border-color .16s;
}
.cm-group.is-open .cm-group__chev { transform: rotate(-135deg); margin-top: 3px; }
.cm-group__head:hover .cm-group__chev { border-color: var(--ink); }
.cm-group__body { display: none; padding: 0 0 8px; }
.cm-group.is-open .cm-group__body { display: block; }
.cm-group .fgroup__search { margin-bottom: 8px; }
.cm-group .fgroup__list { max-height: 300px; padding-right: 10px; }
.cm-group .fgroup__empty { margin-top: 4px; }
@media (max-width: 380px) {
  .size-row { grid-template-columns: minmax(0, 104px) minmax(0, 1fr) minmax(0, 1fr); gap: 5px; }
  .size-row__name { font-size: .8rem; }
  .size-row__in { font-size: .76rem; padding: 8px 5px; }
}
@media (max-width: 380px) {
  .fgroup--module { padding: 15px 12px 13px; }
  .price-input input { padding-left: 9px; padding-right: 38px; font-size: .82rem; }
  .price-input span { right: 8px; font-size: .74rem; }
}
.chips { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 22px; }
.chip {
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--accent-soft); color: #8c4413;
  border-radius: 999px; padding: 6px 12px; font-size: .82rem;
}
.chip button { border: 0; background: transparent; color: inherit; font-size: 1rem; line-height: 1; padding: 0; }

/* Строка «соседние значения»: что есть рядом по характеристике и ступени
   расширения допуска. Точка отсчёта — текущий допуск: значения внутри него
   подсвечены, выбранное залито акцентом. */
.nearby {
  display: flex; align-items: center; flex-wrap: wrap; gap: 10px 12px;
  padding: 12px 16px; margin-bottom: 14px;
  border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface);
}
.nearby__label { font-size: .84rem; color: var(--ink-3); flex: none; }
.nearby__vals { display: flex; flex-wrap: wrap; gap: 6px; }
.nearby__ctl { display: flex; align-items: center; gap: 8px; margin-left: auto; }
.nearby__note { font-size: .78rem; color: var(--ink-3); }
.nb {
  display: inline-flex; align-items: center; gap: 6px;
  border: 1px solid var(--line-strong); background: var(--surface); color: var(--ink-2);
  border-radius: 999px; padding: 5px 11px; font-size: .84rem; transition: background .14s, border-color .14s;
}
.nb em { font-style: normal; font-size: .7rem; color: var(--ink-3); }
.nb:hover { border-color: var(--ink-3); color: var(--ink); }
.nb:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.nb.in { border-color: var(--accent); background: var(--accent-soft); color: var(--ink); }
.nb.on { border-color: var(--accent); background: var(--accent); color: var(--accent-ink); }
.nb.on em { color: var(--accent-ink); opacity: .7; }
.nb[disabled] { opacity: .4; cursor: default; }
.nb[disabled]:hover { border-color: var(--line-strong); color: var(--ink-2); }
.nb--ctl { font-weight: 500; }

.toolbar { display: flex; align-items: center; gap: 14px; margin-bottom: 20px; }
.toolbar .push { margin-left: auto; }
.select {
  border: 1px solid var(--line); background: var(--surface); border-radius: var(--r-sm);
  padding: 9px 12px; font: inherit; font-size: .86rem;
}

.pagination { display: flex; gap: 6px; justify-content: center; margin-top: 44px; }
.pagination a {
  min-width: 38px; height: 38px; display: grid; place-items: center;
  border: 1px solid var(--line); border-radius: var(--r-sm); font-size: .88rem;
  background: var(--surface);
}
.pagination a:hover { border-color: var(--ink); }
.pagination a.on { background: var(--ink); color: #fff; border-color: var(--ink); }
/* Стрелка на краю списка: место под неё оставляем, но нажимать нечего */
.pagination__off {
  min-width: 38px; height: 38px; display: grid; place-items: center;
  color: var(--line-strong); font-size: .88rem;
}

/* Листалка в конце списка: слева «Показывать N» и место в списке, справа —
   страницы. Переключатель страницы есть и в шапке списка, но, дойдя до конца
   выдачи, его ищут здесь (как у Arlight), а не прокруткой наверх */
.pager-bar { display: flex; align-items: center; flex-wrap: wrap; gap: 10px 14px; margin-top: 44px; }
.pager-bar #range { margin-right: auto; }
.pager-bar .pagination { margin-top: 0; margin-left: auto; }
.pager-bar .select { padding-top: 7px; padding-bottom: 7px; }
/* Прокрутка к якорю не должна заводить блок под липкую шапку: её .wrap — 72 px
   плюс рамка. #fileorder — блок «Комплектуем объекты светом»: на него ведут
   кнопки «Загрузить спецификацию» с главной и одиннадцати страниц, и раньше
   его заголовок наполовину уезжал под шапку (заказчик 13.10.2026:
   «при нажатии на баннер вот так съезжает на форму, поправь, частично не видно») */
#products, #plist, #fileorder { scroll-margin-top: 96px; }
@media (max-width: 700px) {
  /* На телефоне страницы уходят на свою строку и переносятся, а не сжимаются */
  .pager-bar .pagination { margin-left: 0; width: 100%; justify-content: flex-start; flex-wrap: wrap; }
}

/* ---------- страница товара ---------- */

.pdp { display: grid; grid-template-columns: 1.05fr .95fr; gap: 56px; padding: 26px 0 80px; align-items: start; }
/* Обёртка галереи нужна ради значков избранного и сравнения: они лежат поверх
   фото, но вне .gallery__main — тот перерисовывается при листании и снёс бы их */
.gallery { position: relative; }
.gallery__tools { position: absolute; top: 14px; right: 14px; z-index: 3; display: grid; gap: 8px; }
.gallery__main {
  position: relative; background: var(--surface); border-radius: var(--r-lg); aspect-ratio: 1 / 1;
  display: grid; place-items: center; overflow: hidden;
}

/* Стрелки на фото: листать галерею, не целясь в миниатюру */
.gallery__nav {
  position: absolute; top: 50%; transform: translateY(-50%);
  width: 44px; height: 44px; padding: 0; border-radius: 50%;
  border: 1px solid var(--line-strong); background: rgba(255, 255, 255, .92);
  color: var(--ink); font: inherit; font-size: 1.5rem; line-height: 1;
  display: grid; place-items: center; cursor: pointer;
  transition: background .16s, border-color .16s;
}
.gallery__nav:hover { background: #fff; border-color: var(--ink); }
.gallery__nav--prev { left: 14px; }
.gallery__nav--next { right: 14px; }
.gallery__main img { cursor: zoom-in; }

/* Увеличение: снимок открывается во весь экран, листается там же */
.lightbox {
  position: fixed; inset: 0; z-index: 120; padding: 44px 76px;
  background: rgba(16, 16, 12, .97);      /* плотно: сквозь окно не должно быть видно стрелок карточки */
  display: grid; place-items: center;
}
.lightbox[hidden] { display: none; }
.lightbox img {
  max-width: 100%; max-height: calc(100vh - 96px);
  object-fit: contain; border-radius: 6px; background: var(--surface);
}
.lightbox__close {
  position: absolute; top: 16px; right: 20px; z-index: 2;
  width: 46px; height: 46px; padding: 0; border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, .45); background: transparent;
  color: #fff; font: inherit; font-size: 1.5rem; line-height: 1; cursor: pointer;
}
.lightbox__close:hover { background: rgba(255, 255, 255, .14); }
.lightbox__nav {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 2;
  width: 58px; height: 58px; padding: 0; border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, .6); background: rgba(255, 255, 255, .12);
  color: #fff; font: inherit; font-size: 2rem; line-height: 1; cursor: pointer;
}
.lightbox__nav:hover { background: rgba(255, 255, 255, .26); border-color: #fff; }
.lightbox__nav--prev { left: 18px; }
.lightbox__nav--next { right: 18px; }
/* Счётчик — видно, что листание работает и сколько всего снимков */
.lightbox__count {
  position: absolute; bottom: 16px; left: 50%; transform: translateX(-50%);
  color: rgba(255, 255, 255, .75); font-size: .88rem; letter-spacing: .02em;
}

@media (max-width: 700px) {
  .lightbox { padding: 26px 12px; }
  .lightbox img { max-height: calc(100vh - 60px); }
  .lightbox__nav { width: 44px; height: 44px; font-size: 1.5rem; }
  .lightbox__nav--prev { left: 8px; }
  .lightbox__nav--next { right: 8px; }
}
.gallery__main img { width: 74%; mix-blend-mode: multiply; }
.gallery__thumbs { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 14px; }
.gallery__thumbs div {
  width: 72px; height: 72px; border-radius: var(--r-sm); background: var(--surface);
  border: 1px solid var(--line); display: grid; place-items: center; overflow: hidden;
}
.gallery__thumbs div.on { border-color: var(--ink); }
.gallery__thumbs img { width: 80%; mix-blend-mode: multiply; }

.pdp h1 { font-size: clamp(1.5rem, 2.2vw, 2rem); }
/* Строку под заголовком переносим целыми кусками: раньше flex сжимал их,
   и «Арт. 049012» разрывалось на две строки, а разделители повисали по краям */
.pdp__top { display: flex; flex-wrap: wrap; align-items: baseline; color: var(--ink-3); font-size: .84rem; margin-top: 10px; line-height: 1.5; }
.pdp__top > span { white-space: nowrap; }
.pdp__top > span + span { margin-left: 6px; }
.pdp__top i { font-style: normal; margin-left: 6px; }

/* Ценовой блок: воздуха было больше, чем нужно — между ценой и строкой упаковки
   складывались два отступа (свой у строки и сеточный у блока), поля блока были
   крупные, а «за м» уезжало на другой край строки, оставляя пустоту посередине.
   Теперь цена и единица стоят рядом, отступы плотнее, а на правый край уходит
   только розница Arlight — она там действительно нужна для сравнения. */
.price-block { margin: 20px 0; padding: 18px 20px; background: var(--surface); border-radius: var(--r-md); display: grid; gap: 12px; }
.price-row { display: flex; align-items: baseline; flex-wrap: wrap; gap: 10px; }
.price-row b { font-size: 1.9rem; font-weight: 600; letter-spacing: -0.035em; }
.price-row s { color: var(--ink-3); font-size: .9rem; }
.price-row__retail { margin-left: auto; display: flex; align-items: baseline; gap: 6px; }

/* Цена и кнопка покупки в одну строку. У Arlight кнопка небольшая и стоит справа,
   а не во всю ширину блока: тогда рядом с ценой остаётся место для ссылок на
   доставку и оплату. После добавления в корзину под счётчиком появляется
   ссылка «Перейти в корзину» — как у них же */
.buy-top { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.buy-top .price-row { flex: 1 1 auto; }
/* Ширину строки покупки задаём жёстко: иначе её раздувает ссылка «Перейти в
   корзину» — она длиннее кнопки, и вместе со счётчиком строка уезжала до 260 px */
.buy-row { display: grid; gap: 8px; flex: none; width: 200px; }
.buy-row .btn { padding: 11px 16px; width: 100%; }
.buy-goto {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  font-size: .82rem; color: var(--ink-2); border-bottom: 1px solid transparent;
}
.buy-goto:hover { color: var(--ink); border-bottom-color: var(--accent); }
.buy-goto svg { color: var(--ink-3); flex: none; }
.buy-goto:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Доставка и оплата — короткими ссылками в том же блоке */
.pay-links { display: flex; flex-wrap: wrap; gap: 18px; }
.pay-links a { display: inline-flex; align-items: center; gap: 7px; font-size: .82rem; color: var(--ink-2); }
.pay-links a:hover { color: var(--ink); }
.pay-links svg { color: var(--ink-3); flex: none; }
.pay-links a:hover svg { color: var(--ink); }
.pay-links a:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.specs { margin-top: 34px; }
.specs table { width: 100%; border-collapse: collapse; font-size: .89rem; }
.specs td { padding: 11px 0; border-bottom: 1px solid var(--line); vertical-align: top; }
.specs td:first-child { color: var(--ink-3); width: 46%; }
.specs tr:last-child td { border-bottom: 0; }

.badges { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 14px; }
.badge { border: 1px solid var(--line-strong); border-radius: 4px; padding: 5px 9px; font-size: .76rem; color: var(--ink-2); }

/* Пояснение услуги «покраска по RAL» на карточке позиции */
.ral-note { margin-top: 14px; border: 1px solid var(--line); border-radius: 6px; padding: 10px 14px; font-size: .84rem; color: var(--ink-2); }
.ral-note summary { cursor: pointer; color: var(--ink); }
.ral-note summary:hover { border-bottom: 1px solid var(--accent); }
.ral-note__body { padding-top: 10px; }
.ral-note__body p { margin: 0 0 8px; }
.ral-note__body ul { margin: 0 0 8px; padding-left: 18px; }
.ral-note__body li { margin-bottom: 4px; }
.ral-note__body > :last-child { margin-bottom: 0; }

/* ---------- «дилерам» ---------- */

.dealer {
  background: var(--dark); color: #eceae5; border-radius: var(--r-lg);
  padding: 52px; display: grid; grid-template-columns: 1.1fr .9fr; gap: 48px; align-items: center;
}
.dealer h2 { color: #fff; }
.dealer .label { color: #8d8b85; }
.dealer ul { margin: 0; padding: 0; list-style: none; display: grid; gap: 14px; }
.dealer li { display: flex; gap: 12px; color: #c6c3bd; font-size: .93rem; }
.dealer li b { color: var(--accent); }
.dealer-form { background: var(--dark-2); border-radius: var(--r-md); padding: 26px; display: grid; gap: 12px; }
.dealer-form input, .dealer-form select {
  width: 100%; background: #23262b; border: 1px solid #33373d; color: #fff;
  border-radius: var(--r-sm); padding: 12px 14px; font: inherit; font-size: .89rem;
}
.dealer-form input::placeholder { color: #7c7f84; }

/* ---------- подвал ---------- */

.footer { background: var(--dark); color: #a9a7a1; padding: 56px 0 40px; margin-top: 20px; }
/* Приглушённый текст в подвале был цветом страницы (#55554c) — тёмное на
   тёмном, 2,4:1: подпись «Shift+Alt+E» у формы отчёта читалась плохо */
.footer .muted { color: #a9a7a1; }
.footer a:hover { color: #fff; }
.footer-grid { display: grid; grid-template-columns: 1.4fr 1fr 1fr 1fr; gap: 40px; }
.footer .brand { color: #fff; }
.footer h4 { color: #fff; font-size: .82rem; text-transform: uppercase; letter-spacing: .1em; font-weight: 500; margin: 0 0 16px; }
.footer ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; font-size: .89rem; }
.footer-bottom { margin-top: 44px; padding-top: 22px; border-top: 1px solid #2a2d32; display: flex; gap: 24px; font-size: .8rem; flex-wrap: wrap; }

/* ---------- служебное ---------- */

.cookie {
  position: fixed; left: 24px; bottom: 24px; z-index: 60;
  background: var(--ink); color: #efece6;
  border-radius: var(--r-md); padding: 16px 18px; max-width: 430px;
  display: grid; gap: 12px; font-size: .85rem;
  box-shadow: 0 24px 50px -24px rgba(0,0,0,.5);
}
.skip {
  position: absolute; left: -9999px; top: 0;
  background: var(--ink); color: #fff; padding: 12px 18px; z-index: 100;
  border-radius: 0 0 var(--r-sm) 0;
}
.skip:focus { left: 0; }

/* ---------- адаптив ---------- */

/* Строка инструментов каталога: «Найдено», «Сетка / Списком», сортировка и
   размер страницы стоят одной строкой и ниже 713 px уже не влезали. Из-за них
   колонка каталога растягивалась до 669 px, и страница была шире экрана на 313 —
   за ней тянулись панель фильтров, сетка плиток и окно быстрого просмотра
   (в нём крестик и «В корзину» уезжали за край). Разрешаем перенос: там, где
   места хватает, вид не меняется. */
@media (max-width: 980px) {
  .toolbar { flex-wrap: wrap; }
  .toolbar .push { margin-left: 0; flex-wrap: wrap; }
}

@media (max-width: 1200px) {
  .products { grid-template-columns: repeat(3, 1fr); }
  .cat-grid { grid-template-columns: repeat(3, 1fr); }
  .catalog-layout { grid-template-columns: 250px 1fr; gap: 30px; }
}
@media (max-width: 980px) {
  .wrap { padding: 0 22px; }
  .hero-grid, .pdp, .filebox, .dealer, .footer-grid { grid-template-columns: 1fr; }
  .products { grid-template-columns: repeat(2, 1fr); }
  .cat-grid { grid-template-columns: repeat(2, 1fr); }
  .cat-list { grid-template-columns: 1fr; }
  .catalog-layout { grid-template-columns: 1fr; }
  .nav, .topbar { display: none; }
  .section, .filebox__text, .filebox__drop, .dealer { padding-left: 22px; padding-right: 22px; }
}

/* ============================================================
   Фирменный слой «Светосистемы».
   Палитра бренда: жёлтый #f8c000, чёрный #181810, белый #f8f8f8.
   Правило контраста: жёлтый работает только как ФОН под тёмным текстом.
   Как цвет текста на белом он даёт около 1,7:1 и не годится —
   поэтому ссылки и заголовки остаются чёрными, а жёлтый идёт
   в подчёркивание, плашки и заливки.
   ============================================================ */

:root {
  --bg: #f8f8f8;
  --surface: #ffffff;
  --field: #f1f1ed;
  --ink: #181810;
  --ink-2: #55554c;
  /* Приглушённый текст: #8a8a80 давал 3,0–3,5:1 — ниже нормы 4,5:1 для
     мелкого текста (артикул в плитке, счётчик у значения фильтра, подписи
     характеристик, выключенные строки). #6d6d66 даёт 4,6:1 на поле, 4,9:1
     на фоне страницы, 5,2:1 на белом */
  --ink-3: #6d6d66;
  --line: #e3e3dd;
  --line-strong: #c9c9c2;
  --accent: #f8c000;
  --accent-ink: #181810;
  --accent-soft: #fdf3cf;
  --dark: #181810;
  --dark-2: #24241b;
  --ok: #f8c000;
}

/* Логотип: знак и надпись отдельными файлами, чтобы шапка и подвал
   могли брать чёрную или белую версию без пересборки картинок. */
.brand { display: inline-flex; align-items: center; }
.brand img { display: block; height: 40px; width: auto; }

/* Ссылки и акценты: чёрный текст, жёлтое подчёркивание */
.link-accent {
  color: var(--ink);
  border-bottom: 2px solid var(--accent);
  transition: background .16s;
}
.link-accent:hover { background: var(--accent-soft); }
.nav a.on { border-bottom: 3px solid var(--accent); }
.crumbs a:hover { color: var(--ink); border-bottom: 1px solid var(--accent); }
.cat-list a:hover { color: var(--ink); border-bottom: 2px solid var(--accent); }

/* Кнопки: основная — чёрная, акцентная — фирменный жёлтый с чёрным текстом */
.btn.accent { background: var(--accent); color: var(--accent-ink); }
.btn.accent:hover { background: #e3ae00; }
.btn:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }

/* Флажки, чипы, пометки — жёлтая заливка */
.check input:checked { background: var(--accent); border-color: var(--accent); }
.check input:checked::after { border-color: var(--accent-ink); }
.chip { background: var(--accent); color: var(--accent-ink); }
.pcard__flag.new { background: var(--accent); color: var(--accent-ink); }
/* Ярлык скидки акции «30 лет света»: тёмная плашка с фирменной жёлтой цифрой.
   Жёлтую заливку покупатель уже знает по «Новинке», и две одинаковые плашки в
   стопке читались бы как одна и та же метка. Жёлтый на тёмном даёт 11:1 —
   норма для мелкого текста 4,5:1 (жёлтый как цвет текста на белом запрещён) */
.pcard__flag.sale { background: var(--ink); color: var(--accent); }

/* Первый экран: светильник на фирменном жёлтом поле */
.hero-scene { background: linear-gradient(155deg, #f8c000 0%, #edb800 55%, #dca900 100%); }
.hero-scene::after {
  background: radial-gradient(44% 36% at 52% 42%, rgba(255, 255, 255, .5) 0%, rgba(255, 255, 255, 0) 72%);
}
.hero-scene img { filter: drop-shadow(0 30px 44px rgba(60, 42, 0, .32)); }

/* Панель заказа по файлу — жёлтый блок как в фирменных материалах */
.filebox__drop { background: var(--accent); }
.drop-slot { border-color: rgba(24, 24, 16, .35); background: rgba(255, 255, 255, .55); }

/* Преимущества: жёлтая линия сверху вместо чёрной */
.advantage { border-top: 3px solid var(--accent); }

/* Партнёрский блок: жёлтые маркеры на чёрном */
.dealer li b { color: var(--accent); }

/* Страница товара: акцентная цена */
.price-row b { letter-spacing: -0.035em; }
.price-block { border-left: 5px solid var(--accent); }

/* ---------- вкладки под карточкой товара ----------
   Описание, характеристики, аксессуары и совместимые раньше шли подряд одной
   колонкой: карточка вырастала до полутора тысяч пикселей, между блоками
   оставалось пустое место, а длинные списки аксессуаров приходилось обрезать.
   Теперь они за вкладками — как у Arlight: карточка короткая, а всё остальное
   открывается по нажатию и может быть любой длины. */
.p-tabs__bar { display: flex; flex-wrap: wrap; gap: 26px; border-bottom: 1px solid var(--line); }
/* Верхний отступ секции меньше обычного: карточка и вкладки — один смысловой
   блок, шестьдесят пикселей пустоты между ними читались как разрыв */
.p-tabs { padding-top: 44px; }
.p-tabs__bar button {
  border: 0; background: transparent; cursor: pointer; position: relative;
  padding: 12px 0 14px; font: inherit; font-size: .95rem; color: var(--ink-3);
  transition: color .16s;
}
.p-tabs__bar button:hover { color: var(--ink); }
.p-tabs__bar button.on { color: var(--ink); font-weight: 500; }
.p-tabs__bar button.on::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -1px; height: 3px;
  background: var(--accent);
}
.p-tabs__bar button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.p-tabs__bar button span { margin-left: 7px; color: var(--ink-3); font-size: .82rem; }
.p-tabs__panel { padding-top: 26px; }

/* Подвал и шапка: логотип в белой версии */
.footer .brand img { height: 34px; }
.topbar .dot { background: var(--accent); }

/* ============================================================
   Первый экран под проектную поставку: главное действие —
   загрузка спецификации, рядом честные наличие и сроки.
   ============================================================ */

.hero-actions { display: grid; gap: 14px; margin-top: 28px; max-width: 580px; }

.drop-inline {
  display: flex; align-items: center; gap: 16px;
  background: var(--accent); color: var(--accent-ink);
  border-radius: var(--r-md); padding: 18px 20px;
  cursor: pointer;
  transition: background .18s cubic-bezier(.2,.7,.3,1), transform .18s;
}
.drop-inline:hover { background: #e3ae00; }
.drop-inline:active { transform: translateY(1px); }
.drop-inline:focus-within { outline: 2px solid var(--ink); outline-offset: 3px; }
.drop-inline__icon {
  width: 40px; height: 40px; flex: none; border-radius: 50%;
  background: rgba(24, 24, 16, .12);
  display: grid; place-items: center; font-size: 1.35rem; line-height: 1;
}
.drop-inline b { display: block; font-size: 1.04rem; font-weight: 600; letter-spacing: -0.01em; }
.drop-inline em { font-style: normal; font-size: .82rem; opacity: .75; }

/* Панель «наличие и сроки» справа */
.terms { background: var(--surface); border-radius: var(--r-lg); padding: 30px 30px 26px; }
.terms ul { list-style: none; margin: 16px 0 22px; padding: 0; display: grid; gap: 0; }
.terms li {
  padding: 14px 0; border-bottom: 1px solid var(--line);
  font-size: .9rem; color: var(--ink-2);
}
.terms li:first-child { padding-top: 0; }
.terms li:last-child { border-bottom: 0; }
.terms li b { display: block; color: var(--ink); font-weight: 500; margin-bottom: 4px; }

/* Палитра RAL на странице услуг */
.ral-tone { margin-top: 26px; }
.ral-tone h3 { font-size: .98rem; margin: 0 0 12px; }
.ral-tone h3 em { font-style: normal; font-weight: 400; font-size: .8rem; color: var(--ink-3); margin-left: 7px; }
.ral-grid { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(224px, 1fr)); gap: 10px 20px; }
.ral-grid li { display: flex; align-items: center; gap: 9px; font-size: .82rem; color: var(--ink-2); min-width: 0; }
.ral-grid i { width: 20px; height: 20px; border-radius: 4px; border: 1px solid var(--line-strong); flex: none; }
.ral-grid b { font-weight: 500; color: var(--ink); }
.ral-grid span { color: var(--ink-3); }

/* Полный набор характеристик на карточке позиции: живёт во вкладке
   «Характеристики», а в колонке сведений на него ведёт ссылка */
#p-all-body .label { margin: 20px 0 6px; }
#p-all-body .label:first-child { margin-top: 0; }
#p-all-body table { width: 100%; border-collapse: collapse; font-size: .89rem; }
#p-all-body td { padding: 11px 0; border-bottom: 1px solid var(--line); vertical-align: top; }
#p-all-body td:first-child { color: var(--ink-3); width: 46%; }
/* Полный набор — тремя колонками, как на витрине поставщика: иначе вкладка
   растягивается далеко вниз. Группа характеристик не рвётся между колонками;
   на узком экране колонок меньше, чтобы подписи и значения не сжимались */
.spec-cols { columns: 3; column-gap: 40px; }
.spec-group { break-inside: avoid; margin: 0 0 24px; }
.spec-group .label { margin: 0 0 4px; }
@media (max-width: 980px) { .spec-cols { columns: 2; } }
@media (max-width: 620px) { .spec-cols { columns: 1; } }
.specs-all {
  display: inline-block; margin-top: 18px; font-size: .93rem; color: var(--ink);
  border-bottom: 1px solid var(--accent);
}
.specs-all:hover { border-bottom-color: var(--ink); }
.specs-all:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

@media (max-width: 980px) {
  .hero-actions { max-width: none; }
}

/* ============================================================
   Дерево каталога: разделы с подкатегориями.
   ============================================================ */

.quick { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 34px; }
.quick a {
  border: 1px solid var(--line); background: var(--surface);
  border-radius: 999px; padding: 8px 14px; font-size: .85rem; color: var(--ink-2);
  transition: border-color .16s, color .16s;
}
.quick a:hover { border-color: var(--ink); color: var(--ink); }

.tree-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 0 60px; }

.tree-block { padding: 26px 0; border-top: 1px solid var(--line); }
.tree-block__head { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; }
.tree-block__head h2 { font-size: 1.2rem; letter-spacing: -0.02em; }

.tree-subs { display: grid; margin: 14px 0 12px; }
.tree-subs a {
  display: flex; justify-content: space-between; gap: 14px;
  padding: 8px 0; font-size: .9rem; color: var(--ink-2);
  border-bottom: 1px dashed var(--line);
  transition: color .16s;
}
.tree-subs a:last-child { border-bottom: 0; }
.tree-subs a:hover { color: var(--ink); }
.tree-subs em { font-style: normal; color: var(--ink-3); font-size: .82rem; }

.tree-all { font-size: .85rem; border-bottom: 2px solid var(--accent); }

@media (max-width: 980px) {
  .tree-grid { grid-template-columns: 1fr; gap: 0; }
}

/* На жёлтой панели жёлтая кнопка не видна: делаем её тёмной,
   а серый текст заменяем на приглушённый чёрный — иначе контраст низкий. */
.filebox__drop .btn.accent { background: var(--ink); color: #fff; }
.filebox__drop .btn.accent:hover { background: #000; }
.filebox__drop .muted { color: rgba(24, 24, 16, .68); }

/* Параметры прямо в карточке списка: мощность, температура, защита */
.pcard__specs { display: flex; flex-wrap: wrap; gap: 6px; }
.pcard__specs span {
  font-size: .74rem; color: var(--ink-2);
  border: 1px solid var(--line); border-radius: 4px; padding: 3px 7px;
}
/* Плашка цвета у «Цветовой температуры»: цвет считает kelvinColor (lists.js) —
   палитра Arlight из фильтра «Цвет свечения». Стоит у значения в плитке,
   в пилюлях фильтра и в таблице характеристик карточки */
.k-sw {
  display: inline-block; width: 12px; height: 12px; border-radius: 3px;
  border: 1px solid rgba(0, 0, 0, .12); flex: none; vertical-align: -1px;
}
/* «MIX» — плашка диапазона: три полосы читаются в 16 px, в 12 сливались бы */
.k-sw--mix { width: 16px; }
.pcard__specs .k-sw { margin-right: 7px; }
#p-specs .k-sw { margin-right: 9px; }

/* ============================================================
   Шапка в фирменном жёлтом — как на бланках и визитках:
   чёрный знак с белой штриховкой на жёлтом поле.
   ============================================================ */

.header { background: var(--accent); border-bottom-color: transparent; }
.header .nav a { color: rgba(24, 24, 16, .72); }
.header .nav a:hover { color: var(--ink); }
.header .nav a.on { color: var(--ink); border-bottom-color: var(--ink); }
.header .search-inline { border-color: transparent; background: var(--surface); }
.header .search-inline:focus-within { border-color: var(--ink); }
.header .btn.ghost { border-color: rgba(24, 24, 16, .4); color: var(--ink); }
.header .btn.ghost:hover { border-color: var(--ink); background: transparent; }
.header .brand img { height: 42px; }

/* Компактный указатель спецификации вместо большой кнопки в шапке */
.head-spec {
  position: relative; width: 40px; height: 40px; flex: none;
  border-radius: var(--r-sm); display: grid; place-items: center;
  border: 1px solid rgba(24, 24, 16, .4); color: var(--ink);
  transition: border-color .16s, background .16s;
}
.head-spec:hover { border-color: var(--ink); }
.head-spec:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.head-spec__count {
  position: absolute; top: -7px; right: -7px;
  min-width: 19px; height: 19px; padding: 0 5px;
  background: var(--ink); color: #fff;
  border-radius: 10px; font-size: .68rem; font-weight: 500;
  display: grid; place-items: center;
}

/* Значок без подписи оказался непонятен: делаем ссылку со словом и счётчиком. */
.head-spec {
  width: auto; height: auto; border: 0; padding: 8px 0;
  display: inline-flex; align-items: center; gap: 7px;
  font-size: .88rem; color: var(--ink);
}
.head-spec:hover { border-color: transparent; text-decoration: underline; text-underline-offset: 4px; }
.head-spec__count {
  position: static; min-width: 20px; height: 20px; padding: 0 6px;
  border-radius: 10px; background: var(--ink); color: #fff;
  font-size: .72rem; font-weight: 500; display: grid; place-items: center;
}

/* ============================================================
   Единая левая граница контента.
   В файле есть правила .hero и .section с краткой записью
   padding: 76px 0 — она обнуляла горизонтальные отступы .wrap,
   поэтому шапка и содержимое страницы стояли на разной границе.
   ============================================================ */

.wrap { padding-left: 32px; padding-right: 32px; }
.hero.wrap,
.section.wrap { padding-left: 32px; padding-right: 32px; }

@media (max-width: 980px) {
  .hero.wrap,
  .section.wrap { padding-left: 22px; padding-right: 22px; }
}

/* Корзина значком: тележка узнаётся без подписи, счётчик — кружком сверху */
.head-spec {
  position: relative;
  display: inline-grid; place-items: center;
  width: 42px; height: 42px; padding: 0;
  border: 1px solid rgba(24, 24, 16, .4); border-radius: var(--r-sm);
  color: var(--ink); text-decoration: none;
  transition: border-color .16s, background .16s;
}
.head-spec:hover { border-color: var(--ink); text-decoration: none; }
.head-spec:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.head-spec svg { display: block; }
.head-spec__count {
  position: absolute; top: -7px; right: -7px;
  min-width: 19px; height: 19px; padding: 0 5px; margin: 0;
  border-radius: 10px; background: var(--ink); color: #fff;
  font-size: .68rem; font-weight: 500; line-height: 1;
  display: grid; place-items: center;
}

/* ============================================================
   Выбор города в верхней строке.
   От города зависят контакты, склад и условия доставки.
   Сделано на <details>, поэтому работает и без JavaScript.
   ============================================================ */

.topbar { position: relative; z-index: 60; }

.city { position: relative; }
.city > summary {
  list-style: none; cursor: pointer; color: #b9b7b1;
  display: inline-flex; align-items: center; gap: 7px;
  padding: 4px 0; transition: color .16s;
}
.city > summary::-webkit-details-marker { display: none; }
.city > summary:hover { color: #fff; }
.city > summary::after {
  content: ""; width: 6px; height: 6px; margin-left: 3px;
  border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg) translate(-1px, -1px);
}
.city[open] > summary { color: #fff; }

.city__menu {
  position: absolute; top: calc(100% + 12px); left: 0; z-index: 70;
  background: var(--surface); color: var(--ink);
  border-radius: var(--r-sm); min-width: 280px; padding: 6px;
  display: grid; gap: 2px;
  box-shadow: 0 20px 44px -20px rgba(0, 0, 0, .5);
}
.city__menu a {
  display: grid; gap: 3px; padding: 10px 12px; border-radius: 4px;
  font-size: .88rem; color: var(--ink);
}
.city__menu a:hover { background: var(--field); }
.city__menu a.on { background: var(--accent-soft); }
.city__menu em { font-style: normal; font-size: .76rem; color: var(--ink-3); }

.topbar__note { margin-left: -14px; color: #8d8b85; font-size: .78rem; }

/* ============================================================
   Страница «Сотрудничество»: сегменты, шаги, форма заявки.
   ============================================================ */

.seg-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 24px; margin: 34px 0 0; }

.seg {
  background: var(--surface); border-radius: var(--r-md);
  padding: 26px 28px 24px; display: flex; flex-direction: column;
}
.seg h2 { font-size: 1.14rem; letter-spacing: -0.02em; }
.seg > p { margin: 10px 0 18px; }
.seg ul { list-style: none; margin: 0 0 22px; padding: 0; display: grid; gap: 11px; }
.seg li { position: relative; padding-left: 22px; font-size: .9rem; color: var(--ink-2); }
.seg li::before {
  content: ""; position: absolute; left: 0; top: .62em;
  width: 9px; height: 2px; background: var(--accent);
}
.seg .link-accent { margin-top: auto; align-self: flex-start; }

.collab-layout { display: grid; grid-template-columns: 1.05fr .95fr; gap: 56px; align-items: start; }

.steps4 { display: grid; gap: 20px; }
.steps4 > div { display: flex; gap: 14px; align-items: flex-start; font-size: .92rem; color: var(--ink-2); }
.steps4 > div > b {
  flex: none; width: 28px; height: 28px; border-radius: 50%;
  background: var(--accent); color: var(--accent-ink);
  display: grid; place-items: center; font-size: .82rem; font-weight: 600;
}
.steps4 span b { color: var(--ink); font-weight: 500; }

.pform {
  background: var(--surface); border-radius: var(--r-lg);
  padding: 26px 28px 24px; display: grid; gap: 14px;
}
.pform__row { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.pform label { display: grid; gap: 6px; font-size: .82rem; color: var(--ink-3); }
.pform input, .pform select, .pform textarea {
  width: 100%; border: 1px solid var(--line); border-radius: var(--r-sm);
  background: var(--bg); padding: 11px 13px;
  font: inherit; font-size: .9rem; color: var(--ink); resize: vertical;
}
.pform input:focus, .pform select:focus, .pform textarea:focus {
  outline: none; border-color: var(--ink); background: var(--surface);
}
.pform .check-row { display: flex; align-items: flex-start; gap: 10px; font-size: .82rem; color: var(--ink-2); }
.pform .check-row input { width: auto; margin-top: 2px; }

@media (max-width: 980px) {
  .seg-grid, .collab-layout, .pform__row { grid-template-columns: 1fr; }
  .collab-layout { gap: 34px; }
}

/* Сетка преимуществ: без неё блок .advantage-grid оставался обычным контейнером
   и пункты вставали в столбик вместо четырёх колонок. */
.advantage-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--gap); }

@media (max-width: 1200px) {
  .advantage-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 980px) {
  .advantage-grid { grid-template-columns: 1fr; gap: 26px; }
}

/* ============================================================
   Слайдер направлений под первым экраном.
   Без библиотек: горизонтальная прокрутка со снапом.
   Работает пальцем и колесом даже без JavaScript, стрелки и точки —
   надстройка сверху.
   ============================================================ */

.slider { margin: 0; }
.slider__track {
  display: flex; gap: 24px;
  overflow-x: auto; scroll-snap-type: x mandatory;
  scrollbar-width: none; -ms-overflow-style: none;
}
.slider__track::-webkit-scrollbar { display: none; }

.slide {
  flex: 0 0 100%; scroll-snap-align: start;
  background: var(--surface); border-radius: var(--r-lg);
  display: grid; grid-template-columns: 1.05fr .95fr;
  align-items: center; gap: 48px; padding: 40px 48px;
  min-height: 360px;
}
.slide__text { max-width: 48ch; }
.slide__text h2 { font-size: clamp(1.35rem, 2.1vw, 1.85rem); margin: 12px 0 14px; }
.slide__text p { color: var(--ink-2); margin: 0; }
.slide__text .btn { margin-top: 24px; }
.slide__media {
  background: var(--field); border-radius: var(--r-md);
  height: 288px; display: grid; place-items: center; overflow: hidden;
}
.slide__media img { max-height: 84%; width: auto; mix-blend-mode: multiply; }

.slider__nav { display: flex; align-items: center; gap: 16px; margin-top: 18px; }
.slider__arrow {
  width: 42px; height: 42px; flex: none; border-radius: var(--r-sm);
  border: 1px solid var(--line-strong); background: transparent;
  color: var(--ink); display: grid; place-items: center; font-size: 1rem;
  transition: border-color .16s, background .16s;
}
.slider__arrow:hover { border-color: var(--ink); }
.slider__arrow:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.slider__dots { display: flex; gap: 8px; }
.slider__dot {
  width: 28px; height: 3px; padding: 0; border: 0; border-radius: 2px;
  background: var(--line-strong); cursor: pointer; transition: background .16s;
}
.slider__dot.on { background: var(--ink); }

@media (max-width: 980px) {
  .slide { grid-template-columns: 1fr; gap: 22px; padding: 24px 22px; min-height: 0; }
  .slide__media { height: 200px; }
  .slide__text .btn { margin-top: 18px; }
}

/* ============================================================
   Слайдер стал фотографическим: кадр во всю ширину, текст поверх него
   с затемнением снизу. Перебивает прежнюю карточную вёрстку слайда.
   ============================================================ */

.slide {
  position: relative; display: flex; align-items: flex-end;
  flex: 0 0 100%; scroll-snap-align: start;
  min-height: 440px; padding: 0; background: none;
  border-radius: var(--r-lg); overflow: hidden;
  grid-template-columns: none;
}
.slide__img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; z-index: 0;
}
.slide::after {
  content: ""; position: absolute; inset: 0; z-index: 1;
  background: linear-gradient(180deg, rgba(19, 21, 24, 0) 30%, rgba(19, 21, 24, .55) 65%, rgba(19, 21, 24, .88) 100%);
}
.slide__text { position: relative; z-index: 2; padding: 44px 48px; max-width: 66ch; }
.slide__text .label { color: rgba(255, 255, 255, .68); }
.slide__text h2 { color: #fff; font-size: clamp(1.5rem, 2.6vw, 2.15rem); margin: 12px 0 12px; }
.slide__text p { color: rgba(255, 255, 255, .84); margin: 0; }
.slide__text .btn { margin-top: 24px; background: var(--accent); color: var(--accent-ink); }
.slide__text .btn:hover { background: #e3ae00; }

@media (max-width: 980px) {
  .slide { min-height: 380px; }
  .slide__text { padding: 26px 22px; }
}

/* ============================================================
   Панель «Компания» в меню: второстепенные страницы собраны в одном
   месте, чтобы шапка не разрасталась. На <details> — работает без JS.
   ============================================================ */

.nmenu { position: relative; }
.nmenu > summary {
  list-style: none; cursor: pointer; color: rgba(24, 24, 16, .72);
  padding: 4px 0; font-size: .92rem;
  /* flex, а не inline-flex: строчный бокс встаёт на строку родителя и опускает
     текст на 4 пикселя ниже обычных ссылок меню — «Каталог» выбивался из ряда */
  display: flex; align-items: center; gap: 7px;
  transition: color .16s;
}
.nmenu > summary::-webkit-details-marker { display: none; }
.nmenu > summary::after {
  content: ""; width: 5px; height: 5px; margin-top: -2px;
  border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg);
}
.nmenu > summary:hover { color: var(--ink); }
.nmenu[open] > summary { color: var(--ink); }
.nmenu > summary:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; border-radius: 2px; }

.nmenu__panel {
  position: absolute; top: calc(100% + 18px); left: -12px; z-index: 70;
  background: var(--surface); border-radius: var(--r-sm); padding: 8px;
  min-width: 252px; display: grid; gap: 2px;
  box-shadow: 0 20px 44px -20px rgba(0, 0, 0, .45);
}
.nmenu__panel a {
  padding: 10px 12px; border-radius: 4px;
  font-size: .88rem; color: var(--ink);
}
.nmenu__panel a:hover { background: var(--field); }
.nmenu__panel a.on { background: var(--accent-soft); }
/* Панель появляется тем же шагом, что и колонка подразделов: рывок на 600
   пикселей вниз выглядел резко (заказчик 14.10.2026) */
.nmenu[open] > .nmenu__panel { animation: nmenu-in .18s ease-out; }
@keyframes nmenu-in { from { opacity: 0; transform: translateY(-6px); } }

/* «Каталог»: в заголовке лежит ссылка на дерево каталога — по клику уходим на
   страницу, по наведению открывается список разделов. Ссылка должна выглядеть
   как остальные пункты шапки, а не как ссылка внутри строки. */
.nmenu > summary a { color: inherit; text-decoration: none; padding: 0; }
/* Ссылка внутри заголовка не должна получать отступ пункта меню: он складывался
   с отступом самого summary, и «Каталог» вставал на 4 пикселя ниже соседей */
/* Список из 12 разделов выше остальных панелей: подгоняем его под свободное место
   под шапкой и делаем пункты чуть плотнее, иначе на невысоком экране панель
   упирается в край и уезжает в прокрутку со срезанным последним пунктом */
.nmenu__panel--catalog { min-width: 300px; padding: 6px 0; }
.nmenu__panel--catalog a { padding: 9px 12px; }
/* Подразделы выпадают колонкой справа при наведении на раздел: держать все 145
   подпунктов развёрнутыми — простыня на несколько экранов. Колонка привязана к
   строке (не к панели): иначе у нижних строк она открывалась вверху панели, и
   мышью до неё было не дотянуться — по дороге курсор уходил с раздела, и
   колонка закрывалась (заказчик 14.10.2026). Положение по вертикали доводит
   скрипт (assets/header-menu.js): вровень со строкой, а если вниз не влезает —
   поднимает так, чтобы поле колонки всё равно накрывало строку. Боковых
   отступов у панели нет — колонка стыкуется с пунктом вплотную */
.nmenu__sec { position: relative; }
.nmenu__sec-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.nmenu__sec-head::after {
  content: ""; width: 5px; height: 5px; flex: none; opacity: .45;
  border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
  transform: rotate(-45deg);
}
.nmenu__sec:hover > .nmenu__sec-head { background: var(--field); }
/* Колонка подразделов: тот же фон, те же отступы и та же плашка при наведении,
   что у панели разделов, — иначе колонка читается «чужой» (заказчик 14.10.2026).
   Боковых отступов нет, как у .nmenu__panel--catalog: плашка наведения идёт от
   края до края, а не врезается в поле колонки */
.nmenu__subs {
  position: absolute; left: 100%; top: 0; z-index: 2;
  display: none; grid-auto-rows: min-content; gap: 1px;
  min-width: 280px; max-width: 360px; max-height: calc(100vh - 150px);
  overflow: auto; padding: 6px 0; border-radius: var(--r-sm);
  background: var(--surface);
  box-shadow: 0 20px 44px -20px rgba(0, 0, 0, .45);
}
.nmenu__sec:hover > .nmenu__subs,
.nmenu__sec:focus-within > .nmenu__subs { display: grid; animation: nmenu-subs-in .18s ease-out; }
/* Появление и панели, и колонки — с одним шагом: мгновенный «прыжок» на 600
   пикселей выглядел резко. Анимация на смене display запускается сама, поэтому
   ни классов, ни скрипта для этого не нужно */
@keyframes nmenu-subs-in { from { opacity: 0; transform: translateX(-6px); } }
.nmenu__subs a { padding: 7px 12px; font-size: .82rem; color: var(--ink-2); border-radius: 4px; }
.nmenu__subs a:hover { background: var(--field); color: var(--ink); }
/* «Весь каталог» — не раздел, а выход в дерево: отделяем чертой */
.nmenu__all { margin-top: 6px; border-top: 1px solid var(--line); padding-top: 12px; color: var(--ink-2); }

/* Слайдер теперь первый блок под шапкой: секция была без верхнего отступа,
   задаём воздух, чтобы кадр не лип к жёлтой полосе. */
.slider { margin-top: 44px; }

@media (max-width: 980px) {
  .slider { margin-top: 22px; }
}

/* ============================================================
   Управление слайдером: точки прямо на фотографии, стрелок внизу нет.
   Точки полупрозрачные, активная — белая, чтобы не спорить с кадром.
   ============================================================ */

.slider { position: relative; }

.slider__dots {
  position: absolute; right: 34px; bottom: 26px; z-index: 3;
  display: flex; gap: 8px; margin: 0;
}
.slider__dot {
  width: 26px; height: 3px; padding: 0; border: 0; border-radius: 2px;
  background: rgba(255, 255, 255, .38); cursor: pointer;
  transition: background .2s, transform .2s;
}
.slider__dot:hover { background: rgba(255, 255, 255, .72); }
.slider__dot.on { background: #fff; }
.slider__dot:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }

/* Стрелки больше не нужны */
.slider__nav { display: none; }

@media (max-width: 980px) {
  .slider__dots { right: 22px; bottom: 16px; }
}


/* ============================================================
   Корзина и заявка.
   «Корзина» — список позиций на сайте, «спецификация» — файл клиента.
   ============================================================ */

.cart-layout {
  display: grid; grid-template-columns: 1.4fr .6fr; gap: 40px;
  align-items: start; padding-bottom: 34px;
}

/* --- список позиций --- */
.cart-list {
  background: var(--surface); border-radius: var(--r-lg);
  padding: 6px 26px 10px;
}
.cart-list__head {
  display: flex; align-items: baseline; gap: 10px 16px; flex-wrap: wrap;
  padding: 20px 0 16px; border-bottom: 1px solid var(--line);
}
.cart-list__head .check { padding: 0; }
.cart-list__head b { font-size: 1.02rem; font-weight: 600; }
.cart-list__head .push { margin-left: auto; }

.cart-row {
  display: grid;
  grid-template-columns: 22px 22px 92px minmax(0, 1fr) 128px 156px 34px;
  gap: 18px; align-items: center;
  padding: 20px 0; border-bottom: 1px solid var(--line);
  transition: background-color .12s ease;
}
.cart-row:last-child { border-bottom: 0; }
/* Галочка «оформить эту позицию»: первая колонка строки. Остальное оформление
   берём у .check — та же галочка, что в фильтрах каталога */
.cart-row__pick { padding: 0; justify-content: center; }
/* Позиция без отметки: в заявку не идёт, и это видно сразу — фото и подписи
   приглушены, но строка остаётся рабочей: количество и порядок меняются */
.cart-row.is-off .cart-row__media,
.cart-row.is-off .cart-row__info { opacity: .5; }
/* Куда встанет позиция при переносе: саму строку под курсором притемняем —
   это видно сразу, без оглядки на край. Тонкая полоска акцентом осталась
   подсказкой, встанет позиция выше строки или ниже (серединная линия). */
.cart-row.is-dragging { opacity: .45; }
.cart-row.is-over-above, .cart-row.is-over-below { background: rgba(139, 138, 132, .09); }
.cart-row.is-over-above { box-shadow: inset 0 2px 0 var(--accent); }
.cart-row.is-over-below { box-shadow: inset 0 -2px 0 var(--accent); }
/* Стрелки порядка: закупщик сам выстраивает список под спецификацию.
   На краях списка стрелка выключена — понятно, что дальше двигать некуда. */
.cart-row__move { display: grid; gap: 2px; justify-items: center; }
.cart-row__move button {
  width: 22px; height: 22px; padding: 0; border: 0; border-radius: 5px;
  background: transparent; color: var(--ink-3); cursor: pointer;
  display: grid; place-items: center;
}
.cart-row__move svg { width: 13px; height: 13px; }
.cart-row__move button:hover:not(:disabled) { background: var(--field); color: var(--ink); }
.cart-row__move button:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.cart-row__move button:disabled { opacity: .22; cursor: default; }
/* Ручка переноса — между стрелками: тянуть строку можно только за неё, поэтому
   «лапка» появляется здесь и нигде больше. Полоски рисуем линиями, чтобы ручка
   не спорила со стрелками по весу. */
.cart-row__grip {
  width: 22px; height: 14px; border-radius: 5px; cursor: grab;
  display: grid; align-content: center; gap: 2px; justify-items: center;
}
.cart-row__grip i { width: 11px; height: 1.5px; background: var(--ink-3); border-radius: 1px; }
.cart-row__grip:hover { background: var(--field); }
.cart-row__grip:hover i { background: var(--ink); }
.cart-row__grip:active, .cart-row.is-dragging .cart-row__grip { cursor: grabbing; }
.cart-row__media {
  width: 92px; height: 92px; border-radius: var(--r-sm); background: var(--field);
  overflow: hidden; display: grid; place-items: center;
}
.cart-row__media img { width: 100%; height: 100%; object-fit: contain; padding: 8px; mix-blend-mode: multiply; }
/* Фото — ссылка: клик открывает кадр во весь экран (наведение показывает
   подсказку рядом). Ссылке нужен размер, иначе проценты картинки от неё не
   считаются, и она схлопывается в ноль */
.cart-row__media a { display: block; width: 100%; height: 100%; }
.cart-row__name { font-size: .95rem; line-height: 1.36; letter-spacing: -0.01em; }
.cart-row__name:hover { border-bottom: 1px solid var(--accent); }
/* Подпись под названием — как в списке каталога: бренд и серия. Ссылки берут
   свои цвета из общего .brand-link/.serie-link, здесь только кегль и отступ. */
.cart-row__brand { font-size: .78rem; margin-top: 5px; color: var(--ink-3); }
.cart-row__meta { color: var(--ink-3); font-size: .78rem; margin-top: 7px; }
/* Артикул здесь — кнопка копирования (её ставит art-copy.js): цифры должны
   стоять ровно, как стояли в .mono до неё */
.cart-row__meta .art-copy { font-variant-numeric: tabular-nums; }
/* Наличие — единственный сигнал в корзине, которому нужен «зелёный свет»:
   в фирменной палитре --ok тоже жёлтый, и «в наличии» сливалось с акцентом. */
.cart-row__stock { display: inline-flex; align-items: center; gap: 6px; font-size: .78rem; color: #2f7d4f; margin-top: 7px; }
.cart-row__stock::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.cart-row__stock.wait { color: var(--ink-3); }
.cart-row__sum { text-align: right; font-size: 1.08rem; font-weight: 600; letter-spacing: -0.02em; }
.cart-row__sum em { display: block; font-style: normal; font-weight: 400; color: var(--ink-3); font-size: .78rem; margin-top: 5px; }
.cart-row__del {
  width: 34px; height: 34px; border: 0; border-radius: 50%; background: transparent;
  color: var(--ink-3); cursor: pointer; display: grid; place-items: center;
}
.cart-row__del:hover { background: var(--field); color: var(--ink); }
.cart-row__del:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }

/* ============================================================
   Корзина: удаление с задержкой (cart.html, markPending).

   Крестик не убирает позицию сразу: строка гаснет и пять секунд ждёт
   «Вернуть» — тот же приём, что у сердечка в избранном. Гасим всё, кроме
   крестика и плашки: крестик остаётся рабочим, им удаление и отменяют.
   Плашка — слой на всю строку, но клики ловит только кнопка: прозрачный
   слой закрыл бы строку целиком.
   ============================================================ */
.cart-row.is-pending { position: relative; }
.cart-row.is-pending > :not(.cart-row__del):not(.cart-row__undo) {
  opacity: .35; pointer-events: none;
}
.cart-row.is-pending .cart-row__del { position: relative; z-index: 2; }
.cart-row__undo {
  position: absolute; inset: 0; z-index: 1;
  display: flex; align-items: center; justify-content: center;
  pointer-events: none;
}
.cart-row__undo > * { pointer-events: auto; }
/* Плашка — белая карточка, а не плавающая подпись: строка плотная, и через
   прозрачные подпись с кнопкой читались бы цифры счётчика количества */
.undo-box {
  display: inline-flex; align-items: center; gap: 10px;
  background: var(--surface); border-radius: var(--r-md);
  padding: 8px 10px 8px 14px;
  box-shadow: 0 10px 26px -14px rgba(24, 24, 16, .7);
}

/* шаг количества */
.qty {
  display: inline-flex; align-items: center;
  border: 1px solid var(--line-strong); border-radius: var(--r-sm); overflow: hidden;
}
.qty button {
  width: 34px; height: 38px; border: 0; background: transparent;
  color: var(--ink); font-size: 1.05rem; line-height: 1; cursor: pointer;
}
.qty button:hover { background: var(--field); }
.qty button:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; }
/* «−» на норме упаковки: количество кратно норме и ниже неё не уходит, поэтому
   кнопка выключена — так видно, что меньше нормы не взять (как у стрелок
   порядка строк в корзине, .cart-row__move button:disabled) */
.qty button:disabled { opacity: .3; cursor: default; }
.qty button:disabled:hover { background: transparent; }
.qty input {
  width: 46px; height: 38px; border: 0; border-left: 1px solid var(--line);
  border-right: 1px solid var(--line); background: var(--surface);
  font: inherit; font-size: .9rem; text-align: center; color: var(--ink);
}
.qty input:focus { outline: none; background: var(--field); }

/* Тот же счётчик, но на карточке товара: занимает ширину кнопки, которую
   заменяет, поэтому «−» и «+» разнесены по краям, а число по центру */
.qty--card { width: 100%; }
.qty--card button { flex: none; }
/* min-width: 0 обязателен: у поля ввода собственный минимальный размер, и без
   этого оно не сжимается — «+» уезжает за границу счётчика */
.qty--card input { flex: 1; width: auto; min-width: 0; }
/* В строке списка счётчик не должен растягиваться на всю ячейку и не должен
   быть шире кнопки «В корзину» рядом: иначе колонка заказа раздувается, а
   название позиции переносится на две строки */
.ptable__act .qty--card { width: 96px; }
.ptable__act .qty--card button { width: 27px; }
.ptable__act .qty--card input { width: 40px; }

/* ---------- копирование артикула ----------
   Артикул выглядит как текст, но нажимается: так его видно и так же просто
   забрать в буфер — не нужно целиться мышью в выделение. */
.art-copy {
  display: inline-flex; align-items: center; gap: 5px;
  border: 0; background: transparent; padding: 0; margin: 0;
  font: inherit; color: inherit; cursor: pointer;
  border-bottom: 1px dashed var(--line-strong);
}
.art-copy:hover { color: var(--ink); border-bottom-color: var(--accent); }
.art-copy:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; border-radius: 3px; }
.art-copy svg { opacity: .55; flex: none; }
.art-copy:hover svg { opacity: 1; }
.art-copy.mono { letter-spacing: .01em; }

/* Подтверждение копирования: снизу по центру, не перекрывает работу */
.copy-toast {
  position: fixed; left: 50%; bottom: 24px; z-index: 90; transform: translateX(-50%) translateY(12px);
  max-width: min(560px, calc(100vw - 32px));
  padding: 11px 18px; border-radius: var(--r-md);
  background: var(--ink); color: #fff; font-size: .86rem;
  box-shadow: var(--shadow-lift);
  opacity: 0; visibility: hidden; transition: opacity .18s, transform .18s, visibility .18s;
}
.copy-toast.on { opacity: 1; visibility: visible; transform: translateX(-50%) translateY(0); }
.copy-toast--bad { background: #9a3b22; }

/* --- сводка --- */
.cart-sum {
  position: sticky; top: 96px;
  background: var(--surface); border-radius: var(--r-lg);
  padding: 26px 28px 24px; border-top: 5px solid var(--accent);
  display: grid; gap: 14px;
}
.cart-sum__rows { display: grid; gap: 10px; font-size: .9rem; color: var(--ink-2); }
.cart-sum__rows div { display: flex; justify-content: space-between; gap: 16px; }
.cart-sum__rows s { color: var(--ink-3); }
.cart-sum__rows .save { color: var(--accent-ink); }
.cart-sum__total {
  display: flex; justify-content: space-between; align-items: baseline; gap: 16px;
  padding-top: 16px; border-top: 1px solid var(--line);
}
.cart-sum__total span { font-size: .9rem; color: var(--ink-3); }
.cart-sum__total b { font-size: 1.86rem; font-weight: 600; letter-spacing: -0.035em; }
.cart-sum__delivery {
  display: flex; gap: 10px; align-items: flex-start;
  background: var(--accent-soft); border-radius: var(--r-sm);
  padding: 12px 14px; font-size: .82rem; color: var(--ink-2);
}
.cart-sum__delivery b { color: var(--ink); font-weight: 500; }
/* Пояснение к отметкам: показываем, когда в заявке ничего не осталось */
.cart-sum__pick { font-size: .78rem; color: var(--ink-3); margin: 12px 0 0; }
.cart-sum .btn.block + .btn.block { margin-top: -4px; }
.cart-sum__note { font-size: .78rem; color: var(--ink-3); margin: 0; }

/* --- пустая корзина --- */
.cart-empty {
  background: var(--surface); border-radius: var(--r-lg);
  padding: 62px 40px; text-align: center; max-width: 720px; margin: 0 auto;
}
.cart-empty__icon {
  width: 72px; height: 72px; margin: 0 auto 22px; border-radius: 50%;
  background: var(--field); display: grid; place-items: center; color: var(--ink-3);
}
.cart-empty h2 { font-size: 1.3rem; letter-spacing: -0.02em; }
.cart-empty p { max-width: 46ch; margin: 14px auto 26px; }
.cart-empty__actions { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; }

/* строка демонстрации второго состояния */
.demo-note {
  margin: 30px 0 0; padding: 14px 18px; border: 1px dashed var(--line-strong);
  border-radius: var(--r-md); font-size: .82rem; color: var(--ink-3);
  display: flex; gap: 14px; align-items: center; flex-wrap: wrap;
}

@media (max-width: 980px) {
  .cart-layout { grid-template-columns: 1fr; gap: 26px; }
  .cart-list { padding: 4px 14px 6px; }
  /* На узком экране колонки галочки, стрелок и фото ужимаются, чтобы названию
     осталось места: и отметка, и стрелки нужны с телефона. */
  .cart-row { grid-template-columns: 22px 22px 58px minmax(0, 1fr) auto; gap: 8px 10px; align-items: start; }
  .cart-row__pick { grid-column: 1; grid-row: 1 / span 2; align-self: center; }
  .cart-row__move { grid-column: 2; grid-row: 1 / span 2; align-self: center; }
  .cart-row__media { width: 58px; height: 58px; grid-row: 1 / span 2; grid-column: 3; }
  .cart-row__info { grid-column: 4; grid-row: 1; }
  .cart-row__del { grid-column: 5; grid-row: 1; justify-self: end; }
  .cart-row__qty { grid-column: 4; grid-row: 2; }
  .cart-row__sum { grid-column: 5; grid-row: 2; }
  .cart-sum { position: static; padding: 22px 20px 20px; }
  .cart-empty { padding: 44px 22px; }
}

/* ============================================================
   Слайдер: рабочая версия.
   Прежняя опиралась на нативную прокрутку трека, а точки лежали
   вне блока слайдера — на кадр они не попадали. Теперь слайд
   едет трансформом, точки лежат внутри кадра на подложке,
   чтобы читались и на светлых снимках.
   ============================================================ */

.slider {
  position: relative; overflow: hidden;
  border-radius: var(--r-lg); touch-action: pan-y;
}
.slider__track {
  display: flex; gap: 0; overflow: visible; scroll-snap-type: none;
  transform: translateX(0);
  transition: transform .62s cubic-bezier(.22, .61, .36, 1);
  will-change: transform;
}
.slide { flex: 0 0 100%; }

.slider__dots {
  position: absolute; right: 26px; bottom: 24px; z-index: 4;
  display: flex; gap: 7px; align-items: center; margin: 0;
  padding: 9px 13px; border-radius: 999px;
  background: rgba(18, 18, 14, .34);
  -webkit-backdrop-filter: blur(7px); backdrop-filter: blur(7px);
}
.slider__dot {
  width: 22px; height: 3px; padding: 0; border: 0; border-radius: 2px;
  background: rgba(255, 255, 255, .45); cursor: pointer;
  transition: background .22s, width .22s;
}
.slider__dot:hover { background: rgba(255, 255, 255, .8); }
.slider__dot.on { background: #fff; width: 34px; }
.slider__dot:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }

@media (prefers-reduced-motion: reduce) {
  .slider__track { transition: none; }
}

@media (max-width: 980px) {
  .slider__dots { right: 16px; bottom: 14px; padding: 8px 11px; }
  .slider__dot { width: 18px; }
  .slider__dot.on { width: 26px; }
}

/* ============================================================
   Плитки «Кому мы полезны»: четыре входа на страницы сегментов.
   ============================================================ */

.who-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; }

.who {
  background: var(--surface); border-radius: var(--r-md); overflow: hidden;
  display: flex; flex-direction: column;
  transition: transform .18s, box-shadow .18s;
}
.who:hover { transform: translateY(-3px); box-shadow: var(--shadow-lift); }
.who:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.who__media { display: block; aspect-ratio: 16 / 9; overflow: hidden; background: var(--field); }
.who__media img { width: 100%; height: 100%; object-fit: cover; transition: transform .35s; }
.who:hover .who__media img { transform: scale(1.05); }
.who__body { display: flex; flex-direction: column; gap: 8px; padding: 15px 18px 17px; flex: 1; }
.who__body b { font-size: .96rem; font-weight: 600; letter-spacing: -0.02em; }
.who__body em { font-style: normal; font-size: .82rem; line-height: 1.4; color: var(--ink-2); flex: 1; }
.who__link { font-size: .8rem; color: var(--ink); border-bottom: 2px solid var(--accent); align-self: flex-start; }

@media (max-width: 1100px) {
  .who-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 620px) {
  .who-grid { grid-template-columns: 1fr; }
}

/* ============================================================
   Страницы сегментов: баннер, условия, подборка.
   ============================================================ */

.seg-banner {
  position: relative; overflow: hidden; display: flex; align-items: flex-end;
  border-radius: var(--r-lg); min-height: 320px; margin: 18px 0 40px;
}
.seg-banner img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.seg-banner::after {
  content: ""; position: absolute; inset: 0;
  /* Текст стоит в левом нижнем углу, поэтому затемняем и слева, и снизу:
     на светлых кадрах белый заголовок не читался. */
  background:
    linear-gradient(90deg, rgba(19, 21, 24, .82) 0%, rgba(19, 21, 24, .58) 40%, rgba(19, 21, 24, .12) 76%, rgba(19, 21, 24, 0) 100%),
    linear-gradient(180deg, rgba(19, 21, 24, .1) 0%, rgba(19, 21, 24, .3) 55%, rgba(19, 21, 24, .72) 100%);
}
.seg-banner__text { position: relative; z-index: 2; padding: 38px 46px; max-width: 64ch; }
.seg-banner__text .label { color: rgba(255, 255, 255, .7); }
.seg-banner__text h1 { color: #fff; margin: 10px 0 0; }
.seg-banner__text p { color: rgba(255, 255, 255, .86); margin: 14px 0 0; }

.seg-conditions { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--gap); }
.seg-conditions .seg { height: 100%; }

.seg-cta {
  background: var(--surface); border-radius: var(--r-lg); padding: 30px 34px;
  display: flex; align-items: center; gap: 28px; border-left: 5px solid var(--accent);
}
.seg-cta > div { flex: 1; }
.seg-cta h3 { font-size: 1.2rem; letter-spacing: -0.02em; }
.seg-cta p { margin: 10px 0 0; font-size: .9rem; color: var(--ink-2); max-width: 62ch; }
.seg-cta .btn { flex: none; }

.seg-others { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--gap); }
.seg-others a {
  background: var(--surface); border-radius: var(--r-md); padding: 20px 22px;
  display: grid; gap: 6px; transition: transform .18s, box-shadow .18s;
}
.seg-others a:hover { transform: translateY(-2px); box-shadow: var(--shadow-lift); }
.seg-others b { font-weight: 600; font-size: .96rem; letter-spacing: -0.01em; }
.seg-others span { font-size: .82rem; color: var(--ink-2); }

@media (max-width: 980px) {
  .seg-banner { min-height: 260px; margin-bottom: 28px; }
  .seg-banner__text { padding: 26px 22px; }
  .seg-conditions, .seg-others { grid-template-columns: 1fr; }
  .seg-cta { flex-direction: column; align-items: flex-start; gap: 18px; padding: 24px 22px; }
}

/* ============================================================
   Блок «Акции и новости»: две вкладки, три карточки в ряд.
   ============================================================ */

.promo-head { display: flex; align-items: flex-end; gap: 24px; margin-bottom: 30px; flex-wrap: wrap; }
.promo-tabs { display: flex; gap: 8px; margin-left: auto; }
.promo-tab {
  border: 1px solid var(--line-strong); background: transparent; border-radius: 999px;
  padding: 9px 20px; font: inherit; font-size: .88rem; color: var(--ink-2); cursor: pointer;
  transition: background .16s, border-color .16s, color .16s;
}
.promo-tab:hover { border-color: var(--ink); color: var(--ink); }
.promo-tab[aria-selected="true"], .promo-tab[aria-pressed="true"] { background: var(--ink); border-color: var(--ink); color: #fff; }
.promo-tab:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }

.promo-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--gap); }
.promo-grid[hidden] { display: none; }

/* Плитки блока «Акции и новости» — одной высоты в обеих вкладках. У карточки акции
   в теле на строку больше (внизу ссылка «Смотреть товары акции»), поэтому новости
   выходили ниже акции, и блок прыгал при переключении вкладок (замер 15.10.2026:
   360 против 377 px на 1440 px). Высоту задаём числом, тело растягивается — текст
   не режем. Значения взяты по худшему случаю (заголовок в две строки и анонс
   на 180 символов — столько даёт short() в make_news_articles_index.py), замер
   на 1440/1280/1200/1100/1000 px: нужно 395–405 px и 412–423 px соответственно.
   Ниже 980 px плитки идут в одну колонку и кадр растёт вместе с шириной — там
   высота снова свободная, единым числом её не задать */
@media (min-width: 1200px) {
  #promo .promo { height: 415px; }
}
@media (min-width: 981px) and (max-width: 1199px) {
  #promo .promo { height: 435px; }
}

.promo {
  background: var(--surface); border-radius: var(--r-md); padding: 24px 26px 26px;
  display: flex; flex-direction: column; gap: 12px; border-top: 4px solid var(--accent);
}
.promo__meta { display: flex; align-items: center; gap: 10px; font-size: .76rem; color: var(--ink-3); }
.promo__tag {
  background: var(--accent); color: var(--accent-ink); border-radius: 4px;
  padding: 3px 8px; font-size: .7rem; font-weight: 600; text-transform: uppercase; letter-spacing: .06em;
}
.promo__tag.news { background: var(--field); color: var(--ink-2); }
/* Бейдж черновика: статья открыта по прямой ссылке, в ленте её ещё нет
   (news.html?drafts=1 — стек на проверку, см. make_news_articles_index.py) */
.promo__tag.draft { background: var(--ink); color: #fff; }

/* Стек черновиков: нумерованный список статей на проверку. Номер — тот, которым
   заказчик называет статью («публикуй №3»), и он за статьёй закреплён */
.drafts { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.drafts__item {
  display: flex; align-items: baseline; gap: 16px; flex-wrap: wrap;
  padding: 15px 20px; background: var(--surface); border-radius: var(--r-md);
}
.drafts__n { font-weight: 700; font-variant-numeric: tabular-nums; min-width: 1.6em; }
.drafts__date { font-size: .82rem; color: var(--ink-3); white-space: nowrap; }
.drafts__title { font-weight: 500; }
.promo h3 { font-size: 1.06rem; letter-spacing: -0.02em; }
.promo p { margin: 0; font-size: .88rem; line-height: 1.5; color: var(--ink-2); }
.promo .link-accent { margin-top: auto; align-self: flex-start; font-size: .85rem; }

/* Карточка новости с кадром: фото сверху во всю ширину, тексты в .promo__body.
   Верхнюю жёлтую полосу снимаем — она спорит с фотографией. */
.promo--news { padding: 0; border-top: 0; gap: 0; overflow: hidden; min-width: 0; }
/* Кадр — в своём соотношении, без обрезки: у Arlight в новостях баннеры своего формата
   (у «Резки неона» 1200x427, то есть 2,8:1), и кроп под 16:10 резал надписи по краям.
   `min-width: 0` тут обязателен: без него картинка шириной 1200 px держит ширину колонки
   сетки, карточка вылезает за экран и текст в ней обрезается */
.promo__media { background: var(--field); min-width: 0; }
.promo__media img { display: block; width: 100%; height: auto; max-width: 100%; }
.promo__body { display: flex; flex-direction: column; gap: 12px; padding: 20px 26px 24px; flex: 1 1 auto; min-width: 0; }
/* Ссылкой служит вся карточка — и кадр, и текст; отдельной «Читать у нас» внизу нет
   (заказчик 13.10.2026: «ссылка должна быть всё — и картинка, и текст»).
   Так сделаны карточки новостей и на странице «Новости», и в блоке на главной */
.promo__link { display: flex; flex-direction: column; height: 100%; color: inherit; min-width: 0; }
.promo__link:hover h3 { text-decoration: underline; text-decoration-color: var(--accent); text-underline-offset: 3px; }
/* Чипы рубрик на странице «Новости» идут слева, а не справа, как табы на главной.
   Перенос разрешён: четыре чипа шире телефона и без него растягивали страницу,
   отчего текст выше тоже обрезался (проверено на 430 px) */
.promo-tabs--left { margin-left: 0; flex-wrap: wrap; }
/* На телефоне чипы рубрик и подпись «Материалов: N» идут друг под другом,
   а не в одну строку */
@media (max-width: 620px) {
  #news-tags { margin: 0 0 8px; }
  #news-updated { margin-left: 0; }
}

/* ============================================================
   «Новинки месяца» — лента постов Arlight (new.html) и первый её пост
   в блоке на главной. Пост это не плитка в ряд, а строка ленты: месяц со
   спикером, заголовок, абзац, видео и серии. Стили свои, а мета и видео
   общие с новостями (.promo__meta, .article__video) — они уже задают
   шрифт подписи и кадр плеера 16:9.
   ============================================================ */

.posts { display: grid; gap: var(--gap); max-width: 820px; }
/* Колонку постов ограничиваем по ширине статьи на «Новостях» (там .article —
   760 px): карточка во всю ширину страницы давала строку в 150 знаков, и абзац
   читался по диагонали. 820 = 760 + поля карточки по 30 px */
.post {
  background: var(--surface); border-radius: var(--r-md);
  padding: 26px 30px 28px; display: flex; flex-direction: column; gap: 14px;
}
/* Заголовок поста — как h2 статьи (.article__body h2): на странице это второй
   уровень после «Новинки месяца», а не заголовок секции (clamp до 2.1rem) */
.post h2 { font-size: 1.22rem; margin: 0; }
.post p { margin: 0; color: var(--ink-2); line-height: 1.55; }
/* Видео и серии внутри поста стоят плотнее, чем в статье: между ними нет
   абзацев текста, и общий отступ .article__video (22 px снизу) разрывал ленту */
.post .article__video { margin: 4px 0 0; }
/* Серии — строками без маркеров: у серии две части (название и цена), и в списке
   с точками цена «от N ₽» уезжала на вторую строку */
.post__series { list-style: none; margin: 2px 0 0; padding: 0; display: grid; gap: 8px; }
.post__series li { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
/* Цена — справочная подпись к серии, поэтому приглушённая: название читается
   первым, а число не спорит с ним за внимание */
.post__price { font-size: .85rem; color: var(--ink-3); }
/* Серия, которой у нас нет: ссылки нет, поэтому название приглушено — так видно,
   что в каталог отсюда не перейти (цена у таких не показывается вовсе) */
.post__name { color: var(--ink-2); }
/* Телефон: внутренние поля поста уменьшаем — в узкой колонке 30 px по бокам
   съедают по строке у длинных названий серий («A120 24V 15 W/m IP67») */
@media (max-width: 620px) {
  .post { padding: 22px 20px 24px; }
}

/* ============================================================
   Статья новости (news.html?n=...): кадр, текст, наши ссылки, подпись источника.
   Разметку собирает скрипт страницы из data/news-articles/<id>.json.
   ============================================================ */

.article { max-width: 760px; }
/* Шапка статьи — по ширине статьи. Общий `.lead` ограничен 46ch (это для шапок
   разделов), и на странице статьи подводка выходила заметно уже обложки и текста
   (заказчик 13.10.2026 с вопросом про выравнивание) */
.article-head > div { max-width: 760px; }
.article-head .lead { max-width: none; }
.article__cover { margin: 0 0 26px; border-radius: var(--r-md); overflow: hidden; background: var(--field); }
.article__cover img { display: block; width: 100%; height: auto; }
.article__body { font-size: 1.02rem; line-height: 1.65; }
.article__body p { margin: 0 0 16px; }
.article__body h2 { font-size: 1.22rem; margin: 30px 0 12px; letter-spacing: -0.02em; }
.article__body ol, .article__body ul { margin: 0 0 18px; padding-left: 22px; }
.article__body li { margin-bottom: 8px; }
.article__body img { display: block; width: 100%; height: auto; margin: 0 0 18px; border-radius: var(--r-md); }
.article__quote {
  margin: 0 0 18px; padding: 2px 0 2px 18px; border-left: 3px solid var(--accent);
  color: var(--ink-2); font-size: .95rem;
}
.article__cta { display: flex; flex-wrap: wrap; gap: 12px; margin: 6px 0 22px; }
/* Видеообзор новинки: до клика — кнопка, после — плеер rutube в кадре 16:9.
   Плеер грузим по клику, чтобы чужой iframe не тянулся с каждой статьёй */
.article__video { margin: 6px 0 22px; }
.article__video iframe {
  display: block; width: 100%; aspect-ratio: 16 / 9; height: auto;
  border: 0; border-radius: var(--r-md); background: var(--field);
}
.article__src {
  margin: 30px 0 0; padding-top: 14px; border-top: 1px solid var(--line);
  font-size: .82rem; line-height: 1.5; color: var(--ink-3);
}

@media (max-width: 980px) {
  .promo-grid { grid-template-columns: 1fr; }
  .promo-tabs { margin-left: 0; }
}

/* ============================================================
   Верх главной: слайдер → плитки сегментов → поиск.
   Раньше между блоками складывались отступы двух секций
   (76 + 76 = 152 px) и получалась пустая полоса. Сводим к 44 px.
   ============================================================ */

.slider-section { padding-top: 0; padding-bottom: 44px; }
/* Заголовок этого блока без надстрочника, поэтому верхний отступ вернули сами:
   иначе он лип к секции слайдера, а у соседних блоков заголовок стоит ниже края. */
#who { padding-top: 26px; padding-bottom: 44px; }
.hero { padding-top: 0; }

@media (max-width: 980px) {
  .slider-section { padding-bottom: 28px; }
  #who { padding-bottom: 28px; }
}

/* ============================================================
   Мессенджеры в верхней полосе: Telegram, WhatsApp, MAX.
   Иконки, а не подписи — полоса узкая, телефон важнее.
   ============================================================ */

.topbar__im { display: inline-flex; align-items: center; gap: 4px; }

.topbar__im a {
  width: 26px; height: 26px; border-radius: 50%;
  display: grid; place-items: center; color: #8d8b85;
  border: 1px solid transparent;
  transition: color .15s, border-color .15s;
}
.topbar__im a:hover { color: #fff; border-color: #3a3d42; }
.topbar__im a:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.topbar__im svg { display: block; }

@media (max-width: 1100px) {
  .topbar__im { display: none; }
}

/* ============================================================
   Страница поиска: шапка с крупной строкой и блок точного совпадения
   по артикулу. Остальное — обычные карточки и фасеты каталога.
   ============================================================ */

.search-head { padding: 6px 0 28px; display: grid; gap: 16px; }
.search-head h1 { font-size: clamp(1.5rem, 2.4vw, 2rem); }
.search-head .bigsearch { max-width: 760px; }

.match {
  display: grid; grid-template-columns: 128px minmax(0, 1fr) auto;
  gap: 26px; align-items: center;
  background: var(--surface); border-radius: var(--r-lg);
  border-left: 5px solid var(--accent); padding: 22px 26px;
}
.match__media {
  width: 128px; height: 128px; border-radius: var(--r-sm); background: var(--field);
  display: grid; place-items: center; overflow: hidden;
}
.match__media img { width: 100%; height: 100%; object-fit: contain; padding: 10px; mix-blend-mode: multiply; }
.match__name { font-size: 1.04rem; font-weight: 500; letter-spacing: -0.02em; }
.match__meta { font-size: .8rem; color: var(--ink-3); margin-top: 8px; }
.match__specs { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; }
.match__specs span { border: 1px solid var(--line); border-radius: 4px; padding: 3px 8px; font-size: .76rem; color: var(--ink-2); }
.match__price { display: grid; gap: 10px; justify-items: end; text-align: right; }
.match__price b { font-size: 1.42rem; letter-spacing: -0.03em; }
.match__stock { font-size: .8rem; color: #2f7d4f; }
.match__stock.wait { color: var(--ink-3); }

@media (max-width: 900px) {
  .match { grid-template-columns: 1fr; gap: 18px; padding: 20px; }
  .match__price { justify-items: start; text-align: left; }
}

/* ============================================================
   Таймлайн на странице «О компании».
   .steps4 рассчитан на кружки с цифрами 1–4, а тут годы и слово
   «Сегодня» — они в кружок не влезают, поэтому отдельный стиль.
   ============================================================ */

.timeline { position: relative; display: grid; gap: 34px; padding-left: 40px; }
.timeline::before {
  content: ""; position: absolute; left: 7px; top: 12px; bottom: 12px;
  width: 2px; background: var(--line);
}
.timeline > div {
  position: relative; display: grid;
  grid-template-columns: 120px minmax(0, 1fr); gap: 26px; align-items: baseline;
}
.timeline > div::before {
  content: ""; position: absolute; left: -40px; top: 6px;
  width: 16px; height: 16px; border-radius: 50%; box-sizing: border-box;
  background: var(--accent); border: 4px solid var(--bg);
}
.timeline > div > b {
  font-size: 1.32rem; font-weight: 600; letter-spacing: -0.03em; color: var(--ink);
}
.timeline > div > span { font-size: .93rem; line-height: 1.55; color: var(--ink-2); }
.timeline span b { color: var(--ink); font-weight: 500; }

@media (max-width: 700px) {
  .timeline { padding-left: 30px; gap: 26px; }
  .timeline::before { left: 5px; }
  .timeline > div { grid-template-columns: 1fr; gap: 4px; }
  .timeline > div::before { left: -30px; }
}

/* ============================================================
   Навигация: две выпадашки — «Покупателям» и «Компания».
   Пункт внутри группы подсвечивается своим правилом, но нужно
   показать и саму группу: иначе на страницах правил в шапке
   не видно, где ты находишься. Прозрачная линия — чтобы при
   подсветке шапка не дёргалась на 1,5 px.
   ============================================================ */

.nmenu > summary { border-bottom: 1.5px solid transparent; }
.nmenu > summary.on { color: var(--ink); border-bottom-color: var(--accent); }

/* ============================================================
   Ссылка в плашке про cookie.
   В фирменной палитре .link-accent чёрный — на светлом фоне это
   правильно, но плашка тёмная, и текст ссылки пропадал совсем:
   оставалась только жёлтая линия. На тёмных поверхностях берём
   акцентный цвет, а на наведении не подкладываем светлый фон,
   иначе жёлтый по кремовому не читается.
   ============================================================ */

.cookie .link-accent { color: var(--accent); }
.cookie .link-accent:hover { background: transparent; border-bottom-color: currentColor; }

/* ============================================================
   Каталог: наличие и срок в карточке, вид списком.
   Раньше в карточке была только цена — закупщик не мог понять,
   что есть на складе, а что ждать три недели.
   ============================================================ */

.pcard__avail {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: .78rem; color: var(--ink-2);
  /* Прижата к низу карточки: в ряду плиток у одной название длиннее или есть
     лишняя метка, и строка остатков стояла выше соседей — теперь у всех на
     одном уровне вместе с упаковкой и ценой (заказчик 12.10.2026: «прижми
     остатки к низу, как посередине»). Место собирается над строкой — тело
     карточки тянется на всю высоту ряда, поэтому и работает.
     Когда в карточке есть характеристики, место собирают они (правила у
     .pcard__body > .pcard__specs): тогда характеристики и остатки стоят на одном
     уровне у всех плиток ряда, а не разъезжаются из-за меток вверху */
  margin-top: auto;
}
.pcard__avail::before {
  content: ""; width: 6px; height: 6px; border-radius: 50%;
  background: currentColor; flex: none;
}
.pcard__avail.now { color: #2f7d4f; }
.pcard__avail.order { color: var(--ink-3); }
.pcard__price em .mult { color: var(--ink-3); }

/* Переключатель вида: сетка или список */
.view-toggle { display: inline-flex; border: 1px solid var(--line-strong); border-radius: var(--r-sm); overflow: hidden; }
.view-toggle button {
  border: 0; background: transparent; font: inherit; font-size: .84rem;
  padding: 8px 14px; color: var(--ink-2); cursor: pointer;
}
.view-toggle button + button { border-left: 1px solid var(--line-strong); }
.view-toggle button:hover { background: var(--field); color: var(--ink); }
.view-toggle button[aria-pressed="true"] { background: var(--ink); color: #fff; }
.view-toggle button:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; }

/* Вид списком: таблица с параметрами — так закупщику удобнее сверять со сметой */
.ptable { width: 100%; border-collapse: collapse; font-size: .88rem; background: var(--surface); border-radius: var(--r-md); overflow: hidden; }
.ptable th {
  text-align: left; font-weight: 500; font-size: .76rem; text-transform: uppercase;
  letter-spacing: .06em; color: var(--ink-3); padding: 14px 16px; border-bottom: 1px solid var(--line);
}
.ptable td { padding: 14px 16px; border-bottom: 1px solid var(--line); vertical-align: middle; }
.ptable tr:last-child td { border-bottom: 0; }
.ptable tbody tr:hover { background: var(--bg); }
.ptable__media { width: 56px; position: relative; }
.ptable__media img { width: 44px; height: 44px; object-fit: contain; mix-blend-mode: multiply; }
/* Метки «Новинка» и акции в списке — значками в углу фото, без подписи.
   Подпись занимала отдельную строку под названием и растягивала строку
   списка (заказчик 18.10.2026: нужны иконки на фото и компактно). */
.ptable__flags {
  position: absolute; top: 2px; left: 10px; z-index: 2;
  display: flex; flex-direction: column; align-items: flex-start; gap: 4px;
}
.ptable__flag {
  width: 19px; height: 19px; border-radius: 5px;
  display: grid; place-items: center;
  box-shadow: 0 1px 3px rgba(24, 24, 16, .26);
}
.ptable__flag svg { width: 12px; height: 12px; display: block; }
.ptable__flag.new { background: var(--accent); color: var(--accent-ink); }
.ptable__flag.sale { background: var(--ink); color: var(--accent); }
.ptable__art-col { white-space: nowrap; font-variant-numeric: tabular-nums; }
.ptable__art-col a { color: var(--ink); border-bottom: 1px solid var(--line-strong); }
.ptable__art-col a:hover { border-bottom-color: var(--ink); }
/* Ссылка на документ изделия: подпись «PDF», полное название — в подсказке */
.ptable__doc {
  display: inline-block; padding: 3px 8px; border-radius: 5px;
  background: var(--field); color: var(--ink-2);
  font-size: .74rem; letter-spacing: .04em; text-transform: uppercase;
}
.ptable__doc:hover { background: var(--accent); color: var(--ink); }
.ptable__doc-cell { white-space: nowrap; }

/* Аксессуары: виды (Подвес, Крепёж, Аксессуар) — кнопками над сеткой, как у
   Arlight. Активный вид — чёрная плашка, как у кнопок сайта */
/* Шапка вкладки связей: пояснение слева, «Страница серии» справа (у марок
   серия листается вкладкой, и кнопка на её страницу стоит здесь, а не в
   отдельном блоке под карточкой) */
.rel-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin: 0 0 14px; }
.rel-tabs { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 24px; }
.rel-tabs button {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 8px 15px; border: 1px solid var(--line); border-radius: 999px;
  background: var(--surface); color: var(--ink-2);
  font: inherit; font-size: .86rem; cursor: pointer;
  transition: background .16s, color .16s, border-color .16s;
}
.rel-tabs button:hover { border-color: var(--line-strong); color: var(--ink); }
.rel-tabs button.on { background: var(--ink); border-color: var(--ink); color: #fff; }
.rel-tabs button span { font-size: .78rem; opacity: .7; }

/* Листалка списков «Аксессуары» и «Совместимые»: после нажатия страницы верх
   списка не уезжает под липкую шапку; на телефоне страницы переносятся */
#p-acc, #p-serie-tab, #p-cmp { scroll-margin-top: 96px; }
#p-acc .pagination, #p-serie-tab .pagination, #p-cmp .pagination { margin-top: 28px; }
@media (max-width: 700px) {
  #p-acc .pagination, #p-serie-tab .pagination, #p-cmp .pagination { flex-wrap: wrap; justify-content: flex-start; }
}

/* Увеличение фото в списке: в строке миниатюра мелкая, разглядеть по ней
   позицию нельзя. Наведение показывает кадр рядом, клик открывает во весь
   экран. Механика живёт в assets/img-zoom.js, класс подсказки — .ptable-zoom;
   .img-zoom остался от прежней копии в корзине и пока не используется. */
.ptable-zoom, .img-zoom {
  position: fixed; z-index: 60; pointer-events: none; padding: 8px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-sm); box-shadow: var(--shadow-lift);
}
.ptable-zoom img, .img-zoom img { display: block; width: 320px; height: 320px; object-fit: contain; mix-blend-mode: multiply; }
.zoombox {
  position: fixed; inset: 0; z-index: 80; display: grid; place-items: center;
  padding: 40px 24px; background: rgba(19, 21, 24, .62);
}
.zoombox img {
  max-width: min(1000px, 92vw); max-height: 86vh; cursor: zoom-out;
  background: #fff; border-radius: var(--r-md); box-shadow: var(--shadow-lift);
}
.zoombox__close {
  position: absolute; top: 18px; right: 22px; width: 44px; height: 44px;
  border: 0; border-radius: 50%; cursor: pointer; font-size: 1.4rem; line-height: 1;
  background: rgba(255, 255, 255, .92); color: var(--ink);
}
.ptable__name { display: block; line-height: 1.35; }
.ptable__art { color: var(--ink-3); font-size: .78rem; margin-top: 4px; }
/* Кнопки «+ аксессуары» и «+ совместимые» в строке списка — как в кабинете
   Arlight. Раскрывают под строкой список позиций, откуда их можно положить в
   корзину, не уходя в карточку. Кнопки есть только у тех позиций, к которым
   что-то привязано, поэтому пустой блок скрыт */
.ptable__links { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.ptable__links:empty { display: none; }
/* Кнопки живут в отдельной строке под строкой товара (её собирает linksRow в
   catalog.html): в колонке названия паре места не хватало — на экране 1250 px она
   155 px, а паре нужно ~235, и они вставали в две строки. Ячейка кнопок занимает
   название и оба склада (colspan=3): обе кнопки встают в одну строку, а ширину
   таблицы это не раздувает (одна широкая ячейка названия потянула бы за собой
   горизонтальную прокрутку страницы). Крайние ячейки строки пустые и без
   паддингов: ячейка начинает строку с первой колонки, поэтому без них кнопки
   встали бы под артикулом, а фон подсветки обрывался бы на названии */
/* Отступы ячеек строки кнопок перебиваются общим `.ptable td` (0,1,1 против
   0,1,0): из-за этого у ячейки кнопок оставался верхний отступ 14 px, а пустые
   крайние ячейки давали ещё 28 px высоты — под названием появлялась пустая
   полоса (заказчик 18.10.2026). Селекторы с `td.` специфичнее общего правила */
.ptable td.ptable__links-cell { padding: 0 16px 10px; }
.ptable__links-cell .ptable__links { margin-top: 0; }
.ptable td.ptable__links-lead,
.ptable td.ptable__links-tail { padding: 0; }
/* Отделитель строки уезжает под кнопки: иначе полоса встаёт между названием и
   кнопками, и они читаются как начало следующей строки. Нижний отступ ячейки
   меньше обычного: строку с кнопками отделяет только он, и лишние 14 px
   превращались в пустую полосу под названием (заказчик 18.10.2026) */
.ptable__row.has-links > td { border-bottom: 0; padding-bottom: 8px; }
.ptable__links-row > td { border-bottom: 1px solid var(--line); }
/* Наведение подсвечивает позицию целиком: строка товара и её строка кнопок —
   одно, и светиться они должны вместе. Первое правило — когда курсор на строке
   товара, второе и третье — когда на кнопках; «предыдущего соседа» в CSS иначе
   как через :has не выразить. В браузере без :has подсветится одна строка
   кнопок — вёрстка от этого не поедет */
.ptable__row.has-links:hover + .ptable__links-row,
.ptable__links-row:hover,
.ptable__row.has-links:has(+ .ptable__links-row:hover) { background: var(--bg); }
.ptable__links button {
  border: 1px solid var(--line-strong); background: transparent; border-radius: 4px;
  padding: 4px 9px; font: inherit; font-size: .78rem; color: var(--ink-2); cursor: pointer;
  transition: border-color .16s, color .16s, background .16s;
}
.ptable__links button:hover { border-color: var(--ink); color: var(--ink); }
.ptable__links button.on { border-color: var(--ink); color: var(--ink); background: var(--field); }
/* Знак перед подписью: «+» закрыто, «−» открыто. Рисуем его стилем, а не
   разметкой, чтобы он не разъезжался с состоянием списка */
.ptable__links button::before { content: "+"; margin-right: 6px; color: var(--ink-3); }
.ptable__links button.on::before { content: "−"; color: var(--ink); }
.ptable__links button span { color: var(--ink-3); }
.ptable__links button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Раскрытый список под строкой: своя подложка, чтобы он читался как вложенный */
.ptable__sub > td { padding: 0; border-bottom: 1px solid var(--line); }
.sublist { background: var(--field); padding: 16px 20px 10px; }
.sublist__head { display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap; margin-bottom: 10px; }
.sublist__head b { font-size: .92rem; font-weight: 600; }
.sublist__head .muted { margin-left: auto; }
.sublist__close {
  border: 0; background: transparent; font: inherit; font-size: .8rem; color: var(--ink-3);
  cursor: pointer; padding: 2px 0; border-bottom: 1px solid transparent;
}
.sublist__close:hover { color: var(--ink); border-bottom-color: var(--ink); }
.sublist__close:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Длинный список связей (у «Совместимых» бывает 126 ламп) показываем партиями:
   первые 12 строк видны, остальные лежат в разметке скрытыми и раскрываются
   кнопкой — так строка каталога не растягивается на несколько экранов */
.sub-item.is-hidden { display: none; }
.sublist__more {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 14px 0 4px; border-top: 1px solid var(--line);
}
.sublist__more button {
  border: 1px solid var(--line-strong); background: var(--surface); color: var(--ink);
  border-radius: var(--r-sm); padding: 8px 14px; font: inherit; font-size: .82rem;
  cursor: pointer;
}
.sublist__more button:hover { border-color: var(--ink); }
.sublist__more button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.sub-item {
  display: grid; grid-template-columns: 56px minmax(0, 1fr) 120px 56px 150px;
  gap: 16px; align-items: center; padding: 10px 0; border-top: 1px solid var(--line);
}
.sub-item:first-of-type { border-top: 0; }
.sub-item__media {
  width: 56px; height: 56px; border-radius: var(--r-sm); background: var(--surface);
  display: grid; place-items: center; overflow: hidden; position: relative;
}
/* Значки новинки и акции на фото позиции в раскрытом списке: те же .ptable__flag,
   что в строке каталога, только меньше — кадр здесь 56 px */
.sub-item__media .ptable__flags { top: 1px; left: 4px; gap: 3px; }
.sub-item__media .ptable__flag { width: 15px; height: 15px; border-radius: 4px; }
.sub-item__media .ptable__flag svg { width: 10px; height: 10px; }
.sub-item__media img { width: 100%; height: 100%; object-fit: contain; padding: 6px; mix-blend-mode: multiply; }
/* Название занимает две строки всегда. Иначе шаг строк во вложенном списке
   рваный: у лент название в две строки, у заглушек в одну, и строки разной
   высоты. Высоту задаём ровно в две строки (2 × 1.35em) — иначе двухстрочное
   имя оказывается выше минимума и строка всё равно уезжает.
   Лишнее обрезаем многоточием, полное название — в подсказке и в карточке */
.sub-item__name {
  font-size: .88rem; line-height: 1.35;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  overflow: hidden; min-height: 2.7em;
}
.sub-item__name:hover { border-bottom: 1px solid var(--accent); }
.sub-item__meta { color: var(--ink-3); font-size: .76rem; margin-top: 5px; }
.sub-item__price { text-align: right; font-size: .95rem; font-weight: 600; white-space: nowrap; }
.sub-item__price em { display: block; font-style: normal; font-weight: 400; color: var(--ink-3); font-size: .76rem; margin-top: 3px; }
/* Паспорт изделия — там же, где он стоит в строке списка: между ценой и кнопкой.
   Светлая подложка с рамкой — только нейтральному значку: на серой подложке
   раскрытого списка он пропадал. Цветные значки (PDF, IES, 3D) красятся своими
   классами, и общее правило их больше не перебивает: раньше подложка становилась
   белой, а надпись оставалась белой — вместо «PDF» был пустой прямоугольник */
.sub-item__doc { text-align: center; }
.sub-item__doc .ptable__doc--other { background: var(--surface); border: 1px solid var(--line-strong); }
.sub-item__doc .ptable__doc:hover { background: var(--accent); border-color: var(--accent); }
.ptable__num { white-space: nowrap; font-variant-numeric: tabular-nums; }
.ptable__sum { text-align: right; white-space: nowrap; }
.ptable__sum b { font-size: 1rem; letter-spacing: -0.02em; }
.ptable__sum em { display: block; font-style: normal; color: var(--ink-3); font-size: .76rem; margin-top: 3px; }
/* Позиция без цены — архивная или снята с прайса: вместо суммы пометка, вместо
   кнопки покупки просьба уточнить. Собирается в assets/lists.js (priceBox,
   addOrAsk), а вид один на весь сайт — потому и правило одно, ниже правил
   цены, чтобы перебивать их размер шрифта */
b.arch { font-size: .82rem; font-weight: 500; color: var(--ink-2); letter-spacing: 0; }
.arch-ask { flex: 1; text-align: center; font-size: .86rem; color: var(--ink-3); }
.ptable__act { text-align: right; }
/* Избранное и сравнение в строке списка: те же кнопки, что на плитке, но не
   поверх фото, а рядом с «В корзину» — в списке они должны быть на виду всегда,
   а не появляться по наведению, как на плитке */
.ptable__tools { display: inline-flex; gap: 6px; vertical-align: middle; margin-right: 8px; }
.ptable__act .pcard__wish, .ptable__act .pcard__cmp { background: transparent; }

@media (max-width: 1100px) {
  .ptable__hide { display: none; }
}

/* ============================================================
   Наличие по складам — как у ЭТМ: свой склад, склад вендора,
   и суммарно. Закупщик смотрит не «есть/нет», а откуда повезут:
   из Хабаровска заберёт сегодня, от вендора — ждать поставку.
   ============================================================ */

.stock { margin-top: 26px; }
.stock__table { width: 100%; border-collapse: collapse; font-size: .9rem; }
.stock__table td { padding: 11px 0; border-bottom: 1px solid var(--line); vertical-align: baseline; }
.stock__table tr:last-child td { border-bottom: 0; }
.stock__table td:first-child { color: var(--ink-2); width: 132px; }
.stock__table td:nth-child(2) { width: 110px; white-space: nowrap; }
.stock__table b { font-weight: 600; font-size: 1rem; letter-spacing: -0.02em; }
.stock__table .none { color: var(--ink-3); }
.stock__table .unit { color: var(--ink-3); font-size: .82rem; }
/* Пробел перед единицей стоит в разметке (product.html, ячейка наличия), а не
   отбивкой: так «более 505м» читается как «более 505 м» при копировании и
   скринридером. Отбивку поэтому убрали — зазор даёт сам пробел */
.stock__note { font-size: .8rem; color: var(--ink-3); margin: 12px 0 0; }

/* Строка наличия в карточке каталога: кратко, по складам */
.pcard__avail {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-size: .78rem; color: var(--ink-2);
}
.pcard__avail::before {
  content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: none;
}
.pcard__avail.now { color: #2f7d4f; }
.pcard__avail.order { color: var(--ink-3); }
.pcard__avail .wh { white-space: nowrap; }
.pcard__avail .wh b { font-weight: 500; color: var(--ink); }

@media (max-width: 560px) {
  .stock__table td:first-child { width: 96px; }
}

/* ============================================================
   Плитки разделов в каталоге.
   Базовый .cat-tile гасит фото до 42 % — это правильно для главной,
   где плитка читается как тёмный баннер. В каталоге фото раздела —
   главное, поэтому показываем его целиком, а подпись держим на
   градиенте снизу.
   ============================================================ */

.cat-tile--photo { background: var(--field); }
.cat-tile--photo img { opacity: 1; }
.cat-tile--photo::after {
  content: ""; position: absolute; inset: 0; z-index: 1;
  background: linear-gradient(180deg, rgba(19, 21, 24, 0) 38%, rgba(19, 21, 24, .52) 68%, rgba(19, 21, 24, .84) 100%);
}
.cat-tile--photo span { z-index: 2; }
.cat-tile--photo:hover img { opacity: 1; transform: scale(1.04); }
.cat-tile--photo:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }

/* ============================================================
   Кнопка «наверх»: появляется, когда страница прокручена вниз.
   На длинных страницах (каталог, список подразделов) возвращаться
   к началу иначе приходится колесом. Живёт справа внизу, слева —
   плашка про cookie, они не пересекаются.
   ============================================================ */

.to-top {
  position: fixed; right: 24px; bottom: 24px; z-index: 55;
  width: 46px; height: 46px; border-radius: 50%;
  border: 0; cursor: pointer;
  background: var(--ink); color: #fff;
  display: grid; place-items: center;
  box-shadow: 0 10px 24px -12px rgba(24, 24, 16, .6);
  opacity: 0; visibility: hidden; transform: translateY(8px);
  transition: opacity .2s, transform .2s, visibility .2s, background .16s;
}
.to-top.on { opacity: 1; visibility: visible; transform: translateY(0); }
.to-top:hover { background: #000; }
.to-top:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.to-top svg { display: block; }

@media (max-width: 980px) {
  .to-top { right: 16px; bottom: 16px; width: 42px; height: 42px; }
}

/* ============================================================
   Плитки разделов в нашем стиле.
   Фотографии у Arlight прайсовые: белые предметы на белом фоне,
   двенадцать одинаковых светлых карточек. Даём им тёплую тонировку
   (одна и та же на всех, поэтому ряд выглядит единым) и подпись
   на тёмной плашке с жёлтой линией — фирменные цвета.
   На наведении фотография возвращает настоящие цвета.
   ============================================================ */

.cat-tile--photo {
  position: relative; display: block; padding: 0;
  background: var(--field); aspect-ratio: 4 / 3; overflow: hidden;
}
.cat-tile--photo img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover;
  transition: transform .5s cubic-bezier(.2, .7, .3, 1);
}
/* Затемнение только снизу, под подписью: сам кадр остаётся открытым */
.cat-tile--photo::after {
  content: ""; position: absolute; inset: 0; z-index: 1;
  background: linear-gradient(180deg, rgba(19, 21, 24, 0) 46%, rgba(19, 21, 24, .42) 72%, rgba(19, 21, 24, .8) 100%);
}
.cat-tile--photo span {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 2;
  padding: 0 18px 16px; color: #fff;
  font-size: 1rem; line-height: 1.28; letter-spacing: -0.01em;
}
.cat-tile--photo small {
  display: block; margin-top: 4px; color: rgba(255, 255, 255, .74); font-size: .78rem;
}

.cat-tile--photo:hover img,
.cat-tile--photo:focus-visible img { transform: scale(1.04); }

/* ============================================================
   Страница раздела каталога: позиция без фото.
   Часть артикулов Arlight приходит без картинки — вместо битого
   изображения показываем артикул на подложке карточки.
   ============================================================ */
.pcard__noimg {
  display: flex; align-items: center; justify-content: center;
  height: 100%; padding: 16px; text-align: center; line-height: 1.5;
}

/* ============================================================
   Раздел каталога: панель фильтров как у Arlight.
   Кружок цвета у цветовых фильтров и «показать все» у длинных списков.
   ============================================================ */
.check .swatch {
  width: 13px; height: 13px; border-radius: 50%; flex: none;
  border: 1px solid rgba(0, 0, 0, .18); margin-right: 8px;
}
.check { display: flex; align-items: center; }
.fgroup__more {
  border: 0; background: transparent; padding: 8px 0 0;
  color: var(--ink-3); font: inherit; font-size: .82rem; cursor: pointer;
}
.fgroup__more:hover { color: var(--ink); }
/* Длинный список значений прокручивается сам, а не растягивает панель:
   в «Модельном ряду» 505 значений, и после «Выбрать все» они раскрывались
   во всю длину — десяток экранов (заказчик 19.10.2026: «хочу чтобы там был
   скролл, а не длинющий список»). Высота — около дюжины строк: видно, что
   список длинный и у него есть продолжение. «Очистить», «Поиск» и
   «Показать все» стоят вне прокрутки и остаются на месте */
.fgroup__list {
  max-height: 360px;
  overflow-y: auto;
  /* Колесо над списком не протаскивает страницу, когда список кончился */
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: var(--line-strong) transparent;
}
/* ============================================================
   Числовой фильтр: ползунок, риски, поля «от … до …» и пилюли.

   Заказчик 12.10.2026: сначала выбрал гистограмму, но она показалась
   перенасыщенной — вернулись к варианту В из макетов
   (prototype/_sources/range-variants.html): ползунок тот же, что у цены,
   под ним риски шкалы, строка «от … до …» и пилюли частых значений
   с живой цифрой (нажатие оставляет ровно это значение).
   Трек, заливку и ручки даёт общий компонент .price-range.
   ============================================================ */
.range-box__row {
  display: flex; align-items: baseline; gap: 6px; margin-top: 2px;
  font-size: .84rem; color: var(--ink-3);
}
.range-box__row input {
  width: 100%; min-width: 0; border: 0; border-bottom: 1px solid var(--line-strong);
  background: transparent; padding: 2px 0; font: inherit; font-size: .84rem; color: var(--ink);
}
.range-box__row input:hover { border-bottom-color: var(--ink-3); }
.range-box__row input:focus { outline: none; border-bottom-color: var(--accent); }
.range-box__row span { flex: none; }
/* Пилюли частых значений: значение и живая цифра. Ряд не переставляется от
   галочек (набор и порядок — из позиций папки), а значение, до которого
   фильтры уже не оставляют ни одной позиции, стоит приглушённым и выключенным —
   как галочки в панели */
/* Пилюли — сеткой в две колонки: так у всех одна ширина, а значение и цифра
   стоят каждый в своей колонке, как в строках-галочках (заказчик 12.10.2026:
   «выровняй структуру» — пилюли были по ширине содержимого, и цифры шли
   лесенкой). В три колонки не влезают длинные значения («10 000 878») */
.pills { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; margin-top: 14px; }
/* Стандартные значения цветовой температуры в модуле «Световые характеристики»:
   та же сетка пилюль, но отступ меньше — они стоят прямо под полями «от/до» */
.light-pills { gap: 8px; margin: 8px 0 14px; }
.pill {
  display: inline-flex; align-items: baseline; gap: 6px;
  border: 1px solid var(--line-strong); border-radius: 999px; background: var(--surface);
  padding: 6px 11px; font: inherit; font-size: .84rem; color: var(--ink);
  cursor: pointer; transition: border-color .16s, background .16s, color .16s;
}
/* Цифра — к правому краю пилюли, как счётчик у значений-галочек */
.pill em { margin-left: auto; font-style: normal; font-size: .72rem; color: var(--ink-3); }
.pill:hover { border-color: var(--ink); }
.pill.on { background: var(--accent); border-color: var(--accent); }
.pill.on em { color: rgba(24, 24, 16, .7); }
.pill.is-off { color: var(--ink-3); cursor: default; }
.pill.is-off:hover { border-color: var(--line-strong); }
/* На выбранной пилюле фон жёлтый — плашке нужна светлая обводка, иначе её
   не видно на жёлтом */
.pill.on .k-sw { box-shadow: 0 0 0 1.5px rgba(255, 255, 255, .85); }
/* «Очистить» у группы — как у Arlight: ссылка под названием и только когда в
   группе что-то отмечено. Тот же вид, что у «Сбросить» в заголовке панели */
.fgroup__clear,
.fgroup__all {
  display: block; margin: 0 0 10px; padding: 0;
  border: 0; border-bottom: 1px solid transparent; background: transparent;
  font: inherit; font-size: .82rem; color: var(--ink-3); cursor: pointer;
  transition: color .16s, border-color .16s;
}
.fgroup__clear:hover,
.fgroup__all:hover { color: var(--ink); border-bottom-color: var(--accent); }
.fgroup__clear:focus-visible,
.fgroup__all:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; border-radius: 2px; }
/* Строка «Очистить» есть у каждой группы всегда: когда снимать нечего, она
   невидима, но место занимает — иначе первая галочка толкала бы вниз поля и
   список (заказчик 12.10.2026) */
.fgroup__clear.is-idle { visibility: hidden; }
/* Поле «Поиск» у длинной группы: «Модель экрана» — 147 значений, глазами их
   не перебрать. Появляется от 20 значений (SEARCH_FROM в catalog.html) */
.fgroup__search {
  width: 100%; margin: 0 0 10px; padding: 8px 10px;
  border: 1px solid var(--line-strong); border-radius: var(--r-sm);
  background: var(--surface); font: inherit; font-size: .89rem; color: var(--ink);
}
.fgroup__search::placeholder { color: var(--ink-3); }
.fgroup__search:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.fgroup__empty { margin: 4px 0 0; font-size: .84rem; }
/* Значение, до которого текущие фильтры не оставляют ни одной позиции: остаётся
   на месте приглушённым и выключенным, чтобы список не уезжал под курсором
   между двумя нажатиями. Раньше такие значения просто исчезали */
.check.is-off { color: var(--ink-3); cursor: default; }
.check.is-off input { border-color: var(--line); background: transparent; }
.check.is-off:hover { color: var(--ink-3); }
/* Строку поиска прячем классом, а не атрибутом hidden: у .check свой display */
.check.is-hidden { display: none; }
.fgroup__empty[hidden] { display: none; }

/* «Вопросик» с пояснением — как у Arlight в характеристиках позиции: там шаг
   расстановки светодиодов тоже объяснён всплывающей карточкой, а не сноской.
   Подсказка на чистом CSS: ждём наведение или фокус с клавиатуры (tabindex=0).
   Внутри label значок — ссылка, а не span: интерактивный элемент не переключает
   галочку, а клик по «?» уводит на страницу с объяснением. Сам знак нарисован
   в разметке (hintIcon в lists.js): у шрифта сайта «?» наклонный, и в кружке он
   выглядел кривым, поэтому от набора отказались.
   Отступ значка подобран так, чтобы зазор до текста был одинаковым везде:
   в строке текста (шапка группы, таблица характеристик) это 3 px, а в
   галочке-метке строка флексовая с зазором 10 px — там 3 - 10 = -7 px
   (заказчик 12.10.2026: «сделай одинаково вопросик, расстояние разное»,
   в карточке значок налезал на текст: было -3 px от базового правила) */
.hint {
  position: relative; flex: none; display: inline-grid; place-items: center;
  width: 16px; height: 16px; margin-left: 3px;
  color: var(--ink-3); text-decoration: none; cursor: help;
  transition: color .16s;
}
.hint svg { display: block; }
.hint:hover { color: var(--ink); }
.hint:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 50%; }
/* В галочке-метке строка флексовая с зазором 10 px: компенсируем, чтобы зазор
   до текста был тот же, что в шапке группы и в таблице характеристик */
.check .hint { margin-left: -7px; }
.hint__tip {
  position: absolute; left: 0; bottom: calc(100% + 8px); z-index: 30;
  width: 250px; padding: 10px 12px; border-radius: var(--r-sm);
  background: var(--surface); border: 1px solid var(--line);
  box-shadow: var(--shadow-lift);
  font-size: .78rem; font-weight: 400; line-height: 1.45; text-align: left;
  color: var(--ink-2);
  opacity: 0; visibility: hidden; transition: opacity .14s, visibility .14s;
}
.hint:hover .hint__tip, .hint:focus-visible .hint__tip { opacity: 1; visibility: visible; }

/* ============================================================
   Атрибут hidden должен побеждать.
   У .products задан display:grid, а правило из таблицы стилей
   сильнее служебного [hidden] из браузера — из-за этого переключение
   «Сетка / Списком» не скрывало сетку и список открывался ниже неё.
   ============================================================ */
[hidden] { display: none !important; }

/* ============================================================
   Вид «Списком»: колонка наименования и картинки.
   По умолчанию таблица делила ширину поровну, и наименование
   ломалось на пять строк. Отдаём ему всё свободное место, а узкие
   колонки сжимаем до содержимого; фото в списке увеличиваем.

   Замер 16.10.2026 (раздел «Дизайнерский свет», экран 1280, вид «Списком»):
   таблица занимала 975 px при колонке товаров 869, то есть шире экрана на 74 px,
   а наименование получало 146 px — пять строк. Минимум задавали не значения,
   а то, что в ячейках стоял запрет переноса: заголовок «ХАБАРОВСК» шире своего
   значения, старая цена акции стояла в одной строке с новой, три плашки
   документов — в ряд, значки и «В корзину» — в одну строку. Ниже запрет переноса
   снят там, где он не нужен: таблица укладывается в 869 px, наименование
   получает 197 px (три строки вместо пяти)
   ============================================================ */
.ptable__media { width: 96px; min-width: 96px; padding-right: 4px; }
.ptable__media img { width: 84px; height: 84px; max-width: none; }

/* Колонки узкие ровно по содержимому, всё свободное место забирает
   наименование. Раньше ширину задавали длинные заголовки, из-за этого
   название ломалось на пять строк. */
.ptable th:nth-child(3),
.ptable td:nth-child(3) { width: 100%; }
.ptable th:nth-child(n + 4),
.ptable td:nth-child(n + 4) { width: 1px; white-space: nowrap; }
.ptable th, .ptable td { padding-left: 6px; padding-right: 6px; }

/* Заголовки узких колонок длиннее своих значений и задавали им минимум:
   «ХАБАРОВСК» занимал 96 px там, где значение — 60. Меньше буквы и разрядка —
   колонки отдают наименованию около сорока пикселей */
.ptable th { font-size: .7rem; letter-spacing: .04em; }

/* Остатки переносим по словам: «более 1 000 шт» в одну строку держало колонку
   шире своего заголовка. Разряды числа при этом не рвутся — Intl.NumberFormat
   в русской раскладке разделяет их неразрывным пробелом. Селектор с классом
   на ячейке обязателен: выше стоит общий запрет переноса для колонок с
   четвёртой (у него вес тот же, и побеждает он по порядку, а не по весу) */
.ptable td.ptable__num { white-space: normal; }
/* У плашек документов своей ширины нет, её задаёт width: 1px из общего правила,
   поэтому колонке дан минимум: в строку встают две плашки, третья уходит ниже.
   Высота строки от этого не растёт — её держит кадр в 84 px. Перенос даёт <wbr>
   между плашками (docBadges в lists.js): соседние строчные блоки без
   разделителя — одно неразрывное слово */
.ptable td.ptable__doc-cell { white-space: normal; min-width: 94px; }
.ptable__doc { margin: 2px 4px 2px 0; padding: 3px 7px; font-size: .72rem; }

/* Старая цена акции («−30 %» у участников) — своей строкой: рядом с новой
   ценой она держала колонку в 150 px */
.ptable__sum s { display: block; }
.ptable__sum b { font-size: .96rem; }

.ptable__art-col { font-size: .8rem; }
.ptable__name { padding-right: 8px; }
.ptable__act { padding-left: 6px; }
.ptable__act .btn { white-space: nowrap; padding-left: 11px; padding-right: 11px; }
.ptable__tools { gap: 4px; }
/* Значки избранного и сравнения — строкой выше «В корзину»: в одну строку они
   держали колонку в 176 px, хотя занимали 68 и 90 (замер 16.10.2026). Врозь
   колонка равна более широкому из двух — значки встают над кнопкой, у правого
   края. Раскрытая плашка «Убрано · Вернуть» идёт следом, своей строкой: она
   живёт четыре секунды и на ширину колонки не влияет */
.ptable__act .ptable__tools { display: flex; justify-content: flex-end; margin: 0 0 6px; }

/* ============================================================
   Карточка позиции: колонка с галереей.
   Приклеивать её нельзя: пока обе колонки одной высоты, галерея ведёт
   себя как обычная, а как только справа раскроются «Все характеристики»,
   у неё появляется место — и фото прыгает вниз на три сотни пикселей.
   Пусть лучше колонка едет вместе со страницей.
   ============================================================ */
.gallery__main img { width: 84%; }

/* ============================================================
   Плитка товара: клик по фото тоже открывает карточку.
   Ссылку кладём поверх картинки отдельным слоем, а не оборачиваем
   изображение — иначе кнопка «в избранное» оказалась бы внутри ссылки,
   а так она просто лежит выше по слою.
   ============================================================ */
.pcard__link { position: absolute; inset: 0; z-index: 1; border-radius: inherit; }
.pcard__wish { z-index: 2; }
.pcard__media a img { pointer-events: none; }

/* В списке фото тоже ведёт в карточку */
.ptable__media a { display: block; }

/* ============================================================
   Плитка товара: теги и минимальный объём закупки.
   Arlight помечает новинки флажком, а покраску по RAL — тегом.
   Норму упаковки показывает суммой за
   минимальный объём — закупщику это важнее цены за единицу.
   ============================================================ */
.pcard__tags { display: flex; flex-wrap: wrap; gap: 6px; }
.pcard__tags span {
  font-size: .72rem; color: var(--ink-2);
  background: var(--field); border-radius: 4px; padding: 3px 8px;
}

.pcard__pack { font-size: .78rem; color: var(--ink-3); line-height: 1.5; }
.pcard__pack b { color: var(--ink); font-weight: 600; }

/* На карточке позиции теги стоят рядом с гарантией */
.badges .badge.flag { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }

/* ============================================================
   Избранное, сравнение и быстрый просмотр.
   Сердечко и весы — в правом верхнем углу снимка, быстрый просмотр —
   по наведению внизу. Так же устроена плитка на сайте Arlight.
   ============================================================ */

.pcard__tools { position: absolute; top: 10px; right: 10px; display: grid; gap: 6px; z-index: 3; }
.pcard__wish, .pcard__cmp {
  width: 32px; height: 32px; padding: 0; border-radius: 50%;
  border: 1px solid var(--line); background: rgba(255, 255, 255, .92);
  color: var(--ink-3); display: grid; place-items: center; cursor: pointer;
  transition: color .16s, border-color .16s, background .16s;
}
.pcard__wish:hover, .pcard__cmp:hover { color: var(--ink); border-color: var(--ink-3); }
.pcard__wish.on { color: #d13b3b; border-color: #d13b3b; }
.pcard__wish.on svg { fill: currentColor; }
.pcard__cmp.on { color: var(--accent-ink); border-color: var(--accent); background: var(--accent); }

/* ============================================================
   Избранное: удаление с задержкой (assets/lists.js, startPending).

   В избранном сердечко — единственный способ убрать позицию, и промах
   стоил бы всей карточки: нажатие не удаляет сразу. Карточка гаснет и пять
   секунд ждёт «Вернуть». Гасим всё, кроме сердечка и плашки, — они и
   остаются рабочими: повторное нажатие по сердечку удаление отменяет.
   ============================================================ */
.pcard.is-pending .pcard__media > :not(.pcard__tools),
.pcard.is-pending .pcard__body,
tr.is-pending td:not(.ptable__act),
tr.is-pending .ptable__act > :not(.ptable__tools):not(.ptable__undo) {
  opacity: .35; pointer-events: none;
}

/* Сердечко выше плашки: плашка накрывает снимок целиком, и без этого
   второго нажатия по сердечку не было бы, а им удаление и отменяют */
.pcard.is-pending .pcard__tools { z-index: 5; }

/* Плашка в плитке — слой на весь снимок, но клики ловит только сама кнопка:
   прозрачный слой закрыл бы карточку целиком. Слой ровно по снимку (он
   квадратный, как и карточка по ширине), а не по всей карточке — иначе
   плашка встала бы на подписи с ценой */
/* Плашка позиционируется от самой карточки: у .pcard нет position, и без
   этой строки слой отсчитывался бы от общего предка — вставая посреди сетки,
   а не на карточке */
.pcard.is-pending { position: relative; }
.pcard__undo {
  position: absolute; top: 0; left: 0; right: 0; aspect-ratio: 1 / 1; z-index: 4;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 6px; pointer-events: none;
}
.pcard__undo > * { pointer-events: auto; }
.undo-label {
  font-size: .72rem; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-2);
}
/* Плашка лежит на содержимом — снимке в плитке: подписи и кнопке нужен свой
   фон, иначе они читаются поверх притемнённого фото */
.pcard__undo .undo-label {
  background: var(--surface); border-radius: 4px; padding: 3px 8px;
  box-shadow: 0 1px 4px rgba(24, 24, 16, .18);
}
/* Кнопка поверх снимка белая, как «Быстрый просмотр»: прозрачная с тёмным
   текстом читается не на всяком фото */
.pcard__undo .btn {
  background: var(--surface); box-shadow: 0 6px 18px -10px rgba(24, 24, 16, .6);
}
.pcard__undo .btn:hover { background: var(--surface); border-color: var(--ink); }

/* В строке списка плашка встаёт в колонку действий, рядом с «В корзину» */
.ptable__undo { display: inline-block; margin-left: 8px; vertical-align: middle; white-space: nowrap; }
.ptable__undo .btn { margin-left: 6px; }

/* Избранное и сравнение на странице позиции — значками на фото (.gallery__tools
   и .pcard__wish/.pcard__cmp): так они выглядят и на плитке каталога, и в быстром
   просмотре. Раньше это были кнопки-таблетки в правой колонке — заказчик попросил
   убрать их оттуда и поставить на фото, как везде. */

/* Точки-указатель кадров: без них не видно, что фото листается. Сверху по
   центру — там не мешают ни «Новинка» слева, ни кнопки справа, ни «Быстрый
   просмотр», который выезжает снизу по наведению */
/* Точки-миниатюры: опущены с 10 px до 16 px — при отступе кадра 10 px они
   ложились ровно на его верхнюю границу и читались как часть фотографии
   (заказчик 13.10.2026: «точки лежат прям на границе, некрасиво») */
.pcard__dots {
  position: absolute; top: 16px; left: 50%; transform: translateX(-50%);
  display: flex; gap: 5px; z-index: 2; pointer-events: none;
}
.pcard__dots i {
  width: 6px; height: 6px; border-radius: 50%;
  background: rgba(24, 24, 16, .2);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .75);
  transition: background .16s;
}
.pcard__dots i.on { background: rgba(24, 24, 16, .72); }

.pcard__quick {
  position: absolute; left: 50%; bottom: 12px; transform: translateX(-50%);
  border: 1px solid var(--line-strong); border-radius: 6px; padding: 7px 14px;
  background: rgba(255, 255, 255, .95); color: var(--ink);
  font: inherit; font-size: .8rem; cursor: pointer; white-space: nowrap;
  opacity: 0; transition: opacity .16s; z-index: 3;
}
.pcard__media:hover .pcard__quick, .pcard__quick:focus-visible { opacity: 1; }
@media (hover: none) { .pcard__quick { opacity: 1; } }

/* Счётчики избранного и сравнения в шапке */
.head-icons { display: flex; align-items: center; gap: 8px; }
.head-icon {
  position: relative; width: 40px; height: 40px; flex: none;
  border-radius: var(--r-sm); border: 1px solid rgba(24, 24, 16, .4);
  color: var(--ink); display: grid; place-items: center;
  transition: border-color .16s, background .16s;
}
.head-icon:hover { border-color: var(--ink); }
.head-icon__count {
  position: absolute; top: -6px; right: -6px; min-width: 18px; height: 18px;
  border-radius: 9px; background: var(--ink); color: #fff;
  font-size: .68rem; line-height: 1; display: grid; place-items: center; padding: 0 5px;
}

/* Быстрый просмотр: мини-карточка позиции — кадры галереи, файлы изделия и
   общие характеристики. Плитка знает одно фото и один документ, остальное окно
   добирает из файла деталей раздела, когда его открыли (assets/lists.js) */
/* Класс окна — .quick-modal, а не .quick: под .quick в этом файле выше живут
   «быстрые ссылки» на страницах (block-пилюли), и общее имя превращало блок
   ссылок на «О компании» в тёмный оверлей на весь экран */
/* Колонка сетки — minmax(0, 1fr), а не auto: иначе дорожку раздувает содержимое
   (длинное название позиции), и на телефоне окно вылезало за экран (679 px при 390) */
/* place-items: start center, а не center: окно раскрывается файлом данных, и
   при центрировании растущая панель уезжала вверх вместе со всем содержимым —
   при загрузке файлов и характеристик всё «дёргалось». С привязкой к верху
   рост идёт только вниз, а содержимое стоит на месте */
.quick-modal { position: fixed; inset: 0; z-index: 110; padding: 24px; background: rgba(18, 18, 14, .55); display: grid; grid-template-columns: minmax(0, 1fr); place-items: start center; }
.quick-modal[hidden] { display: none; }
.quick__panel {
  position: relative; width: 100%; min-width: 0; max-width: 900px; max-height: 90vh; overflow: auto;
  background: var(--bg); border-radius: var(--r-lg);
  /* Левая колонка шире правой: кадр должен быть крупным, а правая колонка —
     узкой, как у Arlight. Пропорция 1.2 : 1 */
  display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
}
.quick__media {
  position: relative; min-width: 0; background: var(--surface); padding: 22px;
  /* Группа (кадр, под ним миниатюры и файлы) стоит по центру колонки: заказчик
     просил не прижимать кадр к верху, а миниатюры показывать сразу за ним */
  display: grid; grid-template-rows: auto auto; gap: 14px; align-content: center;
}
/* Кадр, под ним — миниатюры, ещё ниже — файлы изделия. Стрелки лежат поверх
   кадра, поэтому у них своя ячейка внутри .quick__shot-cell */
.quick__shot-cell { position: relative; display: grid; place-items: center; min-width: 0; }
/* Низ группы: миниатюры и файлы вместе */
.quick__foot { display: grid; gap: 14px; min-width: 0; }
.quick__nav {
  position: absolute; top: 50%; transform: translateY(-50%);
  width: 34px; height: 34px; padding: 0; border-radius: 50%; cursor: pointer;
  border: 1px solid var(--line-strong); background: rgba(255, 255, 255, .92);
  color: var(--ink); font: inherit; font-size: 1.15rem; line-height: 1;
  display: grid; place-items: center; transition: background .16s, border-color .16s;
}
.quick__nav:hover { background: #fff; border-color: var(--ink); }
.quick__nav--prev { left: 0; }
.quick__nav--next { right: 0; }
/* Кадр и запасная подпись «Арт. … нет фото» лежат в одной ячейке: если фото
   отдалось, подпись скрыта (фото идёт с прозрачным фоном, и текст просвечивал
   бы сквозь него); если не отдалось — картинка прячется, подпись встаёт на её
   место, см. shotHtml/setShot в lists.js.
   Высота кадра задана жёстко: пока фото не пришло, места под него столько же,
   сколько под загруженное, — иначе миниатюры с файлами подпрыгивают, когда
   картинка появляется (и второй раз, когда кадр плитки сменяется кадром раздела) */
/* Строка сетки ограничена высотой рамки (minmax(0, 1fr)): без этого авто-строка
   растягивалась по картинке, фото вылезало за рамку и накрывало миниатюры с
   файлами — «наезжает на остальное». max-height у самой картинки считается от
   высоты строки, поэтому строку и надо ограничить */
.quick__shot { display: grid; grid-template-rows: minmax(0, 1fr); place-items: center; width: 100%; height: 340px; }
.quick__shot > * { grid-area: 1 / 1; }
.quick__shot img { max-width: 100%; max-height: 100%; mix-blend-mode: multiply; }
.quick__noimg { color: var(--ink-3); font-size: .84rem; text-align: center; line-height: 1.5; display: none; }
/* Подпись показываем в двух случаях: фото у позиции нет вовсе (подпись стоит
   одна) и фото не отдалось (картинка спрятана классом .is-broken) */
.quick__shot > .quick__noimg:only-child { display: block; }
.quick__shot.is-broken img { display: none; }
.quick__shot.is-broken .quick__noimg { display: block; }
/* Миниатюры — строкой под кадром, без прокрутки: кадров у позиции немного
   (в основном 1–5), а ползунок в колонке мешал и выглядел случайным */
.quick__thumbs { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; }
.quick__thumbs:empty { display: none; }
.quick__thumbs button {
  width: 52px; height: 52px; padding: 4px; border-radius: var(--r-sm); cursor: pointer;
  border: 1px solid var(--line); background: var(--surface);
  display: grid; place-items: center; transition: border-color .16s;
}
.quick__thumbs button:hover, .quick__thumbs button.on { border-color: var(--ink); }
.quick__thumbs img { max-width: 100%; max-height: 100%; mix-blend-mode: multiply; }
/* Файлы изделия — в нижнем блоке колонки, под миниатюрами */
.quick__files { min-width: 0; }
.quick__files .label { margin: 0 0 8px; }
/* Пока файл раздела не приехал, место под характеристики не придерживаем:
   фиксированные 300 px не совпадали с настоящей таблицей (от пустой до
   14 строк), и окно сначала вырастало, а потом прыгало на 18–286 px. Теперь
   окно только дорастает, когда характеристики приехали (заказчик 13.10.2026).
   display: block — потому что общее правило «пустой блок из сетки выпадает»
   (.quick__body > :empty) иначе прячет этот блок вместе с его местом */
.quick-modal:not(.is-loaded) #quick-props { display: block; }
/* Те же кнопки, что на снимке плитки: сердечко и весы в углу фото */
.quick__tools { position: absolute; top: 14px; right: 14px; display: grid; gap: 6px; z-index: 3; }
.quick__body { padding: 24px 26px; display: grid; gap: 12px; align-content: start; min-width: 0; }
.quick__body h3 { font-size: 1.22rem; overflow-wrap: anywhere; }
.quick__body a { overflow-wrap: anywhere; }
.quick__meta { color: var(--ink-3); font-size: .84rem; }
/* Бренд логотипом — те же 22 px высоты, что в карточке позиции (.pdp__brand) */
.quick__brand { display: inline-block; }
.quick__brand img { height: 22px; width: auto; display: block; }
/* Строка «Арт. 041880 ⧉» и кнопка «Страница серии» — одной строкой. Отступ
   справа — под крестик закрытия: он висит в том же верхнем углу, и без запаса
   накрывал кнопку серии */
.quick__art {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  color: var(--ink-3); font-size: .86rem;
  padding-right: 44px;
}
.quick__art .btn { margin-left: auto; }
/* Пустые блоки (метки, короткие характеристики, упаковка) не должны оставлять
   промежуток: сетка даёт по 12 px зазора на каждый, даже на пустой */
.quick__body > :empty { display: none; }
.quick__close {
  position: absolute; top: 12px; right: 14px; z-index: 4;
  width: 36px; height: 36px; padding: 0; border-radius: 50%;
  border: 1px solid var(--line-strong); background: rgba(255, 255, 255, .94);
  color: var(--ink); font: inherit; font-size: 1.2rem; line-height: 1; cursor: pointer;
}
.quick__close:hover { border-color: var(--ink); }
/* Цена и кнопка покупки — как в плитке: одной строкой под чертой */
.quick__buy {
  display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap;
  padding-top: 12px; border-top: 1px solid var(--line);
}
.quick__price { display: flex; align-items: baseline; gap: 10px; }
.quick__price b { font-size: 1.7rem; font-weight: 600; letter-spacing: -0.03em; }
.quick__price em { font-style: normal; color: var(--ink-3); font-size: .84rem; }
.quick__actions { display: flex; gap: 10px; flex-wrap: wrap; }
.quick__actions .btn { flex: 1; }
/* Общие характеристики: подпись серым, значение тёмным, как у Arlight */
.quick__specs { width: 100%; border-collapse: collapse; font-size: .86rem; }
.quick__specs td { padding: 8px 10px; vertical-align: top; }
.quick__specs tr:nth-child(odd) td { background: var(--surface); }
.quick__specs td:first-child { color: var(--ink-3); width: 46%; }
#quick-props .label { margin-bottom: 8px; }

/* Описание серии на странице серии: текст поставщика под заголовком */
.cat-about { max-width: 78ch; margin: 0 0 34px; color: var(--ink-2); font-size: .92rem; line-height: 1.6; }
.cat-about p { margin: 0 0 10px; }
.cat-about p:last-child { margin-bottom: 0; }
.cat-about .label { margin: 18px 0 8px; }
.cat-about__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 5px; font-size: .88rem; }
.cat-about__list li { color: var(--ink-3); }
.cat-about__list b { color: var(--ink-2); font-weight: 500; }

/* Ссылка на серию в подписи плитки и в списке: подчёркиваем фирменным
   жёлтым, как остальные ссылки на сайте — иначе серия читается как текст */
.serie-link { color: var(--ink-2); border-bottom: 1px solid var(--accent); }
.serie-link:hover { color: var(--ink); border-bottom-color: var(--ink); }

/* Бренд: в списках — словом тёмным полужирным, чтобы читался раньше серии
   (серия остаётся обычной ссылкой с подчёркиванием); в карточке позиции —
   логотипом своей строкой под названием */
.brand-link { color: var(--ink); font-weight: 600; border-bottom: 1px solid transparent; }
.brand-link:hover { border-bottom-color: var(--accent); }
/* Логотип бренда в мете плитки и строки списка: высота как у строки шрифта,
   иначе картинка раздвигает строку и плитки в ряду встают по-разному */
.pcard__meta .brand-link img { height: 14px; width: auto; display: inline-block; vertical-align: -2px; }
.ptable__art .brand-link img { height: 14px; width: auto; display: inline-block; vertical-align: -2px; }
.cart-row .brand-link img, .cmp .brand-link img { height: 14px; width: auto; display: inline-block; vertical-align: -2px; }
.pdp__brand { display: inline-block; margin-top: 12px; }
.pdp__brand img { height: 22px; width: auto; display: block; }

/* ============================================================
   Бренды: список брендов и страница бренда
   ============================================================ */

.brand-list { display: grid; gap: 16px; }
.brand-card {
  display: grid; grid-template-columns: 200px 1fr auto; align-items: center; gap: 24px;
  padding: 24px 28px; border: 1px solid var(--line); border-radius: var(--r-lg);
  background: var(--surface); color: var(--ink);
}
.brand-card:hover { border-color: var(--ink-3); }
.brand-card__logo { display: grid; place-items: center; min-height: 56px; }
.brand-card__logo img { max-width: 100%; }
.brand-card__text { display: grid; gap: 5px; }
.brand-card__text b { font-weight: 600; font-size: 1.05rem; }
.brand-card__text span { color: var(--ink-2); font-size: .9rem; }
.brand-card__text em { font-style: normal; color: var(--ink-3); font-size: .82rem; }
.brand-card__go { color: var(--ink-3); font-size: .88rem; white-space: nowrap; }
.brand-card:hover .brand-card__go { color: var(--ink); }
.brand-card--soon { background: transparent; border-style: dashed; grid-template-columns: 1fr auto; }

.brand-head { display: grid; grid-template-columns: 280px 1fr; gap: 44px; align-items: center; padding: 26px 0 26px; }
.brand-head__logo { background: var(--surface); border-radius: var(--r-lg); padding: 32px; display: grid; place-items: center; }
.brand-head__logo img { max-width: 100%; }

@media (max-width: 800px) {
  .brand-card { grid-template-columns: 1fr; gap: 14px; }
  .brand-head { grid-template-columns: 1fr; gap: 20px; }
}

@media (max-width: 800px) {
  .quick-modal { padding: 12px; }
  .quick__panel { grid-template-columns: 1fr; }
  .quick__media { padding: 18px; }
  .quick__shot { height: 240px; }        /* высота та же жёсткая — иначе прыгает */
  .quick__thumbs button { width: 46px; height: 46px; }
  .quick__body { padding: 20px; }
}

/* ---- Блоки страницы серии (assets/series-extras.js) ---- */
.sx-block { margin: 0 0 40px; }
.sx-block h2 { font-size: 1.05rem; margin: 0 0 16px; }
.sx-shots { display: grid; grid-template-columns: repeat(6, 1fr); gap: 10px; }
.sx-shot { display: block; aspect-ratio: 1; border-radius: 10px; overflow: hidden; background: #f2f1ee; }
.sx-shot img { width: 100%; height: 100%; object-fit: cover; }
.sx-figs { display: grid; gap: 30px; }
.sx-fig { display: grid; grid-template-columns: minmax(0, 420px) minmax(0, 1fr); gap: 26px; align-items: center; }
.sx-fig img { width: 100%; border-radius: 12px; }
.sx-fig b { display: block; margin: 0 0 8px; font-size: 1rem; }
.sx-fig p { margin: 0 0 8px; color: var(--ink-2); font-size: .92rem; line-height: 1.6; }
.sx-specs .sx-spec { border-top: 1px solid var(--line); padding: 14px 0 4px; }
.sx-specs h3 { font-size: .78rem; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-3); margin: 0 0 10px; }
.sx-specs dl { display: grid; grid-template-columns: minmax(0, 240px) minmax(0, 1fr); gap: 6px 20px; margin: 0; font-size: .92rem; }
.sx-specs dt { color: var(--ink-3); }
.sx-specs dd { margin: 0; color: var(--ink-2); }
.sx-doc-list { display: flex; gap: 10px; flex-wrap: wrap; }
.sx-video-list { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
.sx-video { display: block; color: inherit; text-decoration: none; }
/* Кнопка-обложка Rutube: сбрасываем стили кнопки, клик запускает плеер здесь же */
button.sx-video { width: 100%; padding: 0; border: 0; background: none; font: inherit; text-align: left; cursor: pointer; }
.sx-video__frame {
  position: relative; aspect-ratio: 16 / 9; border-radius: 10px;
  overflow: hidden; background: #000;
}
.sx-video__frame iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.sx-video img { width: 100%; border-radius: 10px; }
.sx-video__date { display: block; color: var(--ink-3); font-size: .78rem; margin: 8px 0 4px; }
.sx-video b { display: block; font-size: .94rem; line-height: 1.4; }
.sx-video p { margin: 6px 0 0; color: var(--ink-3); font-size: .86rem; line-height: 1.5; }
@media (max-width: 900px) {
  .sx-shots { grid-template-columns: repeat(3, 1fr); }
  .sx-fig, .sx-specs dl { grid-template-columns: 1fr; }
  .sx-video-list { grid-template-columns: 1fr; }
}

/* ============================================================
   Шапка на телефоне.

   У поиска в шапке min-width 250 px, поэтому в строку 390 px шапка не
   влезала: сжиматься мог только логотип, и он схлопывался в ноль — на
   телефоне не было видно ни логотипа, ни части значков (они уезжали за
   край и обрезались). Здесь: длинную надпись заменяем фирменным знаком
   (он узнаётся и без неё), поиск отдаём под остаток ширины, «Войти» —
   пока заглушка, убираем: поиск и корзина важнее.
   ============================================================ */
@media (max-width: 620px) {
  .header .wrap { gap: 10px; height: 60px; padding: 0 12px; }
  /* Знак вместо надписи: тот же, что в фирменном блоке, — чёрный на жёлтом */
  .header .brand {
    flex: none; width: 30px; height: 30px;
    background: url(img/logo-mark-on-yellow.svg) center / contain no-repeat;
  }
  .header .brand img { display: none; }
  .header .head-actions { margin-left: auto; gap: 6px; flex: 1 1 auto; justify-content: flex-end; min-width: 0; }
  .header .search-inline { flex: 1 1 92px; min-width: 92px; padding: 7px 12px; }
  .header .search-inline input { min-width: 0; }
  .header .head-actions > .btn.ghost { display: none; }
  .header .head-spec { width: 36px; height: 36px; }
}

/* ============================================================
   Заголовки страниц и строка поиска на телефоне.

   Кнопки в .cat-head (у раздела их две: прайс и выгрузка; у поиска —
   сортировка) стоят справа в одну строку и в 390 px не влезали: их обрезало
   краем. Ставим их под заголовком и разрешаем перенос. В строке поиска та же
   беда с кнопками «По фото» и «Найти» — поле отдаём на всю ширину, кнопки
   уходят под него.
   ============================================================ */
@media (max-width: 620px) {
  .cat-head { flex-direction: column; align-items: flex-start; gap: 14px; padding: 14px 0 20px; }
  .cat-head .push { margin-left: 0; flex-wrap: wrap; }
  .bigsearch { flex-wrap: wrap; padding: 10px 12px; }
  .bigsearch input { flex: 1 1 100%; order: -1; padding: 8px 0 4px; }
}

/* Строка корзины на телефоне: счётчик количества и цена стояли в одной строке и
   на 390 px цена налезала на «+». Цену уводим на свою строку во всю ширину —
   читается спокойно, количество и крестик остаются на месте. */
@media (max-width: 620px) {
  .cart-row__qty { grid-column: 4; grid-row: 2; }
  .cart-row__sum { grid-column: 4 / span 2; grid-row: 3; text-align: right; }
  .cart-row__del { grid-column: 5; grid-row: 1; }
}

/* ============================================================
   Возвращаем на телефон верхнюю строку с городом и меню.

   На узком экране и .topbar (город, телефон), и .nav (Каталог, Бренды, …)
   были просто скрыты, и на телефоне не оставалось ни выбора города, ни меню:
   в каталог можно было попасть только с главной. Возвращаем: верхнюю строку —
   компактно (город и телефон, остальное прячем), меню — второй строкой шапки.
   Панели меню прижимаем на всю ширину шапки: у правых пунктов («Компания»)
   они уезжали за край экрана.
   ============================================================ */
@media (max-width: 620px) {
  .topbar { display: block; }
  .topbar .wrap { height: 34px; gap: 14px; padding: 0 12px; }
  .topbar__note, .topbar__im, .topbar .push, .topbar .wrap > a:last-child { display: none; }

  .header .wrap { flex-wrap: wrap; height: auto; padding: 8px 12px; gap: 8px 10px; }
  .header .brand { order: 1; }
  .header .head-actions { order: 2; }
  /* Меню — своя строка под знаком и поиском; position: relative нужен, чтобы
     панель считалась от шапки, а не от пункта меню */
  .header .nav {
    order: 3; flex: 1 0 100%; position: relative;
    display: flex; gap: 10px; font-size: .8rem; padding-top: 2px;
  }
  /* Пункты меню на телефоне — тап-цели: держим высоту около 30 px */
  .header .nav > .nmenu > summary { padding: 7px 0; font-size: .8rem; }
  .header .nav .nmenu { position: static; }
  .header .nav .nmenu__panel {
    left: 0; right: 0; top: calc(100% + 10px); width: auto; min-width: 0;
    max-height: 60vh; overflow-y: auto;
  }
}

/* Раскрытый список аксессуаров на узком экране: цена и кнопка уходят под
   название — иначе четыре колонки не помещаются в строку */
@media (max-width: 980px) {
  .sub-item { grid-template-columns: 48px minmax(0, 1fr); gap: 10px 12px; align-items: start; }
  .sub-item__media { width: 48px; height: 48px; }
  .sub-item__price, .sub-item__doc, .sub-item__act { grid-column: 2; text-align: left; }
}

/* На телефоне фиксированную ширину строки покупки снимаем: там кнопка и счётчик
   должны занимать всю ширину блока — так по ним проще попасть пальцем */
@media (max-width: 700px) {
  .buy-row { width: 100%; }
}

/* Избранное и сравнение в строке корзины: те же кнопки, что на плитке и в
   списке каталога. Ставим их рядом с названием, а не отдельной строкой под
   сведениями: отдельная строка удлиняла каждую строку корзины. Справа для них
   места нет — там счётчик количества, сумма и крестик */
.cart-row__head { display: flex; align-items: flex-start; gap: 12px; }
.cart-row__head .cart-row__name { flex: 1 1 auto; }
.cart-row__tools { display: flex; gap: 6px; flex: none; }
/* Фон снимаем у неподсвеченных кнопок; у сравнения в состоянии «добавлено»
   (.pcard__cmp.on) жёлтая заливка остаётся — иначе от подсветки видна одна
   рамка, и состояние читается как «кнопка чуть подсвечена» */
.cart-row__tools .pcard__wish { background: transparent; }
.cart-row__tools .pcard__cmp:not(.on) { background: transparent; }

/* На телефоне название забирает строку целиком, иконки уходят под него —
   там ширина дороже высоты: в узкой колонке название и так переносится */
@media (max-width: 620px) {
  .cart-row__head { flex-wrap: wrap; gap: 4px 12px; }
  .cart-row__head .cart-row__name { flex: 1 1 100%; }
}

/* ============================================================
   Документы изделия: тип помечаем цветом.

   Красный PDF — техдокументация на изделие: инструкция, паспорт, руководство.
   Зелёный PDF — бумаги о соответствии: сертификат, декларация, отказное и
   рекомендательное письма (так было до 11.10.2026, заказчик вернул 12.10.2026).
   Фотометрия — серый IES, модели — бирюзовый 3D. В данных тип не сохранён,
   поэтому его выводит docKind() (lists.js) по названию и расширению файла.
   ============================================================ */
.doc-list { display: flex; flex-wrap: wrap; gap: 10px; }
.doc {
  display: flex; align-items: center; gap: 10px; padding: 6px 12px 6px 6px;
  border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--surface);
  transition: border-color .16s;
}
.doc:hover { border-color: var(--ink-3); }
.doc:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.doc__tag {
  flex: none; min-width: 38px; height: 32px; padding: 0 5px; border-radius: 5px;
  display: grid; place-items: center; color: #fff;
  font-size: .68rem; font-weight: 600; letter-spacing: .05em;
}
.doc__tag--pdf { background: #c0392b; }
.doc__tag--cert { background: #2f7d4f; }
/* Карточка бумаги в реестре ФСА: это не файл и не бумага, а ссылка, поэтому
   отдельный синий ярлычок «LINK» (заказчик 17.10.2026: зелёная плашка с «PDF»
   на ссылке в реестр врала, «ФСА» тоже читалась как тип бумаги).
   Цвет нейтральнее зелёного сертификата и красного PDF, но отличен от обоих */
.doc__tag--link { background: #35507a; }
.doc__tag--ies { background: #5b5b54; }
.doc__tag--3d { background: #1f7f8c; }
.doc__tag--other { background: var(--ink-3); }
.doc__text { display: grid; gap: 2px; }
.doc__name { font-size: .85rem; color: var(--ink); }
.doc__size { font-size: .74rem; color: var(--ink-3); }

/* Тот же ярлычок в списке каталога: тип документа видно с первого взгляда */
.ptable__doc--pdf { background: #c0392b; color: #fff; }
.ptable__doc--cert { background: #2f7d4f; color: #fff; }
.ptable__doc--link { background: #35507a; color: #fff; }
.ptable__doc--ies { background: #5b5b54; color: #fff; }
.ptable__doc--3d { background: #1f7f8c; color: #fff; }
.ptable__doc--other { background: var(--ink-3); color: #fff; }

/* ============================================================
   Телефон: мессенджеры в верхней строке, значки к знаку, поиск во всю
   ширину, меню на одной линии.

   Заказчик с телефона: «вверху нет ссылок на мессенджеры, поиск сместился
   вниз зачем-то, а Каталог/Бренды/Проекты и тд не на одной линии». Разбор:
   — .topbar__im прятался правилом для ширины до 1100 px, и на телефоне
     мессенджеров не оставалось вовсе;
   — знак стоял один в своей строке, а поиск со значками уезжал под него:
     .head-actions вытягивал строку целиком (у поля поиска большая
     собственная ширина), поэтому знаку места рядом не оставалось;
   — пункты с выпадающим списком («Каталог», «Покупателям», «Компания») стоят
     на 3 px ниже обычных ссылок меню: у summary отступ 7 px, у ссылок — 4 px.
   ============================================================ */
@media (max-width: 620px) {
  /* Мессенджеры возвращаем: город, телефон и три значка в строку 360 px влезают.
     Остальное в верхней строке (подпись, прайс, сотрудничество) остаётся скрытым */
  .topbar__im { display: inline-flex; margin-left: auto; }
  .topbar .wrap { gap: 12px; }

  /* Значки (избранное, сравнение, корзина) встают в строку к знаку, а поиск
     занимает свою во всю ширину: рядом со значками поле сжимается до 200 px,
     и подпись «Артикул или название» обрезается. display: contents распускает
     .head-actions, и его содержимое раскладывается вместе со знаком и меню по
     общему order */
  .header .head-actions { display: contents; }
  .header .head-icons { order: 2; margin-left: auto; }
  .header .head-spec { order: 2; }
  .header .search-inline { order: 3; flex: 1 1 100%; }
  .header .nav { order: 4; }

  /* Значки одной мерки: у избранного и сравнения было 40 px, у корзины 36 */
  .header .head-icons .head-icon { width: 36px; height: 36px; }

  /* Знак снова с надписью: место справа от него освободилось, когда значки ушли
     к нему, а поиск — на свою строку. Берём тот же логотип, что на десктопе
     (знак и надпись одним файлом) */
  .header .brand { width: auto; height: auto; background: none; }
  .header .brand img { display: block; height: 30px; width: auto; }

  /* Пункты меню — на одну линию: одинаковые отступы у ссылок и у выпадашек */
  .header .nav { align-items: center; }
  .header .nav > a { padding: 7px 0; line-height: 1.2; }
  .header .nav > .nmenu > summary { line-height: 1.2; }
}

/* Совсем узкий экран (360 px и меньше): меню из пяти пунктов шире строки —
   «Компания» уезжала за край и появлялась горизонтальная прокрутка. Пункты
   те же, просто на полтора пикселя мельче и с меньшим зазором. Логотип здесь
   тоже мельче: со знаком и надписью он занимает всю строку до значков */
@media (max-width: 400px) {
  .header .nav { gap: 6px; font-size: .74rem; }
  .header .brand img { height: 26px; }
  .header .nav > .nmenu > summary { font-size: .74rem; }
}

/* Самые узкие экраны (320 px): город, телефон и мессенджеры в строку не влезали,
   и телефон уезжал второй строкой. Чуть мельче подписи и значки — влезают.
   Мессенджеры не прячем: за них и была правка. Меню из пяти пунктов в 320 px не
   влезает даже мелким шрифтом, поэтому здесь разрешаем ему перенос на две строки:
   обрезанный край хуже второй строки */
@media (max-width: 340px) {
  /* Телефон переносить нельзя: рвётся на две строки и налезает на шапку. Поэтому
     строке разрешаем стать выше и уложить мессенджеры второй строкой */
  .topbar .wrap {
    gap: 8px; font-size: .78rem; height: auto; min-height: 34px;
    padding: 6px 12px; flex-wrap: wrap; row-gap: 4px;
  }
  .topbar .wrap > a[href^="tel"] { white-space: nowrap; }
  .topbar__im { gap: 2px; }
  .topbar__im a { padding: 3px; }
  .header .nav { flex-wrap: wrap; row-gap: 2px; }
}

/* ============================================================
   Всплывающее «Найдено N» после правки фильтров.

   Заказчик: «сделай всплывающее сообщение о том, сколько нашлось — знаю, что у
   нас обновляется сразу и кнопка «Показать» не нужна, но информация полезная»,
   затем: «плашка должна быть рядом с той галочкой, которую добавил или убрал».
   Поэтому положение считает catalog.html (toastFound) по прямоугольнику того,
   что нажали: справа от строки, а если справа тесно — под ней. Хвостик слева
   указывает на строку, сверху — когда плашка встала под ней.
   ============================================================ */
.toast {
  position: fixed; z-index: 85;
  padding: 10px 14px; border-radius: var(--r-md);
  background: var(--dark); color: #fff; font-size: .88rem; white-space: nowrap;
  box-shadow: 0 18px 40px -24px rgba(23, 25, 27, .6);
  opacity: 0; pointer-events: none;   /* плашка только сообщает, кликать по ней нечего */
  transition: opacity .18s ease;
}
.toast.is-on { opacity: 1; }
.toast::before {
  content: ""; position: absolute; left: -4px; top: 50%;
  width: 8px; height: 8px; margin-top: -4px;
  background: var(--dark); transform: rotate(45deg);
}
.toast--below::before { left: 50%; top: -4px; margin: 0 0 0 -4px; }

/* ============================================================
   Подсказка у «вопросика» на узком экране.
   У метки «Индивидуальная покраска» и в характеристиках позиции значок «?»
   раскрывает карточку шириной 250 px вправо от себя. В панели фильтров значок
   стоит у правого края, и на телефоне карточка вылезала за экран — а так как
   лежит она в разметке всегда (скрыта прозрачностью), страница тянулась до
   505 px, и вслед за ней растягивалось окно быстрого просмотра: в нём за край
   уезжали крестик и «В корзину». На узком экране раскрываем карточку влево.
   Правило стоит в конце файла: базовое .hint__tip объявлено выше по тексту, а
   при равной специфичности побеждает последнее.
   ============================================================ */
@media (max-width: 980px) {
  .hint__tip { left: auto; right: 0; }
}

/* ============================================================
   Вид «Списком» и таблица сравнения: прокрутку отдаём самому блоку.
   Столбцы в них не сжимаются: в списке каталога их восемь и в ячейках стоит
   запрет переноса, в сравнении на каждую позицию своя колонка. На телефоне
   таблица выходила за экран (802 px при экране 390), и страница разъезжалась
   на 446 px; с 16.10.2026 то же случилось и на большом экране — список занимал
   975 px при свободных 901, и страница уезжала на 74 px вбок (на 1100 — на 202).
   Прокрутка на самом блоке чинит это на всех ширинах: страница остаётся по
   ширине экрана, а таблицу листают вбок, и только когда она правда не влезает —
   на 1280 список укладывается целиком, и полосы прокрутки нет вовсе.
   Панель фильтров и колонка товаров — элементы сетки, а у элемента сетки
   минимальная ширина по содержимому: без min-width: 0 колонка не даёт сжать
   себя под таблицу и тащит страницу за собой.
   ============================================================ */
#plist, #fav-plist, #cmp-table { overflow-x: auto; }
.catalog-layout > * { min-width: 0; }

/* ============================================================
   Таблица сравнения позиций (compare.html, собирает assets/compare.js).

   На каждую позицию колонка, на каждую характеристику строка — строк бывает
   под тридцать, поэтому держим на месте и шапку с позициями, и первую колонку
   с названиями характеристик: листая таблицу вбок, видно, какую строку
   читаешь. Липкая шапка работает только внутри прокручиваемого блока, а блок
   без заданной высоты растягивается по содержимому и не прокручивается вовсе
   — поэтому на широком экране у #cmp-table задана высота, и таблицу листают
   внутри блока, а не вместе со страницей. На узком экране высоту снимаем:
   там важнее листать таблицу вбок и не запирать страницу в две прокрутки.
   Прокрутка самого блока задана выше (@media 980px) и правилом ниже — там же,
   где вид «Списком»: у обоих столбцы не сжимаются.

   Жёлтой подложкой отмечены строки, где значения позиций разошлись
   (--accent-soft). Жёлтым текстом такое помечать нельзя: у --accent 1,7:1 на
   белом, это записано и в фирменном слое переменных.
   ============================================================ */
.cmp {
  width: 100%; border-collapse: separate; border-spacing: 0; font-size: .89rem;
  /* Ширина столбцов — раз и навсегда: при обычной (auto) раскладке браузер
     считает её от содержимого, и всё ехало, стоило содержимому шевельнуться —
     «В корзину» заменялся счётчиком количества (он шире), столбцы
     пересчитывались, названия переносились заново, а шапка и кнопки прыгали
     (заказчик 14.10.2026). При fixed ширина столбца берётся из первой строки, и
     содержимое на неё не влияет */
  table-layout: fixed;
  --cmp-label: 190px;   /* колонка с названиями характеристик */
  --cmp-col: 232px;     /* колонка позиции */
}
/* Минимальная ширина таблицы: со фиксированными столбцами без неё на телефоне
   столбцы сжались бы в нечитаемую полоску вместо горизонтальной прокрутки.
   Ширины — те же переменные, что у столбцов, поэтому медиазапрос на узком
   экране подхватывается сам; число колонок задаёт класс, его ставит compare.js
   (позиций в сравнении не больше четырёх) */
.cmp--1 { min-width: calc(var(--cmp-label) + var(--cmp-col)); }
.cmp--2 { min-width: calc(var(--cmp-label) + 2 * var(--cmp-col)); }
.cmp--3 { min-width: calc(var(--cmp-label) + 3 * var(--cmp-col)); }
.cmp--4 { min-width: calc(var(--cmp-label) + 4 * var(--cmp-col)); }
.cmp th, .cmp td {
  text-align: left; vertical-align: top;
  padding: 9px 14px; border-bottom: 1px solid var(--line);
}
#cmp-table {
  overflow: auto; max-height: 76vh;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md);
}

/* Шапка с позициями и первая колонка — липкие. Уголок липнет по обеим осям,
   поэтому у него свой слой выше остальных. Селекторы с классом на элементе
   (`th.cmp__label`) — не украшение: у общего правила ячеек вес выше, и простой
   двойной класс его не перебьёт */
.cmp thead th { position: sticky; top: 0; z-index: 3; background: var(--surface); box-shadow: 0 1px 0 var(--line); }
.cmp th.cmp__label {
  position: sticky; left: 0; z-index: 2;
  background: var(--surface); box-shadow: 1px 0 0 var(--line);
}
.cmp thead th.cmp__label { top: 0; z-index: 4; }
/* Ширины колонок: их берёт раскладка fixed из первой строки таблицы, поэтому
   заданы у уголка и у шапки колонки. Обе — из переменных .cmp: по ним же
   compare.js считает минимальную ширину таблицы */
.cmp__label { width: var(--cmp-label); color: var(--ink-2); font-weight: 400; }
.cmp__corner { font-size: .8rem; letter-spacing: .04em; text-transform: uppercase; color: var(--ink-3); }

/* Колонка позиции: кадр, название, артикул с брендом, цена с кнопкой.
   Класс с двойным весом (`.cmp .cmp__col`), иначе отступ перебивает общее
   правило ячеек `.cmp th, .cmp td` — у него вес выше.
   font-weight: 400 обязателен: ячейка — <th>, а браузер делает th жирным, и
   артикул, бренд и «за шт» рядом с названием выходили полужирными, как нигде
   больше на сайте (заказчик 14.10.2026: «шрифт сверху другой») */
.cmp .cmp__col { width: var(--cmp-col); padding: 12px 14px; font-weight: 400; }
.cmp__top { display: flex; gap: 10px; align-items: flex-start; }
.cmp__shot {
  position: relative; flex: none; display: block;
  width: 56px; height: 56px; border-radius: var(--r-sm);
  background: var(--field); overflow: hidden;
}
.cmp__shot img { width: 100%; height: 100%; object-fit: contain; }
.cmp__noimg {
  position: absolute; inset: 0; display: none;
  align-items: center; justify-content: center; text-align: center;
  font-size: .66rem; line-height: 1.3; color: var(--ink-3);
}
/* Файла кадра может не быть — тогда на его месте подпись с артикулом
   (тот же приём в быстром просмотре, см. .quick__shot) */
.cmp__shot.is-broken img { display: none; }
.cmp__shot.is-broken .cmp__noimg { display: flex; }
.cmp__id { min-width: 0; }
/* Название, артикул и цена — теми же значениями, что на плитке каталога
   (.pcard__name, .pcard__meta, .pcard__price b): шапка сравнения — это та же
   карточка позиции, и своим набором весов она выбивалась из сайта.
   Название обрезаем по трём строкам и держим под них высоту: имена разной
   длины, без этого шапки колонок получались разной высоты, а кнопки вставали
   на разной высоте (полное имя — в title ссылки, ставит compare.js) */
.cmp__name {
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
  overflow: hidden;
  min-height: 4.05em;                   /* три строки по line-height 1.35 */
  font-size: .92rem; font-weight: 400; line-height: 1.35; letter-spacing: -0.01em;
}
.cmp__art, .cmp__brand { display: block; margin-top: 3px; font-size: .76rem; color: var(--ink-3); }
.cmp__drop {
  flex: none; width: 26px; height: 26px; padding: 0;
  border: 1px solid var(--line-strong); border-radius: 50%;
  background: transparent; color: var(--ink-3);
  font: inherit; font-size: 1rem; line-height: 1; cursor: pointer;
}
.cmp__drop:hover { color: var(--ink); border-color: var(--ink); }
/* align-items: stretch — чтобы «В корзину» и счётчик количества, который встаёт
   на её место, были одной ширины: счётчик тянется на всю ячейку, и у
   выровненной по левому краю кнопки он вырастал вдвое (заказчик 14.10.2026:
   «кнопки пляшут») */
.cmp__buy { display: flex; flex-direction: column; align-items: stretch; gap: 8px; margin-top: 12px; }
.cmp__price { display: flex; align-items: baseline; gap: 7px; flex-wrap: wrap; }
/* Цена — как в плитке каталога (.pcard__price b/em): и вес, и размер оттуда.
   По умолчанию <b> берёт 900 из общего правила, и цена была чернее, чем где
   бы то ни было на сайте */
.cmp__price b { font-size: 1.12rem; font-weight: 600; letter-spacing: -0.02em; }
.cmp__price em { font-style: normal; font-size: .78rem; color: var(--ink-3); }
.cmp__stock { font-size: .8rem; color: var(--ink-3); }
/* Наличие зелёным — тем же, что плитка и список каталога (.pcard__avail.now).
   Переменная --ok в фирменном слое перекрашена в жёлтый, для текста не годится */
.cmp__stock .is-in { color: #2f7d4f; }
.cmp__warn { font-size: .8rem; color: var(--ink-3); }

/* Различия: подложка на всю строку, у названия — точка. Правило стоит после
   правил липких ячеек: при равной специфичности побеждает последнее, иначе
   подложка не перебила бы их белый фон */
.cmp__row.is-diff > * { background: var(--accent-soft); }
.cmp__mark {
  display: inline-block; width: 6px; height: 6px; margin-left: 7px;
  border-radius: 50%; background: var(--accent); vertical-align: 2px;
}
.cmp__none { color: var(--ink-3); }
.cmp__nodiff, .cmp__hint { color: var(--ink-3); }
.cmp__hint { margin: 0 0 12px; }
.cmp__grp th {
  background: var(--field); padding: 7px 14px;
  font-size: .76rem; letter-spacing: .04em; text-transform: uppercase; color: var(--ink-2);
}

/* Полоса над таблицей: переключатель «Только различия» и пояснение.
   Пока в сравнении пусто, полоса скрыта атрибутом hidden — его надо вернуть
   явно, иначе его перебьёт собственный display: flex */
.cmp-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 20px; margin: 16px 0 12px; }
.cmp-bar[hidden] { display: none; }
.cmp-toggle { display: inline-flex; align-items: center; gap: 8px; font-size: .9rem; cursor: pointer; }
.cmp-bar .small { max-width: 62ch; }

/* Плашка «в сравнении уже четыре позиции» (lists.js): у .toast задан запрет
   переноса — ради короткого «Найдено N». Здесь текст длиннее экрана телефона */
.toast--cmp { white-space: normal; max-width: min(320px, calc(100vw - 16px)); }

/* Удаление колонки с ожиданием — тот же приём, что в избранном
   (.pcard__undo/.ptable__undo): колонка гаснет, на блоке покупки встаёт
   «Убрано · Вернуть», пять секунд ждёт. Плашка именно на блоке покупки, а не
   на всей колонке: колонка тянется на тридцать с лишним строк, и её середина
   далеко от крестика, которым удаление и начали.
   Крестик остаётся живым и не гаснет: второе нажатие по нему отменяет
   удаление — как сердечко в избранном */
.cmp__col.is-pending .cmp__top > :not(.cmp__drop),
.cmp__col.is-pending .cmp__buy > :not(.cmp__undo) { opacity: .35; pointer-events: none; }
.cmp__col.is-pending .cmp__buy { position: relative; }
.cmp__undo {
  position: absolute; inset: 0; z-index: 4;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 6px; pointer-events: none;
}
.cmp__undo > * { pointer-events: auto; }
/* Плашка лежит на подписи с ценой — им нужен свой фон, иначе читаются поверх
   притемнённого содержимого (так же в плитке избранного) */
.cmp__undo .undo-label {
  background: var(--surface); border-radius: 4px; padding: 3px 8px;
  box-shadow: 0 1px 4px rgba(24, 24, 16, .18);
}
.cmp__undo .btn { background: var(--surface); }
.cmp__undo .btn:hover { background: var(--surface); border-color: var(--ink); }

@media (max-width: 980px) {
  /* Узкий экран: таблицу листают вбок, липкая шапка не нужна — она заняла бы
     половину экрана, а страница и без неё прокручивается целиком.
     Колонки здесь уже: 390 px экрана на 190 px подписей жалко. Числа — те же
     переменные, по которым compare.js считает ширину таблицы */
  #cmp-table { max-height: none; }
  .cmp thead th { position: static; }
  .cmp { --cmp-label: 160px; --cmp-col: 208px; }
}

