

/* ===== 2. ТОКЕНЫ ===== */
:root {
  --brand:            #FC5800;
  --brand-light:      #FF6E22;   /* наведение на кнопку без волны */

  /* Цвета бейджей каталога: подобраны к фирменному зелёному, каждый отвечает
     за свой смысл — гарантия, субсидия, «скоро». */
  --badge-blue:       #1B6FA8;
  --badge-amber:      #9A5C00;   /* затемнён: белая надпись «Субсидия
                                    до 60%» на прежнем #B26A00 давала 4,24:1 —
                                    ниже нормы AA. Стало 5,38:1 */
  --badge-slate:      #4A5459;
  --brand-press:      #E8590C;   /* кнопки и плашки с белым текстом; #C14300 на белой шапке
                                    выглядел мрачно. Белый текст на #E8590C — 3,58:1: проходит
                                    норму WCAG для крупного и жирного текста (3:1), но не для обычного (4,5:1); светлый
                                    оранжевый, который проходит 4,5, не существует. #F7732D из задания давал 2,82:1 */
  --brand-deep:       #D9480F;   /* наведение и нажатие на такой плашке (4,30:1) */
  --brand-dim:        #AD3C00;   /* ссылки и мелкий текст на белом: чистый
                                    --brand на белом не добирает контраста */
  --on-brand:         #FFFFFF;

  --ink:              #0A0D0E;
  --ink-strong:       #161B1D;
  --body:             #3A4246;
  --muted:            #5B666B;   /* подписи и оговорки: прежний #6C777C давал
                                    4,24:1 на --surface — ниже нормы AA, и на
                                    телефоне текст читался как выключенный.
                                    Стало 5,44:1 */
  --faint:            #98A2A7;

  --report-ptzem:     #FBE3CF;   /* метка проекта ptzem в отчёте о работах — оранжевый из логотипа Технопарка, осветлённый */
  --canvas:           #FFFFFF;
  --surface:          #F4F6F6;
  --surface-2:        #E9EDEE;
  --surface-3:        #DCE2E3;   /* шапка таблицы: темнее строк-подзаголовков */
  --hairline:         #E1E6E7;
  --find-mark:        #FFE27A;   /* подсветка найденного на странице после перехода из поиска */
  --hairline-strong:  #C9D1D3;

  --dark:             #0A0D0E;
  --dark-2:           #12181A;
  --dark-3:           #1B2225;
  --header-bg:        #1B1B1B;
  --on-dark:          #FFFFFF;
  --on-dark-2:        rgba(255,255,255,.72);
  --on-dark-3:        rgba(255,255,255,.46);
  --hairline-dark:    rgba(255,255,255,.12);

  --quiz-bg:          #333333;
  --quiz-line:        #555555;

  --danger:           #C0392B;
  --warning:          #9A5C00;

  --font:             'Montserrat', Arial, -apple-system, 'Segoe UI', sans-serif;

  --fs-display:       3.75rem;     /* 60px — H1 первого экрана */
  --fs-h2:            2.0625rem;   /* 33px */
  --fs-h3:            1.5rem;      /* 24px */
  --fs-h4:            1.1875rem;   /* 19px */
  --fs-stat:          2.75rem;     /* 44px — цифра показателя */
  --fs-lead:          1.1875rem;   /* 19px */
  --fs-base:          1rem;        /* 16px — минимум для инпутов, иначе iOS зумит */
  --fs-sm:            0.9375rem;   /* 15px */
  --fs-caption:       0.8125rem;   /* 13px */
  --fs-label:         0.75rem;     /* 12px — прописными, вразрядку */

  --lh-display:       1.04;
  --lh-tight:         1.15;
  --lh-snug:          1.35;
  --lh-base:          1.65;

  --ls-display:      -0.03em;
  --ls-h2:           -0.025em;
  --ls-h3:           -0.015em;
  --ls-label:         0.12em;

  --sp-1:  4px;   --sp-2:  8px;   --sp-3:  12px;  --sp-4:  16px;
  --sp-5:  24px;  --sp-6:  32px;  --sp-7:  48px;  --sp-8:  64px;
  --sp-9:  96px;  --sp-10: 128px;

  --radius:           2px;
  --radius-md:        4px;
  /* Скругления: острые углы кнопок
     читались недружелюбно. Инженерный характер держат волосяные линии и
     типографика, а не прямые углы у всего подряд. */
  --radius-btn:       8px;
  --radius-lg:        12px;
  --radius-full:      999px;

  --shadow-menu:      0 16px 40px -20px rgba(10,13,14,.45);

  --wrap:             1408px;
  --wrap-medium:      1180px;   /* прайс и дорожная карта: широкая таблица неудобна во всю ширину */
  --wrap-narrow:      960px;
  --gutter:           24px;
  --header-h:         76px;

  /* Правый нижний угол: кнопка чата и кнопка «наверх» стоят друг над другом и
     обязаны совпадать по вертикальной оси. Размеры кругов разные, поэтому у
     верхней кнопки отступ считается от этих переменных, а не пишется числом.
     */
  --dock-right:       20px;
  --dock-chat:        56px;
  --dock-top:         44px;
  --dock-lift:        0px;    /* подъём кнопок над плашкой cookie, считается ниже */
}

/* ===== 2.1. ШРИФТЫ =====
   Объявления не было вовсе: файлы лежали в assets/fonts, стояла строка
   preload, но @font-face никто не написал — страница рисовалась системным
   шрифтом, а браузер ругался «preloaded but not used».
   Подмножества разделены по unicode-range: латиница не тянется ради
   кириллического текста и наоборот. */
@font-face {
  font-family: 'Montserrat';
  src: url('/app/assets/fonts/montserrat-cyrillic.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Montserrat';
  src: url('/app/assets/fonts/montserrat-latin.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
                 U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ===== 3. СБРОС И БАЗА ===== */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  -webkit-tap-highlight-color: transparent;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  font-family: var(--font);
  font-size: var(--fs-base);
  line-height: var(--lh-base);
  color: var(--body);
  background: var(--canvas);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img, picture, video, svg { max-width: 100%; height: auto; display: block; }

[hidden] { display: none !important; }
button, input, select, textarea { font: inherit; color: inherit; }

table, .stats, .spec, .tech { font-variant-numeric: tabular-nums; }

:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

/* Место под полосу прокрутки резервируется всегда: иначе при открытии модального
   окна страница теряет полосу и дёргается вправо.
   Только справа: при both-edges слева оставалось пустое поле, и на тёмных
   секциях оно читалось как светлая вертикальная полоса. */
html { scrollbar-gutter: auto; }
@media (hover: hover) and (pointer: fine) { html { scrollbar-gutter: stable; } }
body.is-menu-open, body.is-modal-open { overflow: hidden; }

/* ===== 4. ТИПОГРАФИКА ===== */
h1, h2, h3, h4 {
  margin: 0 0 var(--sp-4);
  color: var(--ink);
  font-weight: 700;
  line-height: var(--lh-tight);
  text-wrap: balance;              /* переносы задаёт браузер, а не <br> вручную */
}
h1 { font-size: var(--fs-display); line-height: var(--lh-display); letter-spacing: var(--ls-display); }
h2 { font-size: var(--fs-h2);      line-height: 1.1;               letter-spacing: var(--ls-h2); }
h3 { font-size: var(--fs-h3);      line-height: 1.25;              letter-spacing: var(--ls-h3); }
h4 { font-size: var(--fs-h4);      line-height: var(--lh-snug);    font-weight: 600; }

/* Длинное слово не должно распирать страницу: «Машиностроение» в заголовке
   карточки документа, цепочка подчёркиваний в юридическом тексте, адрес почты.
   Без этого страница получала горизонтальную прокрутку на телефоне. */
h1, h2, h3, h4, p, li, dd, dt, td, th, figcaption, .lead { overflow-wrap: break-word; }

/* Ручной перенос действует только на широком экране. Переносы в офферах и
   подзаголовках расставлены по смыслу под десктоп; на телефоне строка и так
   короткая, и каждый <br> ломает её второй раз — в первом экране получалось
   «Станция приносит от 53 000 ₽ в / месяц,» с висящей запятой. */
br.br-wide { display: inline; }
@media (max-width: 640px) { br.br-wide { display: none; } }

p { margin: 0 0 var(--sp-4); }
p:last-child { margin-bottom: 0; }

h2 + p, h3 + p, h4 + p { margin-top: calc(var(--sp-2) * -1); }

a { color: var(--brand-dim); text-decoration: none; }
a:hover { text-decoration: underline; }

/* Ширину текста внутри блока не ограничиваем: длину строки задаёт сам текст через <br> в JSON, а не отсечка
   по знакам. Взамен обязательна проверка переносов глазами — см. §7 в
   .claude/CLAUDE.md. */
.lead {
  font-size: var(--fs-lead);
  line-height: 1.6;
  color: var(--ink-strong);
}
/* Подзаголовок блока внутри текста: тот же кегль, но плотнее — иначе на длинной
   странице он читается как обычный абзац. */
.lead--sub { font-weight: 600; }
/* Подзаголовок с цифрами рынка: числа зелёным, чтобы масштаб читался с одного
   взгляда. Выделение приходит из JSON тегом <b>. */
.lead--figures b { color: var(--brand-dim); font-weight: 700; }

/* Примечание под блоком: 15px, а не 13. Мелким кеглем набирают то, что можно
   не читать, а в примечаниях у нас условия, оговорки и цены — их читают.
   13px остаётся подписям: поля форм, шапка, подвал. */
.note    { font-size: var(--fs-sm); color: var(--muted); }
.prose p { max-width: none; }

.eyebrow {
  display: inline-flex; align-items: center; gap: var(--sp-3);
  margin: 0 0 var(--sp-5);
  font-family: var(--font);
  font-size: var(--fs-label);
  font-weight: 700;
  line-height: 1;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--brand-dim);
}

.tech {
  font-family: var(--font);
  font-size: var(--fs-caption);
  letter-spacing: .01em;
}

@media (max-width: 1024px) {
  :root { --fs-display: 3rem; --fs-h2: 1.875rem; --fs-stat: 2.25rem; }
}
@media (max-width: 640px) {
  :root {
    /* H1 тянется за шириной экрана, а не стоит на 36px. На 360px самое длинное
       слово («электромобилей» в заголовке про субсидию) занимало 319px из 328 и
       упиралось в край; здесь оно получает 33px кегля и запас. Верх clamp —
       прежние 36px: на 420px и шире размер не меняется. */
    --fs-display: clamp(1.75rem, 1.89rem + 0.89vw, 2.25rem);
    --fs-h2: 1.5625rem; --fs-h3: 1.3125rem;
    --fs-lead: 1.0625rem;  --fs-stat: 2rem;  --gutter: 16px;
    /* Мелкий текст на телефоне: 13px в оговорках и хлебных крошках заказчик
       читал с трудом. На большом экране 13px остаются. */
    --fs-caption: 0.875rem;
  }
  /* Перенос по слогам (lang="ru" стоит на <html>) — на узкой колонке это
     единственный способ получить ровный край без дыр. Разрыв по буквам
     (overflow-wrap выше) остаётся страховкой на случай, если словарь не
     справился: он рвёт слово посреди корня и выглядит хуже переноса. */
  h1, h2, h3, h4, p, li, dd, dt, figcaption { hyphens: auto; }
}

/* ===== 5. СЕТКА И СЕКЦИИ ===== */
.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.wrap--medium { max-width: var(--wrap-medium); }
/* Контейнер под текст с содержанием сбоку: колонка текста остаётся прежней, а свободные поля по краям отдаются виджету содержания. */
.wrap--wide { max-width: 1760px; }
.wrap--narrow { max-width: var(--wrap-narrow); }

.section { padding-block: var(--sp-8); }
.section--tight { padding-block: var(--sp-7); }
.section--surface { background: var(--surface); }
.section--dark { position: relative; overflow: hidden; background: var(--dark); color: var(--on-dark-2); }

/* Светлая секция с чертёжной абстракцией: тонкая сетка и мягкое пятно в углу.
   Заменила чёрный фон в кейсах — строго, но легко. */
.section--grid { position: relative; overflow: hidden; background: var(--surface); }
.section--grid::before {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background-image:
    repeating-linear-gradient(to right,  rgba(10,13,14,.05) 0 1px, transparent 1px 56px),
    repeating-linear-gradient(to bottom, rgba(10,13,14,.05) 0 1px, transparent 1px 56px);
  -webkit-mask-image: linear-gradient(105deg, #000 0%, rgba(0,0,0,.4) 50%, transparent 75%);
          mask-image: linear-gradient(105deg, #000 0%, rgba(0,0,0,.4) 50%, transparent 75%);
}
.section--grid::after {
  content: ''; position: absolute; right: -8%; top: -30%; width: 46%; aspect-ratio: 1;
  background: radial-gradient(circle, rgba(252,88,0,.10) 0%, transparent 65%);
  pointer-events: none;
}
.section--grid > .wrap { position: relative; }
.section--dark h1, .section--dark h2, .section--dark h3, .section--dark h4 { color: var(--on-dark); }
/* Приглушённый зелёный сделан для белого фона (6,62:1); на тёмном он даёт
   2,95:1 и читается хуже чистого --brand (4,99:1). Поэтому в тёмных частях
   сайта акценты возвращаются к фирменному цвету. */
.section--dark .eyebrow, .hero .eyebrow, .footer .eyebrow, .quiz .eyebrow, .lead-band .eyebrow,
.section--dark b, .hero b, .footer b, .lead-band b { color: var(--brand); }
.section--dark .lead { color: var(--on-dark-2); }

.section__head { margin-bottom: var(--sp-8); text-align: center; }
/* Таблица сразу за шапкой секции: полный отступ шапки плюс собственный отступ
   таблицы давали провал в целый экран. */
.section__head + .table-scroll { margin-top: calc(var(--sp-8) * -1 + var(--sp-5)); }
.section__head h2 { max-width: none; }
.section__head .lead { margin-inline: auto; }

/* Везде minmax(0, 1fr), а не 1fr: колонка «1fr» не может стать уже своего
   содержимого, и один широкий элемент (таблица, длинное слово без переноса)
   растягивает всю сетку за край экрана. */
.grid { display: grid; gap: var(--sp-6); }
.grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

@media (max-width: 1024px) {
  .grid--4, .grid--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 640px) {
  .grid--2, .grid--3, .grid--4 { grid-template-columns: minmax(0, 1fr); }
  .section { padding-block: var(--sp-7); }
  .section--tight { padding-block: var(--sp-7); }
  .section__head { margin-bottom: var(--sp-6); }
}

/* ===== 6. КНОПКИ И ССЫЛКИ ===== */
.btn {
  position: relative; isolation: isolate; overflow: hidden;
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  min-height: 48px;                    /* тап-таргет не меньше 44px */
  padding-inline: var(--sp-5);
  border: 1px solid transparent;
  border-radius: var(--radius-btn);
  font-size: var(--fs-sm); font-weight: 600; line-height: 1;
  cursor: pointer; text-decoration: none;
  transition: background-color .15s, color .15s, border-color .15s;
}
.btn:hover { text-decoration: none; }

.btn::before {
  content: ''; position: absolute; z-index: -1;
  left: 50%; top: 50%; width: 220%; aspect-ratio: 1;
  translate: -50% -50%;
  border-radius: 50%;
  background: currentColor;
  opacity: 0; transform: scale(0);
  transition: transform .45s cubic-bezier(.22,.61,.36,1), opacity .35s ease-out;
}
.btn:hover::before { transform: scale(1); opacity: .16; }
.btn:active::before { transition-duration: .1s; opacity: .22; }

.btn--primary::before { background: #fff; }

@media (prefers-reduced-motion: reduce) {
  .btn::before { display: none; }
  .btn--sheen::after { display: none; }
}

.btn--primary { background: var(--brand-press); color: var(--on-brand); }
.btn--primary:hover  { background: var(--brand-deep); }
.btn--primary:active { background: var(--brand-deep); }

.btn--outline { background: transparent; color: var(--ink); border-color: var(--hairline-strong); }
.btn--outline:hover { border-color: var(--brand); color: var(--brand-dim); }

/* Волна на зелёных кнопках — перенесена из проекта «Генератор КП» заказчика
: круг расходится из левого края раз в шесть секунд и гаснет.
   Геометрия кнопки взята оттуда же, оранжевый фон заменён нашим зелёным.

   Наведение зелёные кнопки не обрабатывают вовсе:
   hover смешивался с волной и мешал ей читаться. */
.btn--primary::after {
  content: ''; position: absolute; z-index: -1;
  top: 0; left: -100%;
  width: 200%; height: 350%;
  background: rgba(255,255,255,.8);
  border-radius: 100%;
  transform: scale(0);
  animation: btn-ripple 6s linear infinite;
}
@keyframes btn-ripple {
  20%  { opacity: 0; transform: scale(2.5); }
  100% { opacity: 0; transform: scale(2.5); }
}

.btn--primary {
  padding: 17px 33px;
  font-size: 14px; font-weight: 600;
  border-radius: 4px; gap: 8px;
}
.btn--primary::before { display: none; }
.btn--primary:hover,
.btn--primary:active { background: var(--brand-deep); }
.btn--primary:hover svg { transform: none; }

/* Зелёная кнопка без волны. Волна — привилегия целевых
   кнопок блоков; на служебных («Заказать звонок», «Подробнее» в карточке)
   постоянное движение превращается в шум. Здесь работает обычный hover:
   фон светлеет. */
.btn--primary.btn--calm::after { content: none; }
.btn--primary.btn--calm:hover,
.btn--primary.btn--calm:focus-visible { background: var(--brand-light); }
.btn--primary.btn--calm:active { background: var(--brand-deep); }

.btn svg { transition: transform .2s ease-out; }
.btn--sheen:hover svg { transform: translateX(3px); }

.btn--ghost { background: none; }

/* Светлые кнопки не бликуют и не зеленеют при наведении:
   темнеет только обводка, фон и цвет текста остаются на месте. */
.btn--outline::before, .btn--ghost::before, .btn--on-dark::before { content: none; }
.btn--outline:hover, .btn--outline:focus-visible {
  background: transparent; border-color: var(--ink); color: var(--ink);
}

.btn--on-dark { background: transparent; color: var(--on-dark); border-color: var(--hairline-dark); }
.btn--on-dark:hover { border-color: var(--on-dark); }

.btn--lg { min-height: 56px; padding-inline: var(--sp-6); font-size: var(--fs-base); }

.link-action {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  font-size: var(--fs-sm); font-weight: 600; color: var(--brand-dim);
}
.link-action::after {
  content: '\2192'; transition: transform .15s;
}
.link-action:hover { text-decoration: none; }
.link-action:hover::after { transform: translateX(3px); }
.section--dark .link-action, .hero .link-action, .quiz .link-action { color: var(--on-dark); }

/* ===== 7. ФОРМЫ ===== */
.field { display: block; margin-bottom: var(--sp-4); }
.field__label {
  display: block; margin-bottom: var(--sp-2);
  font-size: var(--fs-caption); font-weight: 600; color: var(--ink-strong);
}

.input, .textarea, .select {
  width: 100%;
  /* min-width: 0 обязателен именно для <select>: его собственная минимальная
     ширина равна самому длинному пункту списка («Мощность: по убыванию» в
     фильтре каталога), и width: 100% её не перебивает. На экране 320px из-за
     этого распирало панель фильтра и появлялась горизонтальная прокрутка. */
  min-width: 0;
  min-height: 48px;
  padding: var(--sp-3) var(--sp-4);
  font-size: var(--fs-base);          /* не меньше 16px — иначе iOS зумит */
  color: var(--ink);
  background: var(--canvas);
  border: 1px solid var(--hairline-strong);
  border-radius: var(--radius-btn);
  transition: border-color .15s, box-shadow .15s;
}
.input:focus, .textarea:focus, .select:focus {
  border-color: var(--brand);
  box-shadow: inset 0 0 0 1px var(--brand);   /* рамка «в 2px» без сдвига раскладки */
  outline: none;
}
.textarea { min-height: 120px; resize: vertical; }

.field--invalid .input,
.field--invalid .textarea { border-color: var(--danger); }
.field__error { display: none; margin-top: var(--sp-2); font-size: var(--fs-caption); color: var(--danger); }
.field--invalid .field__error { display: block; }

.consent { display: flex; gap: var(--sp-3); align-items: flex-start; font-size: var(--fs-caption); color: var(--muted); }
.consent input { width: 20px; height: 20px; margin-top: 2px; flex: none; accent-color: var(--brand); }
/* Ссылка на юридические документы внутри согласия: подчёркнута всегда. Без подчёркивания она сливается с текстом, и человек не понимает, что документы можно открыть. */
.consent a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.consent a:hover { color: var(--brand-dim); }

/* Объяснение, зачем нужен телефон: одна строка снимает бо́льшую часть
   беспокойства. Цвета — по
   контексту, как у согласия ниже по файлу. */
.form-why {
  margin: calc(var(--sp-2) * -1) 0 var(--sp-2);
  font-size: var(--fs-caption); color: var(--muted);
}
.quiz .form-why,
.lead-band__form .form-why,
.section--dark .form-why { color: var(--on-dark-3); }
/* Порядок как в разметке: поля, пояснение, согласие и под ними кнопка —
   флажок стоит над кнопкой. */
.lead-band__form .form-why { grid-column: 1 / -1; }

.trap {
  position: absolute !important;
  left: -9999px !important;
  width: 1px; height: 1px; overflow: hidden;
}

/* ===== 8. ФИРМЕННЫЕ ЭЛЕМЕНТЫ ===== */

.mark {
  display: inline-grid; gap: 3px;
  width: 22px; flex: none;
}
.mark i { display: block; height: 4px; background: var(--brand); }
.mark i:last-child { background: var(--brand-dim); }
.section--dark .mark i:last-child { background: rgba(252,88,0,.55); }

.icon { display: block; flex: none; color: var(--brand); }
.icon--card, .icon--step { color: var(--brand); }
.icon--link, .icon--tile, .icon--doc { color: var(--muted); transition: color .15s; }
a:hover .icon--link, a:hover .icon--tile, a:hover .icon--doc { color: var(--brand); }

.corner {
  position: absolute; width: 24px; height: 24px;
  border: 2px solid var(--brand); pointer-events: none;
}
.corner--tl { top: -6px;    left: -6px;  border-right: 0; border-bottom: 0; }
.corner--br { right: -6px; bottom: -6px; border-left: 0;  border-top: 0; }

.grid-bg {
  position: absolute; inset: 0; pointer-events: none;
  background-image:
    repeating-linear-gradient(to right,  rgba(255,255,255,.07) 0 1px, transparent 1px 56px),
    repeating-linear-gradient(to bottom, rgba(255,255,255,.07) 0 1px, transparent 1px 56px);
  -webkit-mask-image: linear-gradient(105deg, #000 0%, rgba(0,0,0,.35) 45%, transparent 70%);
          mask-image: linear-gradient(105deg, #000 0%, rgba(0,0,0,.35) 45%, transparent 70%);
}

/* ===== 9. ШАПКА ===== */
.header { background: var(--header-bg); color: var(--on-dark); }

.header__top {
  background: var(--header-bg);
  border-bottom: 1px solid var(--hairline-dark);
  font-size: var(--fs-caption);
  letter-spacing: .01em;
  color: var(--on-dark-3);
}
.header__top .wrap {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-5); min-height: 40px; white-space: nowrap;
}
.header__top a { color: var(--on-dark-3); }
.header__top a:hover { color: var(--on-dark); text-decoration: none; }
.header__top-links { display: flex; gap: var(--sp-5); }


/* ===== Выбор города ===== */
.city { display: inline-flex; align-items: center; gap: 6px; }
.city:hover .city__name { color: var(--brand); }
.city__pin { color: var(--brand); flex: none; }
.city__name { color: var(--on-dark); font-weight: 500; }
.city__addr { color: var(--on-dark-3); }
.city__arrow { align-self: flex-end; margin-bottom: 5px; color: var(--on-dark-3); }


.header__main .wrap { display: flex; align-items: center; gap: var(--sp-6); min-height: var(--header-h); }

/* Логотипу разрешено сжиматься (flex: 0 1 auto вместо none). При flex: none
   содержимое шапки на экране 360px (логотип 151 + телефон 140 + бургер 48 при
   колонке 328) не помещалось, страница становилась 379px шириной и получала
   горизонтальную прокрутку: справа на телефоне видна белая полоса, чёрная шапка
   обрывается раньше края экрана, а заголовок уходит под эту полосу.
   */
.logo { display: flex; align-items: center; gap: var(--sp-3); flex: 0 1 auto; min-width: 0; }
.logo__img { height: 53px; width: auto; max-width: 100%; }
/* Логотип 53px: на 1201–1439px знак, подпись, две кнопки и меню в строку не помещались, подпись наезжала
   на «Каталог». Логотип не сжимается, а на этих ширинах знак 44px и подпись мельче. */
@media (min-width: 1201px) { .logo { flex: none; } }
@media (min-width: 1201px) and (max-width: 1439px) { .logo__img { height: 44px; } .logo__text { font-size: 0.75rem; } .header__main .wrap { gap: var(--sp-4); } }
@media (min-width: 1201px) and (max-width: 1339px) { .logo__img { height: 40px; } .logo__text { display: none; } }
/* Дескриптор отделён от картинки: внутри logo.png он был нарисован
   и на телефоне выходил около 7px. Текстом им можно управлять — и он читается. */
.logo__text {
  font-family: var(--font); font-size: var(--fs-caption); font-weight: 600;
  line-height: 1.2; letter-spacing: .01em; color: var(--on-dark-2);
  white-space: nowrap;
}

/* Меню занимает всю свободную ширину между логотипом и контактами, пункты
   распределены равномерно: раньше они жались
   влево, а справа оставалась пустая полоса. */
.nav { flex: 1; }
.nav__list {
  display: flex; justify-content: space-between; gap: var(--sp-3);
  width: 100%; list-style: none; margin: 0; padding: 0;
}
.nav__item { position: relative; }
.nav__link {
  display: inline-flex; align-items: center; gap: var(--sp-1);
  padding-block: calc((var(--header-h) - 20px) / 2);
  font-size: var(--fs-base); font-weight: 500; line-height: 20px;
  color: var(--on-dark); white-space: nowrap;
  border-bottom: 2px solid transparent;
}
.nav__link:hover { color: var(--on-dark); text-decoration: none; border-bottom-color: var(--brand); }
.nav__item.is-active > .nav__link { border-bottom-color: var(--brand); }

.nav__item:has(.nav__sub) > .nav__link::after {
  content: ''; width: 5px; height: 5px; margin-left: 2px;
  border-right: 1.5px solid var(--on-dark-3); border-bottom: 1.5px solid var(--on-dark-3);
  transform: translateY(-2px) rotate(45deg);
}

.nav__sub {
  position: absolute; top: 100%; left: calc(var(--sp-4) * -1); z-index: 20;
  /* ширина под самое длинное название раздела: с переносами выпадающее меню вытягивалось вниз
     и читалось тяжело */
  min-width: 360px; max-width: 520px; margin: 0; padding: var(--sp-4);
  list-style: none;
  background: var(--dark-3);
  border: 1px solid var(--hairline-dark);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-menu);
  display: grid; gap: var(--sp-1);

  opacity: 0; visibility: hidden; transform: translateY(4px);
  transition: opacity .15s, transform .15s, visibility .15s;
}
.nav__item:hover .nav__sub,
.nav__item:focus-within .nav__sub {
  opacity: 1; visibility: visible; transform: translateY(0);
}
/* Группа внутри выпадающего меню: заголовок-ссылка и список под ним. Так в
   каталоге вместо шести «Зарядные станции …» стоит одно название группы, а
   пункты называются коротко — «60 кВт», «Уличные». */
.nav__group-title {
  display: block; padding: var(--sp-2) var(--sp-3) var(--sp-1);
  color: var(--on-dark); font-weight: 600; font-size: var(--fs-sm);
}
.nav__group-title:hover { color: var(--brand-light); text-decoration: none; }
/* Без нижнего поля: с ним разрыв между последним пунктом группы и следующим
   пунктом меню был вдвое больше, чем между соседними строками списка. */
.nav__group-list { list-style: none; margin: 0; padding: 0; }
.nav__group-list a { padding-left: var(--sp-5); }

.nav__sub a {
  display: block; padding: var(--sp-2) var(--sp-3);
  font-size: var(--fs-sm); color: var(--on-dark-2); border-radius: var(--radius);
}
.nav__sub a:hover { color: var(--on-dark); background: rgba(255,255,255,.06); text-decoration: none; }

/* Пальцем по ссылке-строке: на телефоне высота ссылки в списках первого экрана,
   подвала и бургера доводится до 44px — норма тап-таргета (проверка mobile-check). */
@media (max-width: 900px) {
  .nav__sub a { display: block; padding-block: 4px; }
  /* у ссылок подвала свои отступы ниже по файлу — доводим высоту, а не отступ */
  .footer__list li a { display: flex; align-items: center; min-height: 44px; }
}

/* Второй уровень меню: у подкатегорий каталога и разделов услуг
   подменю выдвигается вправо по наведению. Список строит main.js из data-атрибута:
   двести ссылок в исходном коде каждой страницы размыли бы её релевантность. */
/* Подменю второго уровня отсчитывается от всего выпадающего меню, а не от своей строки:
   верх обоих списков на одной линии, и нижние разделы («Литейное производство» и ниже)
   больше не уводят второй список за нижний край экрана. */
.nav__fly { position: static; }
.nav__fly > a { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); }
.nav__fly > a::after {
  content: ''; width: 5px; height: 5px; flex: none;
  border-right: 1.5px solid var(--on-dark-3); border-top: 1.5px solid var(--on-dark-3);
  transform: rotate(45deg);
}
.nav__fly-list {
  position: absolute; top: -1px; left: calc(100% - 1px); z-index: 21;
  min-height: calc(100% + 2px);
  /* ширина под самое длинное название: с переносами список вытягивался на пол-экрана */
  min-width: 380px; max-width: 560px; max-height: calc(100vh - var(--header-h) - 56px); overflow-y: auto;
  margin: 0; padding: var(--sp-4);
  list-style: none;
  background: var(--dark-3);
  border: 1px solid var(--hairline-dark);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-menu);
  display: grid; gap: var(--sp-1); align-content: start;
  opacity: 0; visibility: hidden;
  transition: opacity .15s, visibility .15s;
}
/* Мостик до второго меню: без него курсор проваливается в зазор, и меню закрывается. */
/* Списки стоят встык, поэтому мостик над зазором больше не нужен. */
.nav__fly:hover > .nav__fly-list,
.nav__fly:focus-within > .nav__fly-list { opacity: 1; visibility: visible; }
.nav__item:not(:hover):not(:focus-within) .nav__fly-list { visibility: hidden; }

.header__contacts { display: flex; align-items: center; gap: var(--sp-5); flex: none; }
/* Телефон со стрелкой: наведение (или фокус с клавиатуры) раскрывает окно со
   вторым номером и почтой. Оба значения — из конфига. */
.header__tel { position: relative; display: flex; flex-direction: column; line-height: 1.25; }
.header__tel-row { display: inline-flex; align-items: center; gap: var(--sp-2); }
.header__tel-arrow { color: var(--on-dark-3); transition: transform .15s, color .15s; }
.header__tel:hover .header__tel-arrow,
.header__tel:focus-within .header__tel-arrow { transform: rotate(180deg); color: var(--brand); }

.contacts-pop {
  position: absolute; top: calc(100% + var(--sp-3)); right: 0; z-index: 40;
  display: grid; gap: var(--sp-2);
  min-width: 240px; padding: var(--sp-4);
  background: var(--canvas); border-radius: var(--radius-lg);
  box-shadow: 0 12px 32px rgba(10,13,14,.28);
  opacity: 0; visibility: hidden; transform: translateY(-4px);
  transition: opacity .15s, transform .15s, visibility .15s;
}
/* Мостик до окна: без него курсор «проваливается» в зазор и окно закрывается. */
.contacts-pop::before { content: ''; position: absolute; left: 0; right: 0; top: calc(var(--sp-3) * -1); height: var(--sp-3); }
.header__tel:hover .contacts-pop,
.header__tel:focus-within .contacts-pop { opacity: 1; visibility: visible; transform: translateY(0); }

.contacts-pop__item {
  display: flex; align-items: center; gap: var(--sp-3);
  font-size: var(--fs-sm); color: var(--ink-strong);
}
.contacts-pop__item:hover { color: var(--brand-dim); text-decoration: none; }
.contacts-pop__item .icon { color: var(--brand); }

/* Окно отделов у номера в шапке: карточки отделов сеткой, у каждой свой светлый фон
   одинаковой насыщенности — ни один отдел не выделен. Те же цвета у блоков отделов на /contacts. */
:root { --dept-a: #FCEFE6; --dept-b: #E8F0FA; --dept-c: #E9F5EC; --dept-d: #F3EDFA; --dept-e: #F7F3E3; --dept-f: #EAF4F6; }
/* Окно у номера: только отдел текущей страницы — название, телефоны, почта, «Все контакты». */
.contacts-pop__title { font-size: var(--fs-sm); font-weight: 700; color: var(--ink-strong); line-height: 1.3; max-width: 260px; }
.contacts-pop__all { justify-self: end; margin-top: var(--sp-1); font-size: var(--fs-sm); color: var(--brand-dim); }
.dept { display: grid; gap: 6px; align-content: start; padding: var(--sp-3) var(--sp-4); border-radius: var(--radius-md); }
.dept__title { font-size: var(--fs-sm); font-weight: 700; color: var(--ink-strong); line-height: 1.3; }
.dept--a { background: var(--dept-a); } .dept--b { background: var(--dept-b); } .dept--c { background: var(--dept-c); }
.dept--d { background: var(--dept-d); } .dept--e { background: var(--dept-e); } .dept--f { background: var(--dept-f); }
/* Отделы на /contacts: строка из трёх колонок на div — кадр отдела | название, телефоны, почта | разделы
   или описание. На телефоне кадр скрыт, колонки встают друг под другом. */
.contacts-depts { display: grid; gap: var(--sp-4); margin: var(--sp-6) 0 var(--sp-5); }
.dept-row { display: grid; grid-template-columns: 200px minmax(240px, 1fr) minmax(0, 1.4fr); gap: var(--sp-5); align-items: start; padding: var(--sp-4); border-radius: var(--radius-lg); }
.dept-row__image { display: block; width: 100%; aspect-ratio: 3 / 2; object-fit: cover; border-radius: var(--radius-md); }
.dept-row__main { display: grid; gap: 6px; align-content: start; }
.dept-row__title { margin: 0 0 var(--sp-1); font-size: 1.125rem; line-height: 1.3; }
.dept-row__aside { margin: 0; font-size: var(--fs-sm); line-height: 1.55; }
.dept-row__links { display: grid; gap: 6px; margin: 0; padding: 0; list-style: none; font-size: var(--fs-sm); }
.dept__line { display: flex; align-items: center; gap: var(--sp-2); margin: 0; }
.dept__line .icon { color: var(--brand); flex: none; }
.contacts-service { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: var(--sp-4); margin-bottom: var(--sp-5); }
.contacts-service__title { margin: var(--sp-8) 0 var(--sp-4); }
.dept__note { margin: 0 0 var(--sp-2); font-size: var(--fs-sm); color: var(--ink-muted, #5b6166); }
@media (max-width: 900px) {
  .dept-row { grid-template-columns: 1fr 1fr; }
  .dept-row__image { display: none; }
}
@media (max-width: 600px) {
  .dept-row { grid-template-columns: 1fr; gap: var(--sp-3); }
}
/* Номер 8 800 при наведении на блок шапки открывается целиком: main.js снимает приглушение по
   data-contact, это правило — страховка на время, пока скрипт не отработал. */
.has-js-contacts .header__tel:hover .contact__tail,
.has-js-contacts .header__tel:focus-within .contact__tail { -webkit-mask-image: none; mask-image: none; }
.header__phone {
  font-size: var(--fs-lead); font-weight: 700; color: var(--on-dark);
  white-space: nowrap; font-variant-numeric: tabular-nums;
}
.header__phone:hover { color: var(--brand); text-decoration: none; }
.header__hours { font-size: var(--fs-caption); color: var(--on-dark-3); white-space: nowrap; }

.burger {
  display: none; width: 48px; height: 48px; margin-right: calc(var(--sp-3) * -1);
  border: 0; background: none; color: var(--on-dark); cursor: pointer;
}

@media (max-width: 1460px) {
  .nav__list { gap: var(--sp-2); }
  .nav__link { font-size: var(--fs-sm); }
  .header__main .wrap { gap: var(--sp-5); }
  .header__contacts { gap: var(--sp-4); }
}

@media (max-width: 1200px) {
  .nav__list { gap: var(--sp-2); }
  .nav__link { font-size: var(--fs-sm); }
  .header__hours { display: none; }
}

@media (max-width: 1200px) {
  /* Служебная строка: «Контакты» остаются рядом с выбором города — это главная
     навигационная ссылка, а в бургере её видно только после раскрытия меню.
     Остальное (документы, гарантия) уезжает в бургер. */
  .header__top-links { margin-left: auto; }
  .header__top-link { display: none; }
  /* Ссылка навигационная, а не служебная: набираем её тем же цветом, что название города. */
  .header__top-link--contacts { display: inline; color: var(--on-dark-2); font-weight: 500; }
  .header__top .wrap { justify-content: flex-start; }
  .burger { display: inline-flex; align-items: center; justify-content: center; }
  .header__contacts { margin-left: auto; }

  .nav {
    position: fixed; inset: 0 0 0 auto; z-index: 60;
    width: min(380px, 88vw);
    padding: var(--sp-6) var(--sp-5) var(--sp-8);
    background: var(--dark-2);
    border-left: 1px solid var(--hairline-dark);
    overflow-y: auto;
    transform: translateX(100%);
    transition: transform .2s ease-out;
    visibility: hidden;
  }
  .nav.is-open { transform: none; visibility: visible; }
  .nav__list { flex-direction: column; gap: 0; }
  .nav__item { border-bottom: 1px solid var(--hairline-dark); }
  .nav__link { display: flex; width: 100%; padding-block: var(--sp-4); font-size: var(--fs-base); border-bottom: 0; }
  .nav__item:has(.nav__sub) > .nav__link::after { margin-left: auto; }

  /* visibility: inherit, а не visible. С visible подменю
     оставалось «видимым» для браузера даже при закрытом меню, а меню лежит
     за правым краем экрана — отсюда горизонтальная прокрутка всей страницы
     на телефоне. */
  .nav__sub {
    position: static; opacity: 1; visibility: inherit; transform: none;
    min-width: 0; padding: 0 0 var(--sp-4);
    background: none; border: 0; box-shadow: none;
  }
  /* Подпункты набраны тем же цветом, что и лид на тёмном: при --on-dark-3 (46% белого) они читались как выключенные. */
  .nav__sub a { padding: var(--sp-2) 0 var(--sp-2) var(--sp-4); color: var(--on-dark-2); }

  /* В бургере второго уровня нет: пункт ведёт на свой раздел, а список страниц лежит на нём. */
  .nav__fly-list { display: none; }
  .nav__fly > a::after { display: none; }
}

@media (max-width: 640px) {
  .header__contacts .btn { display: none; }
  .header__main .wrap { gap: var(--sp-2); min-height: 64px; }
  .header__contacts { gap: var(--sp-3); }
  /* Номер остаётся в главной строке, рядом со знаком. Место под всё сразу — знак, дескриптор,
     номер и кнопку меню — набирается кеглем: дескриптор 11px, знак 24px.
     Внутри картинки logo.png та же надпись выходила около 7px. */
  .header__phone { font-size: var(--fs-caption); }
  .logo__img { height: 24px; }
  .logo { gap: var(--sp-2); }
  /* Дескриптор и номер 13px: 11px нарушали правило
     проекта «любой видимый текст не мельче 13px» и всплывали в каждой проверке.
     Раньше кегль был занижен ради того, чтобы знак, дескриптор, номер и кнопка
     меню помещались в 360px — поэтому после подъёма обязательно проверять
     прокрутку на 320/360/414. */
  /* Кегль штатный (13px): всё, что мельче, нарушает правило проекта «видимый текст
     не мельче 13px» и всплывает в каждой проверке вёрстки. Ступени вниз, где
     дескриптор действительно отнимает ширину у номера, — в медиазапросах 400 и 340px. */
  .logo__text { font-size: 0.8125rem; line-height: 1.15; letter-spacing: 0; }

  /* Стрелка и окно со вторым номером на телефоне убраны: окно открывается
     наведением и :focus-within, а на тач-экране ни того, ни другого нет —
     стрелка обещала действие, которого не происходит, и занимала 15px ширины,
     которых шапке не хватало. Второй номер и почта остаются на /contacts —
     ссылка на неё стоит в верхней строке шапки. */
  .header__tel-arrow, .contacts-pop { display: none; }
}

/* ===== 10. ПЕРВЫЙ ЭКРАН ===== */
.hero {
  position: relative; overflow: hidden;
  background: var(--dark); color: var(--on-dark-2);
  padding-block: var(--sp-9) var(--sp-10);
}
.hero__inner {
  position: relative; z-index: 1;
  display: grid;
  grid-template-columns: 56fr 44fr;   /* пропорция из ТЗ: текст важнее картинки */
  gap: var(--sp-8);
  align-items: center;
}

.hero--cover {
  display: flex; flex-direction: column; justify-content: center;
  min-height: calc(100dvh - var(--header-h) - 40px);
  padding-block: var(--sp-7) calc(var(--sp-6) + 84px);   /* снизу — место под полосу */
  text-align: center;
}
.hero--cover .hero__inner { grid-template-columns: minmax(0, 100%); gap: 0; justify-items: center; }
.hero--cover .hero__text { max-width: none; width: 100%; }
.hero--cover .hero__lead { max-width: 56ch; }
.hero--cover .eyebrow { justify-content: center; }
.hero--cover h1 { max-width: 18ch; margin-inline: auto; margin-bottom: var(--sp-4); }
.hero--cover .hero__lead { margin-inline: auto; }
.hero--cover .hero__actions { justify-content: center; margin-block: 30px; }

.hero__econ {
  margin: var(--sp-4) auto 0;
  max-width: 56ch;
  font-size: var(--fs-lead);
}
.hero__econ b { color: var(--brand); font-weight: 650; }
.hero__econ span {
  display: block; margin-top: var(--sp-2);
  font-size: var(--fs-caption); color: var(--on-dark-3); font-family: var(--font);
}

/* Первый экран внутренней страницы: та же механика, что на главной, но ниже
   ростом — экран целиком отдавать под шапку статьи незачем, содержание должно
   начинаться сразу. Фотография с затемнением нужна ради
   призыва: кнопка на кадре заметно виднее, чем на белом фоне. */
.hero--page {
  display: flex; flex-direction: column; justify-content: center;
  /* Ровно видимая область: при меньшей высоте снизу выглядывает полоса
     следующей секции — она читается как дефект вёрстки.
     Вычитаем 45px, а не 40: шапка целиком занимает 119px (служебная строка 41 +
     основная 78), а --header-h описывает только основную. */
  /* Высоту шапки пишет main.js в --header-total: магическое число (119 + 45) не совпадало на
     другом масштабе, и снизу снова выглядывала полоса следующей секции.
     Запасное значение — на случай выключенного JS. */
  min-height: calc(100dvh - var(--header-total, 164px));
  padding-block: var(--sp-7);
}
.hero--page .hero__inner { grid-template-columns: minmax(0, 100%); gap: 0; }
/* Условия сделки строкой под кнопками: на внутренней странице текст выровнен по
   левому краю, поэтому пункты идут по содержимому, а не растягиваются на всю ширину. */
.hero--page .hero__facts {
  grid-template-columns: repeat(3, max-content); gap: var(--sp-7);
  margin-top: var(--sp-6); justify-items: start;
}
.hero--page .hero__facts li {
  flex-direction: row; align-items: center; justify-content: flex-start;
  padding: 0; text-align: left;
}
/* На узком экране три колонки по содержимому не помещаются и уезжают за край. */
@media (max-width: 900px) {
  .hero--page .hero__facts { grid-template-columns: 1fr; gap: var(--sp-3); margin-top: var(--sp-5); }
}
/* 26ch, а не 20: длинный заголовок услуги на 20ch ломается на четыре строки и вытягивает первый экран. */
.hero--page h1 { max-width: 26ch; margin-bottom: var(--sp-4); }
/* Подзаголовок первого экрана внутренней страницы держим в одну строку. */
.hero--page .hero__subtitle { max-width: 52ch; }
.hero--page .hero__lead { max-width: 62ch; }
.hero--page .hero__actions { margin-block: var(--sp-6) 0; }

/* Крошки на фотографии: тёмно-серый по кадру не читается.
   ⚠️ Селектор через `.hero`: базовые правила `.crumbs a` объявлены ниже по файлу
   и при равной специфичности перебивают одиночный класс. */
.hero .crumbs { color: var(--on-dark-3); }
.hero .crumbs a { color: var(--on-dark-3); }
.hero .crumbs a:hover { color: var(--on-dark); }
.hero .crumbs .crumbs__current { color: var(--on-dark-2); }
.hero .crumbs .crumbs__sep { color: var(--on-dark-3); }

/* Выделенные цифры в лиде на фотографии: --brand-dim рассчитан на белый фон и
   по тёмному кадру почти не читается, здесь нужен основной фирменный. */
.hero .lead--figures b { color: var(--brand); }

/* Лид первого экрана внутренней страницы: кадр там светлее ролика главной, и
   даже основной фирменный на асфальте пропадает — выделяем белым и весом. */
.hero--page .hero__lead b { color: var(--on-dark); font-weight: 700; }

/* Вторая кнопка стоит на фотографии: тёмная надпись по кадру не читается. */
.hero .btn--outline { color: var(--on-dark); }
.hero .btn--outline:hover { color: var(--on-dark); border-color: var(--on-dark); }

/* Кадр внутренней страницы светлее ролика на главной, поэтому левый край
   затемняется плотнее — иначе белый текст на асфальте теряется. */
.hero--page .hero__veil::after {
  background: linear-gradient(90deg, rgba(10,13,14,.72) 0%, rgba(10,13,14,.5) 45%, rgba(10,13,14,.15) 80%);
}

/* Подзаголовок первого экрана внутренней страницы: H2 под H1, набирается
   заметно мельче обычного H2 — на кадре он второй строкой оффера, а не
   заголовком секции. */
.hero__subtitle {
  max-width: 24ch; margin-block: 0 var(--sp-3);
  font-size: clamp(1.15rem, 2.2vw, 1.45rem); line-height: 1.25;
  font-weight: 700; color: var(--on-dark);
}
/* Акцент по светлому кадру: основной фирменный на солнечном асфальте тускнеет, светлый оттенок читается. */
.hero__subtitle b { color: var(--brand-light); font-weight: inherit; text-shadow: 0 1px 8px rgba(10,13,14,.45); }

/* Строка предложения на первом экране внутренней страницы: те же поля, что у
   лида, без огромного нижнего отступа главной. */
.hero__offer--page { max-width: 62ch; margin-block: var(--sp-4) 0; font-size: var(--fs-lead); }
.hero__offer--page b { color: var(--brand); font-weight: 700; }

@media (max-width: 900px) {
  .hero--page { min-height: 400px; }
  .hero--page h1 { max-width: none; }
  /* На главной блок текста на телефоне раскрывается (`display: contents`), и
     порядок задаётся вручную — там между текстом и кнопкой встаёт фотография.
     У внутренней страницы фотография одна, фоном, переставлять нечего: без
     этой отмены крошки и строка предложения уезжали выше заголовка. */
  .hero--page .hero__text { display: block; }
  .hero--page .hero__actions { margin-block: var(--sp-5) 0; }
  /* Переносы расставлены под ширину десктопа; на телефоне они рвут строки
     посреди фразы и вытягивают первый экран — текст переносится сам. */
  .hero--page .hero__subtitle br,
  .hero--page .hero__offer br { display: none; }
}

.hero--left { text-align: left; }
.hero--left .hero__inner { justify-items: stretch; }
.hero--left .eyebrow { justify-content: flex-start; }
.hero--cover.hero--left h1 {
  max-width: none; margin-inline: 0;
  font-size: clamp(1.75rem, 3.85vw, 3.6rem);
  text-wrap: nowrap;
}
.hero--left .hero__actions { justify-content: flex-start; }

/* Кнопки первого экрана вернулись к общему большому размеру: площадь сокращена не геометрией, а текстом — подписи стали
   короче. Вторая кнопка тише первой: обычное начертание и стрелка вместо
   жирного шрифта. */
.btn--quiet { font-weight: 500; }
/* Вторая кнопка первого экрана стоит на фотографии, и обводка в 24% белого на
   ней почти не читалась. */
.hero .btn--outline { border-color: rgba(255,255,255,.55); }
.hero .btn--outline:hover { border-color: var(--on-dark); }
/* Та же плотность обводки у кнопки на тёмном: на первом экране главной она стояла на 12% белого и терялась на видеофоне. */
.hero .btn--on-dark { border-color: rgba(255,255,255,.55); }
.hero .btn--on-dark:hover { border-color: var(--on-dark); }

/* Ширину не ограничиваем: переносы расставлены в разметке через <br>, по
   смыслу фразы. Контейнер, режущий строку там, где кончилось место, рвал
   «55 000 ₽/мес» и «2,5 года» в неудобных местах. */
/* Воздух между строками первого экрана — 30px.
   Значения проставлены в «родных» правилах ниже по файлу: отдельный блок
   здесь перебивался ими по порядку следования, и отступ не применялся. */
.hero__offer {
  max-width: none;
  margin-block: 30px 80px;
  font-size: clamp(1.125rem, 1.9vw, 1.625rem);
  font-weight: 600; line-height: 1.45;
  color: var(--on-dark);
}
/* Цифры дохода и срока — зелёным, без добавочного веса:
   вся строка уже полужирная. Оттенок светлее фирменного: --brand на подвижном
   тёмном кадре теряется. */
.hero__offer b { color: var(--brand-light); font-weight: inherit; }

/* Оффер и награды одной строкой. Снимки уравновешивают
   правую половину кадра, поэтому прижаты к правому краю текстовой колонки.
   Выравнивание по верху, отступы у ряда одинаковые сверху и снизу — верх
   снимков должен совпадать с верхней линией текста. */
.hero__offer-row {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: var(--sp-7); flex-wrap: wrap;
  margin-block: 30px;
}
/* Отрицательный отступ гасит полуинтерлиньяж первой строки: без него буквы
   начинаются ниже верхнего края снимка, хотя блоки выровнены. */
.hero__offer-row .hero__offer { margin-block: -0.22em 0; }

/* Снимки дипломов разной пропорции, и ряд выглядел рваным. Каждый кадр вписан в клетку одного размера на белом фоне —
   ряд ровный, при этом ничего не обрезается. Общую подложку под группой
   пробовали и убрали: лишняя рамка на первом экране. */
/* Награды прижаты к правому краю: слева от них стоит оффер, и свободное место
   должно оставаться между блоками, а не у края экрана. */
.hero__awards {
  display: flex; align-items: flex-start; justify-content: flex-end; gap: var(--sp-3);
  margin: 0; padding: 0; list-style: none;
}
.hero__awards li { display: flex; flex-direction: column; align-items: center; gap: var(--sp-2); width: 140px; }
.hero__award {
  position: relative; display: flex; align-items: center; justify-content: center;
  width: 116px; height: 92px; padding: 4px; overflow: hidden;
  background: #fff;
  border: 1px solid var(--hairline-dark); border-radius: var(--radius-md);
  cursor: zoom-in;                    /* курсор-лупа вместо приподнимания */
  transition: border-color .15s;
}
.hero__award img { display: block; max-width: 100%; max-height: 100%; width: auto; height: auto; object-fit: contain; }
.hero__award:hover { border-color: var(--brand); }
/* Лупа поверх кадра: подсказывает, что снимок открывается крупнее. */
.hero__award-zoom {
  position: absolute; right: 6px; bottom: 6px;
  display: flex; align-items: center; justify-content: center;
  width: 24px; height: 24px;
  color: #fff; background: rgba(10,13,14,.7); border-radius: var(--radius);
}
.hero__award-title {
  font-size: 0.8125rem; line-height: 1.25; text-align: center;
  hyphens: auto;                      /* «электрозаправки» в подпись 96px иначе не переносится */
  color: var(--on-dark); text-shadow: 0 1px 10px rgba(10,13,14,.8);
}

/* Первый экран на телефоне: строка над заголовком идёт
   двумя строками вплотную и отделена от него мало; разделитель между частями на
   узком экране только мешает — части и так стоят на разных строках. Подсказки у
   преимуществ выключены: раскрывать их пальцем неудобно, а строка остаётся
   ссылкой на свой раздел. */
@media (max-width: 640px) {
  .eyebrow { line-height: 1.45; margin-bottom: var(--sp-7); }
  .eyebrow__sep { display: none; }
  /* Обводка второй кнопки вдвое заметнее: 12% белого на фотографии терялись. */
  /* Обводка второй кнопки первого экрана: 28% белого на видеофоне почти не видно — держим ту же плотность, что у внутренних страниц. */
  .hero .btn--on-dark { border-color: rgba(255,255,255,.55); }
  .hero__fact-arrow, .hero__fact-toggle, .hero__hint { display: none; }
}

@media (max-width: 900px) {
  /* На телефоне ряд разворачивается в колонку, и отступ над текстом должен
     равняться отступу под ним — иначе строка о доходе висит посреди пустоты.
     */
  .hero__offer-row { gap: var(--sp-6); margin-block: var(--sp-6); }
  .hero__awards { gap: var(--sp-3); }
  .hero__awards li { width: 96px; }
  .hero__award { width: 96px; height: 76px; }
}

/* Подсказка к преимуществу первого экрана. Открывается наведением, фокусом с
   клавиатуры и классом is-open (нажатие на телефоне). Позиционируется над
   строкой: под ней у первого экрана уже нет места. */
.hero__fact-line { display: inline-flex; align-items: center; gap: var(--sp-2); }
.hero__fact-text { color: inherit; text-decoration: none; }
a.hero__fact-text:hover { text-decoration: underline; text-underline-offset: 3px; }
/* Стрелка-переключатель подсказки: своя кнопка, потому что текст рядом — ссылка. */
.hero__fact-toggle {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; padding: 0;
  background: none; border: 0; cursor: pointer; color: inherit;
}
.hero__fact-arrow { flex: none; color: var(--brand-light); transition: transform .15s; }
[data-fact] { position: relative; }
[data-fact]:hover .hero__fact-arrow,
[data-fact].is-open .hero__fact-arrow { transform: rotate(180deg); }
.hero__hint {
  position: absolute; bottom: calc(100% + 10px); left: 50%; transform: translate(-50%, 4px);
  z-index: 5; width: max-content; max-width: 320px;
  padding: var(--sp-4);
  font-size: var(--fs-caption); font-weight: 500; line-height: 1.45; text-align: left;
  color: var(--ink); background: #FFFFFF;
  border: 1px solid var(--hairline); border-radius: var(--radius-md);
  box-shadow: var(--shadow-menu);
  opacity: 0; visibility: hidden;
  transition: opacity .15s, transform .15s, visibility .15s;
  text-shadow: none;
}
.hero__hint b { color: var(--brand-dim); font-weight: 700; }
[data-fact]:hover .hero__hint,
[data-fact]:focus-within .hero__hint,
[data-fact].is-open .hero__hint {
  opacity: 1; visibility: visible; transform: translate(-50%, 0);
}
@media (max-width: 900px) {
  .hero__hint { left: 0; transform: translate(0, 4px); max-width: min(320px, 100%); }
  [data-fact]:hover .hero__hint,
  [data-fact]:focus-within .hero__hint,
  [data-fact].is-open .hero__hint { transform: translate(0, 0); }
}

/* Три преимущества — карточками с прозрачной подложкой и скруглённой рамкой
: без рамок строка читалась как случайная
   подпись под кнопками. Содержимое по центру, кегль и иконка крупнее. */
.hero__facts {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-5);
  margin: var(--sp-8) 0 0; padding: 0; list-style: none;
}
/* Поля сверху и снизу больше боковых — блок получается ближе к квадрату.
   Переносы в тексте расставлены руками
   в products.json, поэтому строка рвётся по смыслу. */
/* Без рамки и подложки: держатся зелёной
   иконкой, весом шрифта и тенью — кадр под ними остаётся открытым. */
.hero__facts li {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-4);
  font-size: var(--fs-base); font-weight: 600; line-height: 1.35;
  color: var(--on-dark); text-align: center;
  text-shadow: 0 1px 12px rgba(10,13,14,.75);
}
.icon--fact { color: var(--brand); flex: none; }

@media (max-width: 900px) {
  .hero__facts { grid-template-columns: 1fr; gap: var(--sp-3); }
  .hero__facts li { flex-direction: row; justify-content: flex-start; text-align: left; }
  .hero--cover.hero--left h1 { text-wrap: balance; }
}

.hero__bg { position: absolute; inset: 0; }
.hero__bg img { width: 100%; height: 100%; object-fit: cover; object-position: 48% 62%; }

.hero__video {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover; object-position: 50% 55%;
  opacity: 0; transition: opacity .8s ease-out;
  pointer-events: none;
}
.hero__video.is-ready { opacity: 1; }

/* Ровная серая вуаль вместо двух
   градиентов — под ней видно, что происходит на видео.

   Поверх неё — мягкая тень слева, только под текстовой колонкой. Без неё
   надзаголовок (зелёный, мелкий, вразрядку) на светлых кадрах ролика
   пропадает: у него контраст ниже, чем у белого заголовка. Правый край,
   ради которого фон и осветляли, остаётся чистым. */
.hero__veil {
  position: absolute; inset: 0;
  background-color: rgb(49, 49, 49);
  opacity: .7;
}
.hero__veil::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(90deg, rgba(10,13,14,.5) 0%, rgba(10,13,14,.28) 45%, transparent 75%);
}

/* Надзаголовок первого экрана белый, а не зелёный: мелкий текст вразрядку
   зелёным по осветлённому кадру не читается, а затемнять фон сильнее нельзя —
   ради видимости ролика вуаль и осветляли. Зелёным остаётся только маркер. */
.hero .eyebrow { color: var(--brand); text-shadow: 0 1px 10px rgba(10,13,14,.6); }

.hero--cover .hero__trust {
  display: grid; grid-template-columns: repeat(5, 1fr);
  width: 100%; margin: 0; padding: 0;
  border: 1px solid var(--hairline-dark);
  background: rgba(10,13,14,.42);
  backdrop-filter: blur(2px);
}
.hero--cover .hero__trust li {
  display: flex; align-items: center; justify-content: center; gap: var(--sp-3);
  margin: 0; padding: var(--sp-4) var(--sp-3);
  border-right: 1px solid var(--hairline-dark);
  text-align: left; line-height: 1.3;
}
.hero--cover .hero__trust li:last-child { border-right: 0; }
.icon--trust { color: var(--brand); }

/* Строка доверия на первом экране внутренней страницы: тот же приём, что на
   главной, но плашка уже — она стоит под кнопками, а не во всю ширину кадра. */
.hero--page .hero__trust {
  display: flex; flex-wrap: wrap; gap: var(--sp-3) var(--sp-6);
  margin: var(--sp-6) 0 0; padding: 0; list-style: none;
}
/* Кегль основной, а не подписной: это факты о заводе,
   которые читают, а не сноска. 13px тут читалось как «можно не читать». */
.hero--page .hero__trust li {
  display: flex; align-items: center; gap: var(--sp-2);
  margin: 0; font-size: var(--fs-base); line-height: 1.3;
}
@media (max-width: 700px) {
  .hero--page .hero__trust { gap: var(--sp-2) var(--sp-4); margin-top: var(--sp-5); }
}

@media (max-width: 1024px) {
  .hero--cover .hero__trust { grid-template-columns: repeat(2, 1fr); }
  .hero--cover .hero__trust li:nth-child(2n) { border-right: 0; }
  .hero--cover .hero__trust li { border-bottom: 1px solid var(--hairline-dark); }
  .hero--cover .hero__trust li:last-child { grid-column: 1 / -1; border-bottom: 0; }
}
@media (max-width: 560px) {
  .hero--cover .hero__trust { grid-template-columns: 1fr; }
  .hero--cover .hero__trust li { border-right: 0; }
}
.hero h1 { margin-bottom: 80px; color: var(--on-dark); max-width: 12em; }
.hero__lead { color: var(--on-dark-2); }
.hero__actions { display: flex; align-items: center; gap: var(--sp-4); flex-wrap: wrap; margin-block: 30px; }

.hero__trust {
  display: flex; flex-wrap: wrap;
  list-style: none; margin: 0; padding: 0;
  font-family: var(--font); font-size: var(--fs-caption);
  color: var(--on-dark-2);
}
.hero__trust li { padding-right: var(--sp-4); margin-right: var(--sp-4); border-right: 1px solid var(--hairline-dark); }
.hero__trust li:last-child { border-right: 0; margin-right: 0; padding-right: 0; }

.hero__media { margin: 0; }
.hero__shot { position: relative; display: block; }
.hero__media img { width: 100%; border-radius: 0; object-fit: cover; }

.hero__media figcaption {
  margin-top: var(--sp-3); padding-left: var(--sp-3);
  border-left: 2px solid var(--brand);
  font-family: var(--font); font-size: var(--fs-label); line-height: 1.5;
  color: var(--on-dark-3);
}

@media (max-width: 1024px) {
  .hero { padding-block: var(--sp-8) var(--sp-9); }
  .hero__inner { gap: var(--sp-6); }
  .hero h1 { max-width: none; }
}

@media (max-width: 900px) {
  .hero__inner { grid-template-columns: 1fr; gap: var(--sp-5); }
  .hero__text { display: contents; }
  .hero__text > .eyebrow       { order: 1; }
  .hero__text > h1             { order: 2; }
  .hero__text > .hero__lead    { order: 3; }
  .hero__text > .hero__actions { order: 4; margin-block: var(--sp-5) 0; }
  .hero__media                 { order: 5; margin-top: var(--sp-2); }
  .hero__text > .hero__trust   { order: 6; }
  .hero__actions .btn { width: 100%; }

  .hero--cover { min-height: auto; padding-block: var(--sp-8) var(--sp-9); }
  /* На телефоне поле над надзаголовком было 64px: до кнопки «Каталог и цены»
     первый экран не дотягивал. Сжато до 24px сверху и 48px снизу — обе кнопки
     помещаются в окно 700px. */
  @media (max-width: 640px) {
    .hero--cover { padding-block: var(--sp-5) var(--sp-7); }
    .hero--cover .hero__awards { margin-top: var(--sp-3); }
    /* Три диплома равными долями во всю ширину и по центру:
       фиксированная ширина карточки оставляла ряд прижатым влево. */
    .hero--cover .hero__awards {
      display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
      gap: var(--sp-3); width: 100%; justify-items: center;
    }
    .hero--cover .hero__awards li { width: 100%; }
    .hero--cover .hero__award { width: 100%; height: 64px; }
    .hero--cover .hero__text > .hero__actions { margin-block: 0; }
    /* Шаг между блоками первого экрана 16px вместо 24: на телефоне четыре
       промежутка по 24px забирали 96px — ровно те, из-за которых вторая
       кнопка уходила за границу экрана. */
    .hero--cover .hero__inner { gap: var(--sp-4); }
    .hero--cover .hero__offer-row { gap: var(--sp-4); margin-block: var(--sp-4); }
  }
  /* Кадр держим на станции и светлой стене: при 68% по вертикали в окно попадал
     тёмный асфальт, и первый экран выглядел чёрным прямоугольником. */
  .hero--cover .hero__bg img { object-position: 50% 70%; }
  /* Затемнение плотное только под текстом, ниже фотография открывается.
     ⚠️ opacity базового правила здесь снимается: вместе с ним градиент давал
     0,92 × 0,7 сверху и почти чёрный экран. */
  .hero--cover .hero__veil {
    opacity: 1;
    background:
      linear-gradient(180deg, rgba(10,13,14,.84) 0%, rgba(10,13,14,.66) 40%, rgba(10,13,14,.26) 66%, rgba(10,13,14,.44) 100%);
  }

  .hero--cover .hero__text { display: block; }
  .hero--cover .hero__actions { flex-direction: column; align-items: stretch; gap: var(--sp-3); }
  .hero--cover .hero__trust { margin-top: var(--sp-5); }
  /* На десктопе под заголовком 80px воздуха, на телефоне это половина экрана:
     строка о доходе должна отстоять от заголовка ровно настолько же, насколько
     от наград под ней. */
  .hero h1 { margin-bottom: var(--sp-6); }
}

/* ===== 11. ПОЛОСА ХАРАКТЕРИСТИК ===== */
.spec {
  background: var(--dark-2);
  border-top: 1px solid var(--hairline-dark);
  color: var(--on-dark-2);
}
.spec__list {
  display: flex; flex-wrap: wrap;
  list-style: none; margin: 0; padding: 0;
  font-family: var(--font); font-size: var(--fs-caption); line-height: 1.4;
}
.spec__list li {
  flex: 1 1 auto;
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5);
  border-right: 1px solid var(--hairline-dark);
}
.spec__list li:first-child { padding-left: 0; }
.spec__list li:last-child  { border-right: 0; }
.spec__list b { color: var(--on-dark); font-weight: 700; }
.icon--spec { color: var(--brand); }

.spec--overlay {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 1;
  background: rgba(10,13,14,.62);
  backdrop-filter: blur(6px);
  border-top: 1px solid var(--hairline-dark);
}
.spec--overlay .spec__list li { padding-block: var(--sp-3); }

@media (max-width: 900px) {
  .spec__list li { flex: 1 1 50%; padding-inline: 0 var(--sp-4); border-right: 0; }
  .spec__list li:nth-child(odd) { padding-left: 0; }

  .spec--overlay { position: static; background: var(--dark-2); backdrop-filter: none; }
}

/* ===== 12. КАРТОЧКИ ===== */
.card {
  position: relative;
  padding-top: var(--sp-6);
  border-top: 1px solid var(--hairline);
  background: none;
}
/* Иконка обтекается текстом: она встроена в левый верхний угол карточки, а не
   отодвигает заголовок и абзац вправо колонкой. */
.card__head {
  float: left;
  margin: 0 var(--sp-4) var(--sp-2) 0;
  color: var(--brand);
}

/* Короткая карточка с иконкой по центру: текста мало, и обтекание не нужно —
   иконка стоит над заголовком, всё выровнено по центру. */
.card--center { text-align: center; }
.card--center .card__head { float: none; display: block; margin: 0 0 var(--sp-3); }
.card--center .card__head svg { display: block; margin-inline: auto; }
.card--center .card__title { min-height: 0; }
/* Заголовок держит высоту двух строк: иначе в ряду из трёх карточек абзацы
   стартуют на разной высоте — у короткого заголовка текст поднимается, и ряд
   читается неровно. */
/* Верхнее поле снимаем: общее правило h3 отодвигало заголовок вниз, и обтекающая
   иконка оказывалась выше первой строки — она висела над заголовком отдельно. */
.card__title {
  font-size: var(--fs-h3); line-height: 1.25; letter-spacing: var(--ls-h3);
  margin-top: 0; margin-bottom: var(--sp-3);
  min-height: calc(2 * 1.25em);
}
.card p { font-size: var(--fs-sm); color: var(--body); }
/* Схема в карточке (две архитектуры зарядного хаба): рисунок идёт над
   заголовком и тянется на всю ширину карточки. Фон светлый — SVG нарисован
   на белом, на тёмной секции такие карточки не используются. */
.card__scheme {
  display: block; width: 100%; height: auto;
  margin-bottom: var(--sp-4); padding: var(--sp-4);
  background: var(--surface); border: 1px solid var(--hairline); border-radius: 2px;
}
.card::after { content: ''; display: block; clear: both; }

.section--dark .card { border-top-color: var(--hairline-dark); }
.section--dark .card p { color: var(--on-dark-2); }

/* Рассказ о производстве идёт продолжением блока про завод, без своего
   заголовка: отделяем его воздухом и шириной строки, а не линией. */
.plant__lead { margin: var(--sp-8) 0 0; }

/* ===== 13. ПОКАЗАТЕЛИ ===== */
.stats { display: grid; grid-template-columns: repeat(4, 1fr); }
.stats__item {
  padding: 0 var(--sp-5);
  border-left: 1px solid var(--hairline);
}
.stats__item:first-child { padding-left: 0; border-left: 0; }
.stats__value {
  display: block; margin-bottom: var(--sp-3);
  font-size: var(--fs-stat); font-weight: 700; line-height: 1;
  letter-spacing: var(--ls-display); color: var(--brand);
}
/* Единица измерения набирается 0.6 от цифры: на телефоне это 17px, то есть уже
   не крупный текст, и фирменный зелёный даёт 3,91:1. Для мелкого зелёного в
   проекте есть --brand-dim (6,62:1) — цифра рядом остаётся на --brand. */
.stats__value small { font-size: .6em; font-weight: 700; color: var(--brand-dim); }
.stats__label { font-size: var(--fs-caption); color: var(--muted); }

/* Цифры завода — одной рамкой на весь ряд:
   четыре отдельные плитки распадались, а вместе читаются как показатели
   одного предприятия. Кегль цифры крупнее, подпись — 15px и темнее. */
.stats--framed {
  margin-top: var(--sp-7);
  padding: var(--sp-6) var(--sp-5);
  border: 1px solid var(--hairline-strong);
  border-radius: var(--radius-lg);
}
.stats--framed { text-align: center; }          /* цифра и подпись по центру ячейки */
/* Цифра не переносится и подстраивается под ширину ячейки: «165 000 м²» на узком контейнере рвалось на две строки, и
   единица измерения повисала под числом. Заодно боковые поля ячеек уже —
   ряду из четырёх показателей нужна ширина, а не воздух по краям. */
.stats--framed .stats__item { padding-inline: var(--sp-4); }
.stats--framed .stats__value { font-size: clamp(1.875rem, 2.6vw, 3.25rem); white-space: nowrap; }
.stats--framed .stats__label { font-size: 0.9375rem; color: rgb(58, 66, 70); line-height: 1.35; }

/* Показатели полосой под первым экраном. Без рамки:
   блок и так отделён от тёмного экрана сменой фона, а вторая рамка внутри
   белой полосы превратила бы её в карточку. Держат волосяные линии между
   колонками и воздух сверху-снизу. */
.section--figures { padding-block: var(--sp-7); }
.stats--band { text-align: center; }
.stats--band .stats__item { padding-inline: var(--sp-4); }
.stats--band .stats__value { font-size: clamp(1.75rem, 2.4vw, 2.75rem); white-space: nowrap; }
.stats--band .stats__label { font-size: 0.9375rem; color: var(--body); line-height: 1.35; }
/* Показатели технопарка — светлой полосой под первым экраном:
   тёмный первый экран и тёмная полоса подряд читались мрачно, а оранжевый на чёрном
   особенно. Цифры фирменные оранжевые, подписи — основным текстом, как у elli. */
.stats--band .stats__value { color: var(--brand); }
.stats--band .stats__value small { color: var(--brand); }

/* Плашка поверх карты: название компании, адрес и кнопка контактов. */
.geo__map-wrap { position: relative; }
.geo__plate {
  position: absolute; z-index: 2; top: var(--sp-5); left: var(--sp-5);
  display: grid; gap: var(--sp-3); justify-items: start;
  max-width: 320px; padding: var(--sp-5);
  background: var(--dark); color: var(--on-dark);
  border-radius: var(--radius-md); box-shadow: var(--shadow-menu);
}
.geo__plate-title { font-size: var(--fs-h4); }
.geo__plate-addr { font-size: var(--fs-sm); color: var(--on-dark-2); }
@media (max-width: 768px) {
  /* Карта на телефоне не грузится — плашка остаётся самостоятельным блоком с адресом. */
  .geo__plate { position: static; max-width: none; }
}

@media (max-width: 900px) {
  .section--figures { padding-block: var(--sp-6); }
  .stats--band { gap: var(--sp-5) 0; }
}

/* Две кнопки в ряд по центру: целевая и второстепенная. */
.section__cta--pair {
  display: flex; flex-wrap: wrap; gap: var(--sp-4);
  align-items: center; justify-content: center;
}
@media (max-width: 560px) { .section__cta--pair .btn { width: 100%; } }

@media (max-width: 900px) {
  /* minmax(0, …): у показателей значение набрано white-space: nowrap, и колонка
     «1fr» раздувалась до его ширины — сетка вылезала за экран на узких телефонах. */
  .stats { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-6) 0; }
  .stats__item:nth-child(odd) { padding-left: 0; border-left: 0; }
}

/* Ниже 560px показатели идут столбиком. Значение набрано без переноса,
   и такие подписи, как «ПП РФ №719» или «60–240 кВт», в половину
   ширины телефона не помещаются: ячейка получалась 108px против нужных 175,
   ряд вылезал за экран и вся страница получала горизонтальную прокрутку.
   Одна колонка сохраняет и цельность цифры, и ширину под неё. */
@media (max-width: 560px) {
  .stats { grid-template-columns: minmax(0, 1fr); gap: var(--sp-5) 0; }
  .stats__item { padding-left: 0; border-left: 0; }
}

/* ===== 14. ПОДВАЛ ===== */
.footer {
  background: var(--dark); color: var(--on-dark-2);
  padding-block: var(--sp-9) var(--sp-6);
  font-size: var(--fs-sm);
}
/* На телефоне подвал набирается основным кеглем: 15px в списке ссылок и в
   строке под логотипом читались мелко. */
@media (max-width: 640px) {
  .footer { font-size: var(--fs-base); }
  .footer__brand p, .footer__home { font-size: var(--fs-base); color: var(--on-dark-2); }
}
.footer a { color: var(--on-dark-2); }
.footer a:hover { color: var(--on-dark); text-decoration: none; }
.footer h4 {
  margin-bottom: var(--sp-5);
  font-family: var(--font); font-size: var(--fs-label); font-weight: 700;
  letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--brand);
}
/* Шесть ячеек: блок бренда, каталог, услуги с инвестором, решения, «Компания» и
   разъёмы. Колонки равной ширины,
   шире только блок бренда: списки в них разной длины, но выравнивать их по
   самому длинному незачем — читается сверху вниз. */
.footer__cols { display: grid; grid-template-columns: 1.5fr repeat(5, minmax(0, 1fr)); gap: var(--sp-6); }
@media (max-width: 1280px) {
  .footer__cols { grid-template-columns: 1.4fr repeat(4, minmax(0, 1fr)); }
}
.footer__list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-1); }
/* Вторая группа в той же ячейке («Инвестору» под «Решениями»). */
.footer__col h4 + ul + h4 { margin-top: var(--sp-6); }
/* Широкая колонка: ссылки в два столбца. Grid здесь не годится — columns
   раскладывает список по высоте сам, не деля пункты пополам вручную. */
/* Колонка с двумя столбцами ссылок («Услуги» — четырнадцать разделов) занимает две ячейки сетки:
   в одной ячейке столбцы получаются уже названия раздела и текст наезжает друг на друга. */
.footer__col--wide { grid-column: span 2; }
.footer__list--two { display: block; columns: 2; column-gap: var(--sp-5); }
.footer__list--two li { break-inside: avoid; }
/* Блок совместимости переехал в первый столбец, под адрес:
   так подвал стал компактнее. Отдельная линия ему там не нужна — хватает отступа,
   а кегль совпадает с соседними абзацами колонки. */
.footer__compat { margin-top: var(--sp-5); }
/* Текст о совместимости — var(--fs-caption), мельче абзацев колонки. */
.footer__brand .footer__compat p { font-size: var(--fs-caption); }
.footer__compat p { margin: 0 0 var(--sp-2); color: var(--on-dark-3); font-size: var(--fs-caption); line-height: 1.5; }
.footer__compat p:last-child { margin-bottom: 0; }
.footer__compat a { color: var(--on-dark-2); text-decoration: underline; text-underline-offset: 2px; }
.footer__compat a:hover { color: #fff; }

.footer__copy { color: var(--on-dark-3); font-size: var(--fs-caption); margin-bottom: var(--sp-3); }
.footer__logo { height: 32px; width: auto; margin-bottom: var(--sp-5); }
.footer__brand p { color: var(--on-dark-3); font-size: var(--fs-sm); line-height: 1.5; }
/* Логотип с дескриптором — ссылка на главную. Цвет и
   кегль те же, что у соседних абзацев: ссылка не должна выглядеть кнопкой. */
.footer__home { display: block; color: var(--on-dark-3); font-size: var(--fs-sm); line-height: 1.5; }
.footer__home:hover { color: var(--on-dark); text-decoration: none; }
.footer__brand .footer__contact { font-size: var(--fs-sm); color: var(--on-dark); }
/* Кнопка «наверх»: белый кружок со стрелкой, всплывает после второго экрана
   (механика, цвета наши). */
/* Кнопка вызова чата — своя вёрстка, а не картинка: текст можно
   менять по времени, а на любом экране она остаётся чёткой. Круг с иконкой
   сообщения плюс плашка с надписью — компоновка привычна по Битрикс24.
   Появляется через две секунды после загрузки, как всплывает сам виджет;
   по нажатию иконка сменяется кружком ожидания и main.js подключает Jivo. */

/* Метка режима диагностики чата (?debug=chat): видно, что режим включился и
   события пишутся в лог. Обычному посетителю не показывается никогда. */
.diag-badge {
  position: fixed; left: var(--sp-3); bottom: var(--sp-3); z-index: 60;
  max-width: 320px; margin: 0; padding: var(--sp-2) var(--sp-3);
  background: var(--dark); color: var(--on-dark);
  font-size: var(--fs-caption); line-height: 1.4;
  border-left: 3px solid var(--brand);
}

.chat-call {
  position: fixed; right: var(--dock-right); bottom: calc(20px + var(--dock-lift)); z-index: 60;
  display: flex; align-items: center; gap: var(--sp-3);
  padding: 0; border: 0; background: none; cursor: pointer;
  opacity: 0; transform: translateY(8px);
  transition: opacity .25s, transform .25s;
}
.chat-call.is-visible { opacity: 1; transform: none; }

.chat-call__text {
  padding: 8px var(--sp-4);
  background: var(--dark-2); color: var(--on-dark);
  font-family: var(--font); font-size: var(--fs-sm); font-weight: 600; white-space: nowrap;
  border-radius: var(--radius-btn);
  box-shadow: 0 6px 20px rgba(10,13,14,.28);
}
/* Надпись остаётся и на телефоне: это призыв к действию, ради него кнопку и
   переверстали. На узких экранах она просто компактнее. */
@media (max-width: 480px) {
  .chat-call { gap: var(--sp-2); }
  .chat-call__text { padding: 6px var(--sp-3); font-size: var(--fs-caption); }
  :root { --dock-chat: 52px; }
}

.chat-call__circle {
  position: relative; flex: none;
  display: flex; align-items: center; justify-content: center;
  width: var(--dock-chat); height: var(--dock-chat); border-radius: 50%;
  color: #fff;
  /* Градиент снят с окна чата в настройках Jivo (образец заказчика): тёмная
     бирюза слева, фирменный зелёный справа. */
  background: linear-gradient(135deg, #0F6B5C 0%, var(--brand) 70%, var(--brand-light) 100%);
  box-shadow: 0 8px 22px rgba(252,88,0,.42);
  transition: transform .18s;
}
.chat-call:hover .chat-call__circle { transform: scale(1.06); }

/* «Стучится в экран»: круг и иконка чуть увеличиваются и возвращаются, а на
   месте увеличенного круга остаётся белый контур и плавно гаснет. */
.chat-call__circle::before {
  content: ''; position: absolute; inset: 0; border-radius: 50%;
  border: 2px solid rgba(255,255,255,.85);
  animation: chat-ring 3.4s ease-out infinite;
}
.chat-call__icon { animation: chat-knock 3.4s ease-out infinite; }

@keyframes chat-knock {
  0%, 82%, 100% { transform: scale(1); }
  88%           { transform: scale(1.1); }
  94%           { transform: scale(1); }
}
@keyframes chat-ring {
  0%, 82% { transform: scale(1);    opacity: 0; }
  88%     { transform: scale(1.1);  opacity: .9; }
  100%    { transform: scale(1.35); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .chat-call__icon, .chat-call__circle::before { animation: none; }
  .chat-call__circle::before { opacity: 0; }
}

/* Кружок ожидания: показывается, пока грузится виджет. */
.chat-call__spinner { display: none; }
.chat-call.is-loading .chat-call__icon { visibility: hidden; }
.chat-call.is-loading .chat-call__circle::before { animation: none; opacity: 0; }
.chat-call.is-loading .chat-call__spinner {
  display: block; position: absolute;
  width: 22px; height: 22px; border-radius: 50%;
  border: 2px solid rgba(255,255,255,.35); border-top-color: #fff;
  animation: chat-spin .7s linear infinite;
}
@keyframes chat-spin { to { transform: rotate(360deg); } }

.to-top {
  /* Отступ справа считается так, чтобы центр белого круга совпал с центром
     круга чата: у них разные диаметры, и одинаковый right разводит их по осям. */
  position: fixed; right: calc(var(--dock-right) + (var(--dock-chat) - var(--dock-top)) / 2); bottom: calc(28px + var(--dock-lift)); z-index: 60;
  display: flex; align-items: center; justify-content: center;
  width: var(--dock-top); height: var(--dock-top);
  color: var(--brand); background: #fff;
  border: 0; border-radius: 50%;
  box-shadow: 0 4px 16px rgba(10,13,14,.22);
  cursor: pointer;
  opacity: 0; transform: translateY(10px); pointer-events: none;
  transition: background-color .18s, color .18s, opacity .25s, transform .25s;
}
.to-top.is-visible { opacity: 1; transform: translateY(0); pointer-events: auto; }
.to-top:hover { background: var(--brand); color: #fff; }
@media (max-width: 640px) { :root { --dock-top: 40px; } .to-top { bottom: calc(16px + var(--dock-lift)); } }
/* Кнопка «наверх» встаёт НАД кнопкой чата: обе живут в правом нижнем углу и
   накладывались друг на друга — белый круг поверх зелёного. Через :has(): нет чата на странице — кнопка остаётся внизу. */
body:has(.chat-call) .to-top { bottom: calc(92px + var(--dock-lift)); }
@media (max-width: 640px) { body:has(.chat-call) .to-top { bottom: calc(84px + var(--dock-lift)); } }

/* Знаки группы: логотипы в ряд, пояснение — рядом мелким текстом.
   Отступы уменьшены в полтора раза: между колонками
   ссылок, знаком завода и копирайтом было слишком много воздуха. */
.footer__group {
  display: flex; align-items: center; gap: var(--sp-6); flex-wrap: wrap;
  margin-top: var(--sp-5); padding-top: var(--sp-4);
  border-top: 1px solid var(--hairline-dark);
}
.footer__group-logo { display: block; }
.footer__group-logo img { display: block; height: 58px; width: auto; }
/* Знак завода приглушён: в родных цветах он ярче
   логотипа Elli и перетягивал внимание на себя. Прозрачность .65,
   обесцвечивания нет: с ним знак становился совсем серым. */
.footer__group-logo--uvz { height: 38px; width: auto; opacity: .65; }

/* Знак концерна на странице о компании: там он довод для тендерного отдела,
   поэтому крупнее подвального и в полную силу цвета. */
.company__group { margin: var(--sp-6) 0 0; }
.company__group-logo { display: block; height: 64px; width: auto; max-width: 100%; }
@media (max-width: 640px) { .company__group-logo { height: 46px; } }
.footer__works {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--sp-2) var(--sp-4);
  margin-top: var(--sp-5); padding-top: var(--sp-4);
  border-top: 1px solid var(--hairline-dark);
  font-size: var(--fs-caption); line-height: var(--lh-snug);
}
.footer__works-title { color: var(--on-dark-3); }
.footer__group-text {
  flex: 1 1 320px; margin: 0;
  font-size: var(--fs-caption); color: var(--on-dark-3); line-height: var(--lh-snug);
}

/* Оговорка об оферте: та же подпись, что у нижней строки подвала, но отдельным абзацем над ней. */
.footer__offer {
  margin: var(--sp-4) 0 0;
  font-size: var(--fs-caption); line-height: 1.5; color: var(--on-dark-3);
}
.footer__offer:empty { display: none; }

.footer__bottom {
  margin-top: var(--sp-3); padding-top: var(--sp-3);
  border-top: 1px solid var(--hairline-dark);
  display: flex; justify-content: space-between; gap: var(--sp-5); flex-wrap: wrap;
  font-family: var(--font); font-size: var(--fs-caption); color: var(--on-dark-2);
}
.footer__bottom a { color: var(--on-dark-2); }
/* Ссылки подвала — самостоятельные цели нажатия, а не слова в строке: без
   вертикального поля палец попадает в них с трудом (высота строки 19px). */
/* Поле у ссылки — это её тап-таргет: на телефоне оставляем прежним, на десктопе
   строки идут плотнее. */
.footer__list a, .footer__bottom a { display: inline-block; padding-block: 6px; }
@media (min-width: 901px) { .footer__list a { padding-block: 2px; } }

@media (max-width: 900px) {
  .footer__cols { grid-template-columns: 1fr 1fr; }
  .footer__col--wide { grid-column: span 1; }
  .footer__list { gap: var(--sp-2); }
  .footer__list--two { columns: 1; }
}
@media (max-width: 560px) { .footer__cols { grid-template-columns: 1fr; gap: var(--sp-7); } }

/* ===== 15. ПРИЗЫВ К ДЕЙСТВИЮ ===== */
.cta {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-6) var(--sp-8); flex-wrap: wrap;
  position: relative;
  margin-top: var(--sp-8); padding-top: var(--sp-6);
  border-top: 1px solid var(--hairline);
}
.cta::before {
  content: ''; position: absolute; top: -1px; left: 0;
  width: 48px; height: 2px; background: var(--brand);
}
.cta__text { flex: 1 1 420px; }
.cta__title { font-size: var(--fs-h4); margin-bottom: var(--sp-2); }

.cta__action { display: flex; align-items: center; gap: var(--sp-5); flex-wrap: wrap; }

.section--dark .cta { border-top-color: var(--hairline-dark); }
.section--dark .cta .note { color: var(--on-dark-3); }

.section__cta { margin-top: var(--sp-8); text-align: center; }
/* Под кнопкой нужен воздух: следующий блок, вставший к ней вплотную, читается
   как её продолжение, и призыв теряется. Последний
   элемент секции не трогаем — там отступ даёт сама секция. */
.section__cta:not(:last-child) { margin-bottom: var(--sp-7); }
/* Кнопки под строкой предложения: между ними воздуха меньше, чем между
   кнопками и предыдущим блоком, — призыв и кнопка должны читаться связкой. */
.section__cta--offer { margin-top: var(--sp-5); }

/* Строка предложения под лидом: то же, что делает компания, но набранное так,
   чтобы взгляд её поймал по дороге к кнопке. Крупнее основного текста, по
   центру, ключевое — акцентом. */
.offer {
  max-width: 46rem; margin: 0 auto;
  font-size: var(--fs-lead); line-height: 1.5;
  text-align: center; color: var(--ink-strong);
}
.offer b { color: var(--brand-dim); font-weight: 700; }

@media (max-width: 640px) {
  .cta__action, .cta__action .btn { width: 100%; }
  .section__cta .btn { width: 100%; }
}

/* ===== 16. КВИЗ ===== */
/* Ширина карточки — 1180px: типов объекта двенадцать, и в ширину 961px они укладывались
   тремя рядами, из-за чего первый шаг перестал помещаться в экран ноутбука.
   Шире плюс мельче плитки — шаг снова виден целиком, а карточка по-прежнему
   читается как одна форма. */
.quiz {
  position: relative;
  overflow: hidden;
  max-width: 1180px;
  margin-inline: auto;
  padding: var(--sp-7) var(--sp-7) var(--sp-6);
  background: var(--quiz-bg);
  color: var(--on-dark);
  border-radius: var(--radius-lg);
}
.quiz.is-live ~ .quiz__skip,
#quiz .section__head { max-width: 1180px; margin-inline: auto; }
/* Заголовок в одну строку: две строки над карточкой
   съедали высоту, которой не хватало самому шагу. */
/* Кегль как у остальных H2: уменьшенный выбивался из
   ряда заголовков. В одну строку он помещается — карточка квиза 1180px. */
#quiz .section__head h2 { text-wrap: nowrap; }

/* Одиночный кейс на городской странице: в сетке из трёх колонок он прижимался
   к левому краю и половина ряда пустовала. */
.grid > .case-card:only-child {
  grid-column: 1 / -1;
  max-width: 560px;
  margin-inline: auto;
}
/* ===== Скрытые контакты =====================================================
   Хвост номера и имя почтового ящика приглушены, пока человек не потянулся к
   контакту: так считаются уникальные просмотры прямых контактов.
   Приглушение включает класс на <html>, который ставит main.js, — без скриптов
   контакты видны полностью. Текст остаётся в разметке: ссылка `tel:` рабочая,
   поисковик и микроразметка видят номер целиком. */
.contact__tail { transition: opacity .18s; }
/* Хвост растворяется слева направо: маска, а не размытие.
   Начало номера читается полностью, последние знаки тают — понятно, что контакт
   есть, но переписать его нельзя. */
.has-js-contacts .contact__tail {
  -webkit-mask-image: linear-gradient(90deg, rgba(0, 0, 0, .9) 0%, rgba(0, 0, 0, .25) 55%, rgba(0, 0, 0, 0) 100%);
          mask-image: linear-gradient(90deg, rgba(0, 0, 0, .9) 0%, rgba(0, 0, 0, .25) 55%, rgba(0, 0, 0, 0) 100%);
  user-select: none;
}
.has-js-contacts .contact:hover .contact__tail,
.has-js-contacts .contact:focus-visible .contact__tail {
  -webkit-mask-image: none;
          mask-image: none;
}
/* ===== Знаки мессенджеров =====
   Приём взят из проекта cncplus: фирменный цвет задаётся родителю, знак рисуется
   currentColor, при наведении гаснет прозрачностью. */
:root { --telegram: #26A5E4; --vk: #0077FF; }

/* Знак ВКонтакте набирается своим фирменным синим, знак Rutube двухцветный —
   его цвета заданы внутри самого SVG и от currentColor не зависят. */
.soc-icon--vk, .soc-link--vk .icon { color: var(--vk); }

.soc-icon {
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  color: var(--telegram);
  transition: opacity .18s;
}
.soc-icon:hover { opacity: .8; }

.soc-link {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  color: inherit; text-decoration: none;
  transition: opacity .18s;
}
.soc-link .icon { color: var(--telegram); flex-shrink: 0; }
.soc-link:hover { opacity: .8; text-decoration: none; }

/* В шапке и подвале ссылки перекрашены своими правилами — знак мессенджера держит фирменный цвет сильнее них. */
.header__top-links .soc-icon,
.footer .soc-link .icon,
.footer__contact .soc-link .icon,
.soc-icon .icon { color: var(--telegram); }
.header__top-links .soc-icon { margin-left: var(--sp-3); }
.footer__contact .soc-link { display: flex; color: inherit; margin-block: var(--sp-2) var(--sp-3); }

/* Короткий заголовок, который text-wrap: balance зря делит пополам: места в колонке
   хватает на одну строку, а браузер всё равно переносит. */
.title--one-line { text-wrap: nowrap; }
@media (max-width: 820px) { .title--one-line { text-wrap: balance; } }
/* Под заголовком воздуха чуть больше, чем над ним:
   поле секции сверху — 64px, здесь 72px, иначе заголовок «прилипал» к
   карточке квиза. */
#quiz .section__head { margin-bottom: calc(var(--sp-8) + var(--sp-2)); }
@media (max-width: 820px) { #quiz .section__head h2 { text-wrap: balance; } }

.quiz__bar {
  position: absolute; top: 0; left: 0; right: 0;
  height: 8px; background: rgba(252,88,0,.22);
}
.quiz__bar-fill { display: block; height: 100%; width: 20%; background: var(--brand); transition: width .25s ease-out; }

.quiz__step { margin: 0 0 var(--sp-7); padding: 0; border: 0; }
.quiz__step:last-of-type { margin-bottom: 0; }
.quiz.is-live .quiz__step { display: none; }
.quiz.is-live .quiz__step.is-current { display: block; }

.quiz__legend {
  padding: 0; margin-bottom: var(--sp-5);
  font-size: var(--fs-h3); font-weight: 700; letter-spacing: var(--ls-h3);
  color: var(--on-dark);
}
.quiz__sub { margin-top: calc(var(--sp-4) * -1); margin-bottom: var(--sp-5); color: var(--on-dark-2); }   /* подсказка к вопросу — рабочий текст, контраст как у основного */

.quiz__options { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: var(--sp-3); }
.quiz__options--pills { display: flex; flex-wrap: wrap; gap: var(--sp-3); }

.tile { position: relative; display: block; cursor: pointer; }
.tile input {
  position: absolute; inset: 0; width: 100%; height: 100%;
  margin: 0; opacity: 0; cursor: pointer;
}
.tile__body {
  display: flex; align-items: center; gap: var(--sp-3); min-height: 56px;   /* тап-таргет */
  padding: var(--sp-3) var(--sp-4);
  font-size: var(--fs-sm); line-height: 1.35; color: var(--on-dark);
  background: transparent;
  border: 1px solid var(--quiz-line);
  border-radius: var(--radius-md);
  transition: border-color .15s, background-color .15s;
}
.tile__body::before {
  content: ''; flex: none;
  width: 18px; height: 18px; border-radius: 50%;
  border: 1.5px solid var(--on-dark-3);
  transition: border-color .15s, box-shadow .15s;
}
.tile__text { display: block; }
.tile:hover .tile__body { border-color: var(--brand); }
.tile input:checked + .tile__body {
  border-color: var(--brand);
}
.tile input:checked + .tile__body::before {
  border-color: var(--brand);
  box-shadow: inset 0 0 0 4px var(--brand);
}
.tile input:focus-visible + .tile__body { outline: 2px solid var(--brand); outline-offset: 2px; }

/* Шесть плиток в ряд: двенадцать типов объекта ложатся в два
   ряда вместо трёх. Кадр в плитке узнаётся и в таком размере — это выбор
   «моё/не моё», а не рассматривание фотографии. */
.quiz__options--media { grid-template-columns: repeat(6, 1fr); gap: var(--sp-2); }
.tile--media .tile__body {
  display: block; min-height: 0; padding: 0; gap: 0;
  overflow: hidden;
}
.tile--media .tile__body::before { display: none; }
.tile__img {
  width: 100%; aspect-ratio: 16 / 9; object-fit: cover;

  transition: filter .15s;
}
/* Высоту ряда выравнивает сама сетка: плитка тянется на всю ячейку, поэтому
   двухстрочная подпись («Участок ещё выбираем») поднимает соседей, а не
   оставляет под ними пустое поле. Прежний min-height в две строки на телефоне
   давал заметную пустоту под каждой короткой подписью. */
.quiz__options--media .tile-slot,
.quiz__options--media .tile,
.tile--media .tile__body { height: 100%; }

/* Обёртка варианта: ячейкой сетки стала она, поэтому высоту
   тянет тоже она, а плитка занимает всю ячейку — ряд остаётся ровным.
   В строчных видах (пилюли) обёртка прозрачна для раскладки.
   Ссылки «Подробнее» в плитках нет: в квизе перелинковки нет. */
.tile-slot { display: flex; flex-direction: column; min-width: 0; }
.tile-slot .tile { flex: 1; }
.quiz__options--pills .tile-slot { display: contents; }
/* Подпись плитки без своего кегля и без жирности:
   так она не давит на кадр и читается спокойнее. */
.tile__caption {
  display: block; padding: var(--sp-2) var(--sp-3);
  line-height: 1.3;
}
.tile--media:hover .tile__img,
.tile--media input:checked + .tile__body .tile__img { filter: none; }

@media (max-width: 1100px) { .quiz__options--media { grid-template-columns: repeat(4, 1fr); } }
@media (max-width: 820px)  { .quiz__options--media { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 620px)  { .quiz__options--media { grid-template-columns: repeat(2, 1fr); } }

.tile--pill .tile__body {
  min-height: 44px; gap: 0;
  padding: var(--sp-2) var(--sp-5);
  border-radius: var(--radius-full);
}
.tile--pill .tile__body::before { display: none; }

/* Квиз: у плиток с фотографией — толстая рамка вместо
   зелёной подложки; пилюля при выборе заливается целиком; в списке «что
   передать нам» остаётся только обводка; сам список идёт в две колонки. */
.tile--media input:checked + .tile__body { border-width: 3px; border-color: var(--brand); }
.tile--media input:checked + .tile__body .tile__caption { color: var(--on-dark); }

.tile--pill input:checked + .tile__body {
  background: var(--brand-press);
  border-color: var(--brand-press);
  color: var(--on-brand);
}

.tile--check input:checked + .tile__body { background: transparent; border-width: 2px; }

/* Карта стандартов в начале статьи о разъёмах: тип тока × регион, ячейка ведёт
   в свой раздел. Заменила обложку-фотографию — по ней читатель сразу находит
   свой случай. */
.connmap { margin: 0 0 var(--sp-7); }
/* Сетка, шапка и рамки берутся у базового класса .table — он и задаёт полную
   сетку всем таблицам сайта (§3.17). Здесь только то, чего в нём нет:
   выравнивание по центру, колонка типа тока и ячейка-ссылка со знаком. */
.connmap__table th, .connmap__table td { padding: var(--sp-2); text-align: center; vertical-align: middle; }
.connmap__table thead th { white-space: normal; }
/* Колонка типа тока узкая намеренно: на телефоне таблица и так уезжает в
   прокрутку, и широкая подпись съедала бы место у самих разъёмов. */
.connmap__kind { width: 76px; background: var(--surface-3); }
@media (max-width: 640px) { .connmap__kind { width: 56px; padding-inline: var(--sp-1); } }
.connmap__kind span { display: block; font-size: var(--fs-caption); font-weight: 400; color: var(--muted); }
.connmap__cell {
  display: flex; flex-direction: column; align-items: center; gap: var(--sp-2);
  min-height: 88px; padding: var(--sp-2);
  font-size: var(--fs-caption); color: var(--text); text-decoration: none;
  border-radius: var(--radius-md);
}
.connmap__cell img { height: 52px; width: auto; }
.connmap__cell:hover { color: var(--brand-dim); background: var(--surface-2); }
.connmap__cell--tall { height: 100%; justify-content: center; }
.connmap figcaption { margin-top: var(--sp-3); font-size: var(--fs-caption); color: var(--muted); }
@media (max-width: 640px) {
  .connmap__table { min-width: 520px; }
  .connmap__cell img { height: 40px; }
}

.quiz__options--two { grid-template-columns: repeat(2, 1fr); }
@media (max-width: 700px) { .quiz__options--two { grid-template-columns: 1fr; } }

/* Один столбец задаётся явно: без него сетка раскладывает длинные варианты в три колонки по ширине карточки. */
.quiz__options--one { grid-template-columns: 1fr; }

/* Незаполненное поле ввода в шаге квиза обводится так же, как блок вариантов: у страны и города своей рамки не было. */
.quiz__question .field.is-invalid .input { border-color: var(--danger); border-width: 2px; }


.quiz__hint {
  margin: var(--sp-5) 0 0; padding-left: var(--sp-4);
  border-left: 2px solid var(--brand);
  font-size: var(--fs-sm); color: var(--on-dark-2);
}
.quiz__note { margin-top: var(--sp-5); color: var(--on-dark-3); }

.quiz__summary {
  margin-bottom: var(--sp-6); padding: var(--sp-5);
  background: rgba(0,0,0,.20); border-left: 2px solid var(--brand);
  font-size: var(--fs-sm); color: var(--on-dark);
}
.quiz__fields { gap: 0 var(--sp-5); margin-bottom: var(--sp-4); }
/* Три поля в строку: имя, телефон, почта. */
.quiz__fields--three { display: grid; grid-template-columns: repeat(3, 1fr); }
@media (max-width: 700px) { .quiz__fields--three { grid-template-columns: 1fr; } }
.quiz__req { margin: calc(var(--sp-2) * -1) 0 var(--sp-4); color: var(--on-dark-3); }
.quiz .field__label { color: var(--on-dark-2); }
.quiz .input {
  background: rgba(0,0,0,.20); border-color: var(--quiz-line); color: var(--on-dark);
}
.quiz .input::placeholder { color: var(--on-dark-3); }
.quiz .consent { color: var(--on-dark-3); }
/* В тёмной карточке квиза ссылка на документы набирается светлее текста: при одинаковом цвете её не отличить от подписи. */
.quiz .consent a { color: var(--on-dark); }
.quiz .consent a:hover { color: var(--brand); }
.quiz__submit { margin-top: var(--sp-5); }
.quiz__submit .note { margin-top: var(--sp-3); color: var(--on-dark-3); }

.quiz__question + .quiz__question { margin-top: var(--sp-7); }
/* Поле ввода после блока вариантов: без отступа они слипаются (квиз локации). */
.quiz__question + .field { display: block; margin-top: var(--sp-7); }

/* Карта в квизе по локации (страница «Бизнес на зарядных станциях»).
   Высота задана жёстко: контейнер карты без размеров Яндекс не рисует
   вовсе, а процент от высоты внутри fieldset ни во что не разрешается. */
.quiz__fields--two { display: grid; grid-template-columns: repeat(2, 1fr); }
@media (max-width: 700px) { .quiz__fields--two { grid-template-columns: 1fr; } }

/* Вопрос с несколькими полями ввода:
   страна короче, город — остальное место. */
.quiz__inputs--2 { display: grid; grid-template-columns: 1fr 2fr; gap: 0 var(--sp-5); }
@media (max-width: 700px) { .quiz__inputs--2 { grid-template-columns: 1fr; gap: var(--sp-3); } }

.quiz-map { margin-top: var(--sp-7); }
.quiz-map__label { display: block; margin-bottom: var(--sp-2); }
.quiz-map__hint { margin-bottom: var(--sp-4); }
.quiz-map__actions { display: flex; flex-wrap: wrap; gap: var(--sp-3); margin-bottom: var(--sp-4); }
/* Карточка квиза тёмная, а базовый .btn--outline красит текст в --ink: на этом
   фоне надписи кнопок пропадали. Правило то же, что у первого экрана. */
.quiz .btn--outline { color: var(--on-dark); border-color: rgba(255,255,255,.55); }
.quiz .btn--outline:hover,
.quiz .btn--outline:focus-visible { color: var(--on-dark); border-color: var(--on-dark); }
.quiz-map__canvas {
  height: 360px; border: 1px solid var(--quiz-line); border-radius: 2px;
  background: rgba(0,0,0,.20);
}
@media (max-width: 700px) { .quiz-map__canvas { height: 260px; } }
.quiz-map .note { margin-top: var(--sp-3); color: var(--on-dark-3); }


.quiz__question.is-invalid .quiz__options {
  padding: var(--sp-3);
  margin: calc(var(--sp-3) * -1);
  border: 1px solid var(--danger);
  border-radius: var(--radius-md);
}
.quiz__error { margin: var(--sp-2) 0 0; font-size: var(--fs-caption); color: var(--danger); }

.quiz__options--column { grid-template-columns: 1fr; }

.tile--check .tile__body::before { border-radius: 3px; }
.tile--check input:checked + .tile__body::before {
  box-shadow: inset 0 0 0 3px var(--quiz-bg);
  background: var(--brand);
}

.quiz__legend--final { font-size: var(--fs-h2); letter-spacing: var(--ls-h2); }
/* Кегль на пункт больше и просторнее интерлиньяж: в исходном виде текст
   финального шага читался слипшимся. */
.quiz__lead {
  margin: calc(var(--sp-3) * -1) 0 var(--sp-6);
  font-size: 1.0625rem; line-height: 1.65; color: var(--on-dark-2);
}

/* Кнопка шага крупнее по площади, кегль тот же. */
.quiz__nav .btn--primary { padding: 21px 42px; }
/* Незаполненное поле финального шага обводится так же, как непройденный вопрос
   выше: рамка цвета ошибки вокруг всего поля, а не только подпись. Для согласия рамка рисуется вокруг самого флажка — обводить
   строку с текстом целиком было бы шумно. */
.quiz .field.is-invalid .input { border-color: var(--danger); border-width: 2px; }
.quiz .consent.is-invalid input { outline: 2px solid var(--danger); outline-offset: 2px; }
.quiz .field.is-invalid::after,
.quiz .consent.is-invalid::after {
  content: 'Обязательное поле';
  display: block; margin-top: var(--sp-2);
  font-size: var(--fs-caption); color: var(--danger);
}

/* Флажок согласия на тёмной карточке: белый квадрат бил по глазам сильнее
   самого текста.
   Грабля: без appearance: none браузер рисует флажок по-своему и
   ни background, ни border не применяются — квадрат так и оставался белым.
   Поэтому вид собирается сам: серая заливка, а галочка появляется фоновым SVG
   при checked. */
/* Заливка светлее фона карточки: тёмный квадрат на
   тёмном терялся, и флажок было не видно. */
.quiz .consent input,
.lead-band__form .consent input {
  appearance: none; -webkit-appearance: none;
  margin-top: 1px;
  background: rgba(255,255,255,.16);
  border: 1px solid rgba(255,255,255,.34); border-radius: 3px;
}
.quiz .consent input:checked,
.lead-band__form .consent input:checked {
  background-color: var(--brand); border-color: var(--brand);
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23fff' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'><path d='M3 8.5l3.5 3.5L13 5'/></svg>");
  background-repeat: no-repeat; background-position: center; background-size: 14px;
}

.quiz__nav {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-4); margin-top: var(--sp-7);
}
.quiz__nav-buttons { display: flex; gap: var(--sp-3); }
.quiz__counter {
  margin: 0;
  font-family: var(--font); font-size: var(--fs-label);
  /* Не --brand: на сером фоне карточки квиза он даёт 3,23:1. Служебной подписи
     цвет-акцент не нужен, белый читается уверенно. */
  letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--on-dark-2);
}
/* Кнопка «Назад» шире и полностью статична: ни волны,
   ни зелёной обводки, ни подсветки фона — она не должна спорить с «Далее». */
.quiz__back {
  width: 64px; padding: 0;
  background: none; border: 1px solid var(--quiz-line); color: var(--on-dark-2);
}
.quiz__back::before, .quiz__back::after { content: none; }
.quiz__back:hover, .quiz__back:focus-visible {
  background: none; border-color: var(--quiz-line); color: var(--on-dark-2);
}

.quiz.is-live ~ .quiz__skip { margin-top: var(--sp-5); }
.quiz__footnote { margin-top: var(--sp-6); color: var(--on-dark-3); }
.quiz__skip { margin-top: var(--sp-5); }

@media (max-width: 640px) {
  .quiz { padding: var(--sp-5) var(--sp-4); }
  .quiz__options { grid-template-columns: 1fr; }
  .quiz__options--media { grid-template-columns: repeat(2, 1fr); }
  .quiz__nav .btn { flex: 1; }
}

/* ===== 17. КАТАЛОГ: КАРТОЧКИ СТАНЦИЙ И ПЛИТКИ ===== */
.products { align-items: stretch; }
/* Вторая сетка карточек на странице (сопутствующее оборудование после станций)
   прилипала к первой: между ними в разметке лежит только микроразметка, и
   соседний селектор через `+` её не перешагивает — поэтому `~`. */
.products ~ .products { margin-top: var(--sp-6); }
/* Карточки в листинге тянутся по высоте ряда, и кадр фото — как flex-элемент
   колонки — при этом терял свои 1:1 и сжимался. На главной этого не видно:
   там сетка без `.products`. Фиксируем кадр, чтобы обе страницы совпадали. */
.products .product__media { flex: 0 0 auto; }

/* Карточка обведена бледной рамкой со скруглением:
   без неё товары в ряду сливались в одну ленту. */
.product {
  display: flex; flex-direction: column;
  padding: var(--sp-5);
  border: 1px solid var(--hairline); border-radius: var(--radius-lg);
  background: var(--canvas);
}
.product__media {
  position: relative;
  display: flex; align-items: center; justify-content: center;
  aspect-ratio: 1 / 1; margin-bottom: var(--sp-5);
  background: transparent;
  overflow: hidden;
}
/* Кадр карточки квадратный, а фото приходят разной пропорции: у станций
   вертикальные, у аксессуаров и генераций — горизонтальные. Ограничиваем обе
   стороны, иначе горизонтальный снимок растягивается по высоте и обрезается
   боками об `overflow: hidden` родителя. */
.product__media img {
  max-width: 100%; max-height: 100%;
  width: auto; height: auto;
  object-fit: contain;
}
.product__noimage { color: var(--hairline-strong); text-align: center; display: flex; }
.product__noimage svg { width: 48px; height: 48px; }

.product__badge {
  position: absolute; top: 0; left: 0;
  padding: var(--sp-2) var(--sp-3);
  background: var(--brand-press); color: var(--on-brand);
  font-family: var(--font); font-size: var(--fs-label); font-weight: 700;
  letter-spacing: .04em; text-transform: uppercase;
}
/* Бейджи карточки: набор и цвет задаются в products.json, здесь только тона.
   Кладутся стопкой в углу фото либо
   строкой под названием — место тоже приходит из JSON. */
.product__badges {
  position: absolute; top: var(--sp-3); left: var(--sp-3); right: var(--sp-3);
  display: flex; flex-wrap: wrap; gap: var(--sp-2);
}
.product__badges--title {
  position: static; display: flex; gap: var(--sp-2);
  margin: calc(var(--sp-3) * -1) 0 var(--sp-4);
}
/* Бейджи заливные и заметные: прозрачная «Гарантия до
   7 лет» на фото не читалась вовсе, а это сильное преимущество. Радиус мелкий —
   плашка, а не пилюля; цвета сочетаются с фирменным зелёным. */
.badge {
  display: inline-flex; align-items: center;
  padding: 6px var(--sp-3);
  border-radius: 4px;
  font-size: var(--fs-caption); font-weight: 700; line-height: 1.2;
  color: #fff;
}
.badge--stock    { background: var(--brand-press); }
.badge--subsidy  { background: var(--badge-amber); }
.badge--warranty { background: var(--badge-blue); }
.badge--soon     { background: var(--badge-slate); }

/* Разъёмы — векторными логотипами от маркетинга. Type 2 использует тот же знак,
   что GB/T AC: разъём той же формы, отличается только протокол обмена данными.


   Значок 68px — вдвое крупнее прежнего и одинаковый у всех: мелкие логотипы
   разного размера в карточке не читались. */
.connectors {
  display: flex; flex-wrap: wrap; justify-content: space-around; gap: var(--sp-4);
  width: 100%; margin: 0 0 var(--sp-4); padding: 0; list-style: none;
}
.connectors__item {
  display: flex; flex-direction: column; align-items: center; gap: var(--sp-1);
  font-size: var(--fs-caption); color: var(--muted); text-align: center;
}
.connectors__item img { height: 47px; width: auto; object-fit: contain; }   /* натуральный размер файлов 52×47: растягивать растр вверх нельзя — мылит */

/* Разделы каталога тегами: прозрачная пилюля с серой обводкой. */
.tags {
  display: flex; flex-wrap: wrap; gap: var(--sp-3);
  margin: var(--sp-6) 0 0; padding: 0; list-style: none;
}
.tag {
  display: inline-flex; align-items: center; min-height: 40px;
  padding: 0 var(--sp-5);
  border: 1px solid var(--hairline-strong); border-radius: var(--radius-full);
  font-size: var(--fs-sm); color: var(--body); background: transparent;
  transition: border-color .15s, color .15s;
}
.tag:hover { border-color: var(--brand); color: var(--brand-dim); text-decoration: none; }

.products--accessories { margin-top: var(--sp-7); }

.product__title { font-size: var(--fs-h4); margin-bottom: var(--sp-4); }

/* Нижней линии у характеристик и верхней у строки покупки нет: между ними оставалась пустая полоса, зажатая двумя правилами. */
.product__specs {
  display: grid; grid-template-columns: auto 1fr; gap: var(--sp-2) var(--sp-4);
  margin: 0 0 var(--sp-4); padding: var(--sp-4) 0 0;
  border-top: 1px solid var(--hairline);
  font-size: var(--fs-caption);
}
.product__specs dt { color: var(--muted); }
.product__specs dd { margin: 0; text-align: right; color: var(--ink-strong); font-family: var(--font); }

/* Цена и кнопка в одной строке: цена слева, действие справа. */
.product__buy {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-4); flex-wrap: wrap;
  margin-top: auto;
}
/* Две кнопки в карточке: «Подробнее» прозрачной и «Запросить» — на узкой карточке встают в столбик. */
.product__actions { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
.product__actions .btn { white-space: nowrap; }
.product__price { margin: 0; }
.product__price-label { font-size: var(--fs-caption); color: var(--muted); }
.product__price b { font-size: var(--fs-h4); color: var(--ink); letter-spacing: var(--ls-h3); }
.product__price-note { font-size: var(--fs-caption); color: var(--muted); }

.product__actions { display: flex; gap: var(--sp-3); flex-wrap: wrap; }
.product__actions .btn { flex: 1 1 auto; }

/* Тезисы с галочкой — пояснение к блоку вместо абзаца. */
.points {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--sp-3) var(--sp-6);
  margin: 0 0 var(--sp-7); padding: 0; list-style: none;
}
.points--column { grid-template-columns: 1fr; margin-bottom: 0; }
@media (max-width: 720px) { .points { grid-template-columns: 1fr; } }
.points li { display: flex; gap: var(--sp-3); align-items: flex-start; font-size: var(--fs-sm); }
.points__icon { flex: none; color: var(--brand); margin-top: 1px; }
.points b { color: var(--brand-dim); font-weight: 700; }
/* Текст сразу за списком тезисов: без отступа абзац читается как продолжение последнего пункта. */
.prose .points + p { margin-top: var(--sp-5); }

.tiles {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 1px; margin: var(--sp-8) 0 0; padding: 0; list-style: none;
  background: var(--hairline);        /* фон проступает в зазорах — сетка без рамок */
  border: 1px solid var(--hairline);
}
.tiles--wide { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 900px) { .tiles--wide { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .tiles--wide { grid-template-columns: 1fr; } }
.tiles__item { background: var(--canvas); }
.tiles__item a {
  display: flex; flex-direction: column; justify-content: center; gap: var(--sp-1);
  min-height: 84px; padding: var(--sp-4) var(--sp-5);
  color: var(--ink-strong); transition: background-color .15s;
}
.tiles__item a:hover { background: var(--surface); text-decoration: none; color: var(--brand-dim); }
.tiles__title { font-size: var(--fs-sm); font-weight: 600; }
.tiles__note { color: var(--muted); }

.tiles--icons .tiles__item a { flex-direction: row; align-items: center; gap: var(--sp-4); }

.services__note { margin-top: var(--sp-5); }

/* ===== Преимущества =====
   Карточка держится не рамкой, а иконкой в зелёном круге: ряд читается как
   набор доводов, а не как таблица. */
.benefits { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-6); }
@media (max-width: 900px) { .benefits { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 640px) { .benefits { grid-template-columns: 1fr; } }

.benefit {
  display: flex; flex-direction: column; gap: var(--sp-3);
  padding: var(--sp-6);
  background: var(--canvas);
  border: 1px solid var(--hairline); border-radius: var(--radius-lg);
}
.benefit__icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 52px; height: 52px; margin-bottom: var(--sp-2);
  color: var(--brand); background: rgba(252,88,0,.1); border-radius: 50%;
}
.benefit__title { font-size: var(--fs-h4); margin: 0; }
.benefit__text  { font-size: var(--fs-sm); color: var(--body); margin: 0; }

/* Фотография вместо шестой карточки: заполняет ячейку целиком, без полей. */
.benefit--media { padding: 0; overflow: hidden; margin: 0; }
.benefit--media img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ===== Решения под тип объекта =====
   Фотография слева, текст справа — карточка читается одной строкой взгляда.
   Кадр фиксированной ширины: снимки разного размера, но ряд должен быть ровным. */
.solutions {
  display: grid; grid-template-columns: repeat(2, 1fr);
  gap: 1px; margin: 0; padding: 0; list-style: none;
  background: var(--hairline); border: 1px solid var(--hairline);
}
@media (max-width: 720px) { .solutions { grid-template-columns: 1fr; } }

.solutions__item { background: var(--canvas); }
.solutions__link {
  display: flex; align-items: center; gap: var(--sp-5);
  height: 100%; padding: var(--sp-4);
  color: var(--ink-strong); transition: background-color .15s;
}
.solutions__link:hover { background: var(--surface); text-decoration: none; }
.solutions__link:hover .solutions__title { color: var(--brand-dim); }
/* Тип объекта, под который страницы ещё нет: та же плитка, но без отклика на
   наведение — иначе она обещает переход, которого не будет. */
.solutions__link--flat { cursor: default; }
.solutions__link--flat:hover { background: transparent; }
.solutions__link--flat:hover .solutions__title { color: inherit; }

.solutions__img {
  flex: none; width: 180px; height: 120px;
  object-fit: cover; border-radius: var(--radius);
}
/* На телефоне кадр уходит наверх во всю ширину: узкая колонка текста рядом с
   картинкой рвёт заголовок на четыре строки. */
@media (max-width: 560px) {
  .solutions__link { flex-direction: column; align-items: stretch; gap: var(--sp-4); }
  .solutions__img { width: 100%; height: 150px; }
}

/* Решения лентой: карточка вертикальная, кадр сверху.
   Рамка и разделители сетки здесь не нужны — карточки разделяет промежуток
   ленты, а фон белый. */
.slider--solutions .solutions__item {
  background: var(--canvas);
  border: 1px solid var(--hairline); border-radius: var(--radius-lg);
  overflow: hidden;
}
.slider--solutions .solutions__link {
  flex-direction: column; align-items: stretch; gap: var(--sp-4);
  padding: 0 0 var(--sp-5);
}
.slider--solutions .solutions__img { width: 100%; height: 150px; border-radius: 0; }
.slider--solutions .solutions__body { padding-inline: var(--sp-5); }
.slider--solutions .solutions__title { font-size: 1.0625rem; }
/* Лента статей: карточка растягивается на всю высоту слайда, кнопка внизу. */
.slider--posts .slider__slide { display: flex; }
.slider--posts .post { width: 100%; }

.solutions__body { display: block; }
.solutions__title { display: block; font-size: var(--fs-h4); font-weight: 600; margin-bottom: var(--sp-2); }
.solutions__text  { display: block; font-size: var(--fs-sm); color: var(--muted); }

/* Что клиент получает, работая с нами: продолжение того же блока, поэтому
   без своей секции и без фона — только заголовок и плитки услуг. */
.services { margin-top: var(--sp-8); }
.services__title { font-size: var(--fs-h3); text-align: center; margin-bottom: var(--sp-5); }
.services__list {
  display: grid; grid-template-columns: repeat(2, 1fr);
  gap: 1px; margin: 0; padding: 0; list-style: none;
  background: var(--hairline); border: 1px solid var(--hairline);
}
@media (max-width: 720px) { .services__list { grid-template-columns: 1fr; } }
.services__item { background: var(--canvas); }
.services__item a {
  display: flex; align-items: center; gap: var(--sp-4);
  min-height: 76px; padding: var(--sp-4) var(--sp-5);
  font-size: var(--fs-sm); font-weight: 600;
  color: var(--ink-strong); transition: background-color .15s;
}
.services__item a:hover { background: var(--surface); text-decoration: none; color: var(--brand-dim); }

.subcatalog { margin-top: var(--sp-8); }
.subcatalog__title { font-size: var(--fs-h4); margin-bottom: var(--sp-5); }
.subcatalog .tiles { margin-top: 0; grid-template-columns: repeat(4, 1fr); }
@media (max-width: 900px) { .subcatalog .tiles { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .subcatalog .tiles { grid-template-columns: 1fr; } }
.subcatalog__note { margin: var(--sp-4) 0; }

/* ===== 18. ТАБЛИЦЫ ===== */
.table-scroll {
  overflow-x: auto;                      /* узкий экран прокручивает таблицу, а не страницу */
  overscroll-behavior-x: contain;        /* прокрутка таблицы не листает страницу за её краем */
  /* Поля задаются обёртке, а не таблице: между текстом и таблицей может стоять
     указатель прокрутки, и правило «соседу через +» тогда не срабатывает.
     */
  margin-block: var(--sp-5) var(--sp-6);
}

/* Указатели прокрутки над и под таблицей — их ставит main.js у таблиц, которые
   шире экрана. Нативная полоса на телефоне видна только во время движения. */
.table-scroll__bar {
  position: relative; height: 6px; border-radius: 3px;
  background: var(--surface-2);
}
.table-scroll__bar--top    { margin-bottom: var(--sp-3); }
.table-scroll__bar--bottom { margin-top: var(--sp-3); }
.table-scroll__thumb {
  position: absolute; inset-block: 0; left: 0;
  border-radius: 3px; background: var(--brand);
}
/* Нативную полосу прячем: положение показывают наши указатели, а вместе с ней
   под таблицей получалось две полосы подряд.
   Прокрутка колесом, пальцем и клавишами при этом работает как обычно. */
.table-scroll { scrollbar-width: none; }
.table-scroll::-webkit-scrollbar { height: 0; width: 0; }
/* Полная сетка у всех таблиц сайта: вертикальные линии
   наравне с горизонтальными, строка заголовков залита серым. Одни
   горизонтальные линии читаются как несколько независимых столбцов текста, а
   не как таблица; так же был свёрстан прайс, и это решение распространено на
   остальные таблицы.

   Две грабли, из-за которых линий может снова не стать (уже ловились на прайсе):
   1) `tr:last-child { border-bottom: 0 }` специфичнее одного класса и срезает
      нижнюю границу — здесь такого правила нет намеренно;
   2) `border-collapse: collapse` вместе с `overflow: hidden` и скруглением
      прячет крайние линии под радиусом: радиус — только у обёртки. */
.table {
  width: 100%; border-collapse: collapse;
  font-size: var(--fs-sm);
  border: 1px solid var(--faint);
}
.table th, .table td {
  padding: var(--sp-1) var(--sp-4);
  text-align: left; vertical-align: top;
  border: 1px solid var(--faint);
}
.table thead th {
  font-family: var(--font); font-size: var(--fs-label); font-weight: 700;
  letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--ink-strong);
  text-align: center;
  background: var(--surface-3);
  border-bottom-color: var(--hairline-strong);
  white-space: nowrap;
}
.table tbody th { font-weight: 600; color: var(--ink-strong); }
.table td { color: var(--body); }

.table__row--accent th, .table__row--accent td { color: var(--brand-dim); font-weight: 600; }

/* Смета по статьям: строка-статья и строки расшифровки под ней. Статья держится
   фоном и весом, расшифровка — отступом и приглушённой подписью; так таблица
   читается сверху вниз как оглавление сметы, а не как ровный список. */
.table__row--group th, .table__row--group td { background: var(--surface-2); font-weight: 600; color: var(--ink-strong); }
.table__cell--sub { padding-left: var(--sp-6); color: var(--muted); }
.table__col--accent { background: var(--surface); }
.section--surface .table__col--accent { background: var(--canvas); }
.table__footnote { margin-top: var(--sp-5); font-size: var(--fs-sm); color: var(--muted); }

/* Варианты комплектации площадки: снимок, заголовок, короткое описание и
   признаки списком. Три карточки в ряд, на планшете две, на телефоне одна. */
.setup { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp-6); }
@media (max-width: 1000px) { .setup { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 680px)  { .setup { grid-template-columns: 1fr; } }

.setup__item {
  display: flex; flex-direction: column;
  background: var(--canvas);
  border: 1px solid var(--hairline); border-radius: var(--radius-lg);
  overflow: hidden;
}
.section--surface .setup__item { background: var(--surface); }
.setup__img { display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover; }
.setup__title { margin: var(--sp-5) var(--sp-5) var(--sp-3); font-size: var(--fs-h4); }
.setup__text  { margin: 0 var(--sp-5) var(--sp-4); font-size: var(--fs-sm); color: var(--body); }
.setup__list  { margin: 0 var(--sp-5) var(--sp-5); padding-left: var(--sp-5); font-size: var(--fs-sm); color: var(--body); }
.setup__list li { margin-bottom: var(--sp-2); }
.setup__list li::marker { color: var(--brand); }

/* Список нормативных документов: иконка, название и реквизиты. Файлы сводов
   правил у себя не размещаем, поэтому это не ссылки на скачивание, а карточки
   с выходными данными — по ним документ находится в государственном реестре. */
.doc-list { display: grid; gap: var(--sp-4); margin: var(--sp-5) 0; padding: 0; list-style: none; }
.doc-list__item {
  display: flex; gap: var(--sp-4); align-items: flex-start;
  padding: var(--sp-5);
  background: var(--surface); border: 1px solid var(--hairline); border-radius: var(--radius-lg);
}
.doc-list__icon { flex: 0 0 auto; color: var(--brand); margin-top: 2px; }
/* Скан первой страницы вместо иконки: документ узнаётся сразу, и видно, что мы
   держали его в руках, а не пересказываем по памяти. */
.doc-list__scan {
  flex: 0 0 auto; width: 92px; height: auto;
  border: 1px solid var(--hairline); border-radius: 2px; background: var(--canvas);
}
@media (max-width: 560px) { .doc-list__scan { width: 68px; } }
.doc-list__body { font-size: var(--fs-sm); color: var(--body); }
.section--surface .doc-list__item { background: var(--canvas); }

/* Колонка с миниатюрой площадки: снимок делает таблицу читаемой сканированием,
   а не сплошным текстом. На телефоне колонка скрывается — там дорог каждый
   пиксель ширины, а фотография не несёт данных. */
/* Длинный заголовок колонки в узкой таблице переносится по словам: с nowrap
   он забирает ширину у соседей, и подпись строки рвётся по слогам. */
.table--wrap-head thead th { white-space: normal; }

.col--thumb { width: 120px; }
.table__thumb { width: 120px; padding: var(--sp-2) !important; }
.table__thumb img { display: block; width: 120px; height: 70px; object-fit: cover; border-radius: 2px; }
@media (max-width: 700px) { .table__thumb { display: none; } }

/* На телефоне колонки не сжимаются до вертикальной строчки: ячейка переносится
   по словам, а всё, что не влезло, уезжает в горизонтальную прокрутку обёртки.
   Без этого браузер делит ширину экрана между всеми колонками поровну и в
   узких столбцах остаётся по одной букве в строке. */
@media (max-width: 640px) {
  .table { font-size: 0.8125rem; }
  .table th, .table td { padding: var(--sp-3); word-break: normal; }
  /* Пояснение под значением переносится по словам и не растягивает колонку. */
  .table .note { display: block; max-width: 17rem; white-space: normal; }

  /* Подпись строки занимала треть экрана, хотя текст в ней спокойно переносится:
     сужаем её и отдаём место цифрам. */
  .table thead th:first-child,
  .table tbody th[scope="row"] { max-width: 8.5rem; }

  /* Заголовки колонок переносятся по словам: с nowrap длинное название
     распирало узкую колонку и налезало на соседнюю. */
  .table thead th { white-space: normal; }

  /* Колонка с коротким значением (число, срок): ширину задаём в colgroup таблицы. */
  .table col.col--tight { width: 4.5rem; }

  /* Подпись строки закреплена у левого края: при прокрутке вбок иначе не видно,
     к какой строке относятся цифры. Фон обязателен — сквозь прозрачную ячейку
     просвечивают проезжающие колонки. Правая граница нарисована тенью:
     при border-collapse обычная граница за закреплённой ячейкой не едет. */
  .table { --table-bg: var(--canvas); }
  .section--surface .table,
  .section--grid .table { --table-bg: var(--surface); }
  .table thead th:first-child,
  .table tbody th[scope="row"],
  .table tbody td.table__cell--sub {
    position: sticky; left: 0; z-index: 1;
    background: var(--table-bg);
    box-shadow: 1px 0 0 var(--faint);
  }
  /* Строка-статья сметы едет вместе со своим фоном, иначе закреплённая ячейка теряет заливку. */
  .table tbody tr.table__row--group th[scope="row"] { background: var(--surface-2); }
  .table tbody td.table__cell--sub { max-width: 8.5rem; padding-left: var(--sp-4); }
  /* Шапка прайса залита серым, у остальных таблиц она на фоне секции —
     закреплённая ячейка повторяет фон своей шапки, иначе над первой колонкой
     повисает серый прямоугольник. */
  .table { --table-head-bg: var(--table-bg); }
  .price { --table-head-bg: var(--surface-3); }
  .table thead th:first-child { z-index: 2; background: var(--table-head-bg); }
}

/* ===== Прайс =====
   Таблица «позиция — стоимость» в цветах сайта: тёмная шапка, чередование строк, выделенные позиции с оборудованием.
   Стоимость выровнена вправо и набрана плотнее — колонка читается столбиком. */
/* Полная сетка вместо одних горизонтальных линий, шапка серая, названия
   колонок по центру и жирным, строки плотнее. Линии
   тонкие и светлые — таблица должна оставаться воздушной. */
/* Линии сетки видимые, а не волосяные: на --hairline
   вертикальный разделитель колонок практически не читался, и таблица выглядела
   как два независимых столбца текста.
   Две грабли, из-за которых линий не было видно даже после этого:
   1) `.table tr:last-child th/td { border-bottom: 0 }` специфичнее одного
      класса и срезал нижнюю границу таблицы — здесь она возвращается;
   2) `border-collapse: collapse` вместе с `overflow: hidden` и скруглением
      прячет крайние линии под радиусом — поэтому радиус снят с самой таблицы
      и оставлен только у обёртки. */
.price { border: 1px solid var(--faint); border-collapse: collapse; }
.price th, .price td { padding: var(--sp-2) var(--sp-4); border: 1px solid var(--faint); }
.price tr:last-child th, .price tr:last-child td { border-bottom: 1px solid var(--faint); }
.price th:first-child, .price td:first-child { padding-left: var(--sp-4); }
.price thead th {
  background: var(--surface-3); color: var(--ink-strong);
  text-align: center; font-weight: 700;
  border-bottom: 1px solid var(--hairline-strong);
}
.price tbody th { font-weight: 500; color: var(--body); }
.price td.price__value {
  text-align: right; white-space: nowrap;
  font-weight: 700; color: var(--ink-strong);
  font-variant-numeric: tabular-nums;
}
.price .table__row--accent th { font-weight: 700; color: var(--ink-strong); }
.price .table__row--accent .price__value { color: var(--brand-dim); }

/* На телефоне двухколоночный прайс должен помещаться в экран целиком: иначе
   цена уезжает за край и её не видно, пока не проскроллишь таблицу вбок.
   ⚠️ Ровно для двух колонок, поэтому и отдельный класс: раньше правило стояло
   на всех .price, и таблица окупаемости из шести колонок (/biznes-na-ezs)
   отдавала 62% первой колонке, остальные пять делили остаток по 7% и текст
   рвался по буквам в вертикальную строчку.
   Многоколоночные таблицы вместо сжатия уезжают в прокрутку — см. раздел 18. */
@media (max-width: 640px) {
  .price { font-size: 0.8125rem; }
  .price th, .price td { padding: var(--sp-2) var(--sp-3); }

  .price--pair { table-layout: fixed; }
  .price--pair thead th:first-child { width: 62%; }
  /* 12px, а не 10: шапка прайса на телефоне читалась хуже всего текста вокруг.
     Помещается за счёт word-break ниже. */
  .price--pair thead th { font-size: 0.75rem; white-space: normal; }
  .price--pair th, .price--pair td { word-break: break-word; }
  .price--pair td.price__value { white-space: normal; }
}

/* Строка-подзаголовок делит прайс по темам: оборудование, проект, монтаж. */
.price__group th {
  background: var(--surface);
  font-family: var(--font); font-size: var(--fs-label); font-weight: 700;
  letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--muted);
  padding-block: var(--sp-2);
}
.section--surface .price__group th { background: var(--surface-2); }

/* Пояснения под таблицей: три колонки со списками. */
.price__notes {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-6);
  margin-top: var(--sp-6);
}
@media (max-width: 900px) { .price__notes { grid-template-columns: 1fr; gap: var(--sp-5); } }
.price__note-title { font-size: var(--fs-h4); margin-bottom: var(--sp-3); }

/* Список с зелёной галочкой: галочка рисуется псевдоэлементом, чтобы в тексте
   не было символов, зависящих от кодировки файла. */
.list-check { margin: 0; padding: 0; list-style: none; font-size: var(--fs-sm); color: var(--body); }
.list-check li { position: relative; padding-left: var(--sp-6); margin-bottom: var(--sp-2); }
.list-check li::before {
  content: '\2713'; position: absolute; left: 0; top: 0;
  color: var(--brand); font-weight: 700;
}

.table__compare {
  margin-top: var(--sp-5);
  padding-left: var(--sp-4);
  border-left: 2px solid var(--brand);
}

.table--tech td { font-size: var(--fs-caption); }
.tech__notes, .choice__notes { margin-top: var(--sp-7); }

/* ===== 19. ЭТАПЫ, ЛЕСТНИЦА, ВРЕЗКА ===== */
.steps {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-7) var(--sp-6);
  margin: 0; padding: 0; list-style: none; counter-reset: none;
}
.steps__item { position: relative; padding-top: var(--sp-5); border-top: 1px solid var(--hairline); }
.steps__item::before {
  content: ''; position: absolute; top: -1px; left: 0;
  width: 32px; height: 2px; background: var(--brand);
}
.steps__head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: var(--sp-3);
}
.steps__num {
  display: block;
  font-family: var(--font); font-size: var(--fs-label); font-weight: 700;
  letter-spacing: var(--ls-label); color: var(--faint);
}
.steps__title { font-size: var(--fs-h4); margin-bottom: var(--sp-2); }
.steps__item p { font-size: var(--fs-sm); }
.steps__outro { margin-top: var(--sp-7); }

/* ===== Субсидия: изображение с обтеканием и шаги кружками =====
   Блок на светлом фоне, кадр стоит
   справа и обтекается текстом, шаги — цифры в кружках, между ними пунктир. */
.subsidy__body::after { content: ''; display: block; clear: both; }
.subsidy__media {
  float: right; width: min(460px, 36%);
  margin: 0 0 var(--sp-5) var(--sp-7);
}
@media (max-width: 800px) {
  .subsidy__media { float: none; width: 100%; margin: 0 0 var(--sp-5); }
}
.subsidy__media img { width: 100%; height: auto; border-radius: var(--radius-lg); }
.subsidy__media figcaption {
  margin-top: var(--sp-2);
  font-size: var(--fs-caption); color: var(--muted); text-align: center;
}

.ladder {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-6) var(--sp-6);
  margin: var(--sp-8) 0 var(--sp-6); padding: 0; list-style: none;
}
@media (max-width: 900px) { .ladder { grid-template-columns: 1fr; gap: var(--sp-5); } }
.ladder__item { position: relative; display: flex; gap: var(--sp-4); align-items: flex-start; }
/* Пунктир к следующему шагу: у последних в ряду его нет. */
.ladder__item:not(:nth-child(3n)):not(:last-child)::after {
  content: ''; position: absolute; top: 21px; right: calc(var(--sp-6) / -1);
  width: var(--sp-6); border-top: 2px dashed var(--hairline-strong);
}
@media (max-width: 900px) { .ladder__item::after { display: none; } }
.ladder__num {
  display: inline-flex; align-items: center; justify-content: center;
  width: 42px; height: 42px; flex: none;
  border-radius: 50%; background: var(--brand-press); color: var(--on-brand);
  font-size: var(--fs-h4); font-weight: 700; line-height: 1;
}
.ladder__body { display: block; }
.ladder__title {
  display: block; margin-bottom: var(--sp-2);
  font-size: var(--fs-h4); font-weight: 700; color: var(--ink-strong);
}
.ladder__text { display: block; font-size: var(--fs-sm); color: var(--body); }

/* Кадр разъёма в статье: гнездо на машине и коннектор в руке одним снимком.
   Люди путают гнездо и штекер — в кадре видно и то, и другое. */
.port-shot { margin: var(--sp-5) 0 var(--sp-6); }
.port-shot img { display: block; width: 100%; height: auto; aspect-ratio: 3 / 2; object-fit: cover; border-radius: var(--radius-lg); }
.port-shot figcaption { margin-top: var(--sp-2); font-size: var(--fs-caption); color: var(--muted); text-align: center; }

/* Крупные карточки типов объектов: уменьшенный кадр первого экрана страницы
   и название поверх него. Ссылка — только если
   страница есть; иначе карточка без перехода. */
.object-cards { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp-5); margin: 0; padding: 0; list-style: none; }
.object-card { position: relative; display: block; overflow: hidden; border-radius: var(--radius-lg); background: var(--dark-3); color: #fff; }
.object-card img { display: block; width: 100%; height: auto; aspect-ratio: 12 / 7; object-fit: cover; transition: transform .3s ease-out; }
.object-card::after { content: ''; position: absolute; inset: 0; background: linear-gradient(180deg, rgba(10,13,14,0) 35%, rgba(10,13,14,.82) 100%); }
.object-card__title { position: absolute; left: var(--sp-5); right: var(--sp-5); bottom: var(--sp-4); z-index: 1; font-size: var(--fs-h4); font-weight: 700; line-height: 1.25; color: #fff; }
a.object-card:hover { text-decoration: none; }
a.object-card:hover img { transform: scale(1.04); }
a.object-card .object-card__title::after { content: ' →'; color: var(--brand); }
.object-cards__text { margin: var(--sp-2) 0 0; font-size: var(--fs-caption); line-height: 1.45; color: var(--muted); }
@media (max-width: 900px) { .object-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .object-cards { grid-template-columns: minmax(0, 1fr); } }
/* Ровно четыре плитки — сеткой 2×2, а не 3+1 с одинокой плиткой. */
@media (min-width: 561px) { .object-cards:has(> li:nth-child(4):last-child) { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* Карточка направления без кнопки: у .post нижний отступ даёт абзац с кнопкой,
   без неё текст прилипал к рамке. */
.post--plain { padding-bottom: var(--sp-6); }

/* Производственные переделы: квадратные снимки из каталога завода с подписью. */
.peredely {
  display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: var(--sp-4);
  margin: var(--sp-6) 0; padding: 0; list-style: none;
}
.peredely figure { margin: 0; }
.peredely img { display: block; width: 100%; height: auto; aspect-ratio: 268 / 250; object-fit: cover; border-radius: var(--radius); }
.peredely figcaption { margin-top: var(--sp-2); font-size: var(--fs-caption); line-height: 1.35; color: var(--body); text-align: center; hyphens: manual; }
@media (max-width: 900px) { .peredely { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 480px) { .peredely { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* Главные тезисы блока в рамке: цифра и одна фраза под ней.
   Человек читает заголовки и выделенное, а не абзацы — поэтому то, ради чего
   написан блок, выносится сюда, а подробности остаются текстом ниже. */
.theses {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  margin: 0 0 var(--sp-7); padding: var(--sp-6) 0;
  border: 1px solid var(--hairline-strong); border-radius: var(--radius-lg);
  background: var(--canvas);
}
.theses__item { padding: 0 var(--sp-5); border-left: 1px solid var(--hairline); }
.theses__item:first-child { border-left: 0; }
.theses__value {
  display: block; margin-bottom: var(--sp-3);
  font-size: clamp(1.75rem, 2.4vw, 2.5rem); font-weight: 700; line-height: 1;
  letter-spacing: var(--ls-display); color: var(--brand); white-space: nowrap;
}
.theses__value small { font-size: .55em; }
.theses__text { margin: 0; font-size: var(--fs-base); line-height: 1.45; color: var(--ink); }
@media (max-width: 760px) {
  .theses { grid-template-columns: minmax(0, 1fr); gap: var(--sp-5); padding: var(--sp-5) 0; }
  .theses__item { border-left: 0; }
  .theses__item + .theses__item { padding-top: var(--sp-5); border-top: 1px solid var(--hairline); }
}

/* Выноска: важная мысль, которую нельзя пропустить при беглом чтении.
   Кегль основной — мелким такое не набирают. */
.callout {
  margin: var(--sp-6) 0; padding: var(--sp-5) var(--sp-6);
  background: var(--dark-3); border-left: 3px solid var(--brand);
  font-size: var(--fs-base); line-height: 1.6;
}
.callout p { margin: 0; }
.callout p + p { margin-top: var(--sp-3); }
.callout__label { display: block; margin-bottom: var(--sp-2); color: var(--brand); letter-spacing: var(--ls-label); text-transform: uppercase; }
.section:not(.section--dark) .callout { background: var(--surface); }

.callout--check { padding: var(--sp-6); }
.callout__lead { margin-bottom: var(--sp-4); font-size: var(--fs-base); }
.checklist {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--sp-3) var(--sp-5);
  margin: 0 0 var(--sp-4); padding: 0; list-style: none;
}
.checklist li { display: flex; gap: var(--sp-3); align-items: flex-start; }
.icon--check { color: var(--brand); flex: none; margin-top: 2px; }

@media (max-width: 640px) { .checklist { grid-template-columns: 1fr; } }

@media (max-width: 900px) { .steps { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 640px) { .steps { grid-template-columns: 1fr; gap: var(--sp-6); } }

/* ===== Дорожная карта =====
   Построчный маршрут: слева крупный номер шага,
   справа название и подробности. Пунктир идёт сверху вниз и связывает шаги
   в один путь — сплошная линия читалась бы как граница таблицы. */
.roadmap { margin: 0; padding: 0; list-style: none; }
.roadmap__step {
  position: relative;
  display: grid; grid-template-columns: 72px 1fr; gap: var(--sp-5);
  padding-bottom: var(--sp-6);
}
.roadmap__step:last-child { padding-bottom: 0; }
/* Пунктир к следующему шагу — от кружка вниз. */
.roadmap__step:not(:last-child)::after {
  content: ''; position: absolute; left: 27px; top: 64px; bottom: var(--sp-2);
  border-left: 2px dashed var(--hairline-strong);
}
/* Номер шага — в кружке с зелёной линией и прозрачной серединой.
   */
.roadmap__num {
  display: inline-flex; align-items: center; justify-content: center;
  width: 56px; height: 56px; flex: none;
  border: 2px solid var(--brand); border-radius: 50%;
  background: transparent;
  font-size: 1.5rem; font-weight: 700; line-height: 1;
  color: var(--brand);
}
.roadmap__body { padding-top: var(--sp-2); }
.roadmap__icon { display: inline-block; color: var(--brand); vertical-align: -4px; margin-right: var(--sp-2); }
.roadmap__title { font-size: var(--fs-h4); margin-bottom: var(--sp-2); }
.roadmap__text { font-size: var(--fs-sm); color: var(--body); margin: 0; }

@media (max-width: 640px) {
  .roadmap__step { grid-template-columns: 48px 1fr; gap: var(--sp-4); }
  .roadmap__num { width: 48px; height: 48px; font-size: 1.25rem; }
  .roadmap__step:not(:last-child)::after { left: 23px; top: 56px; }
}

/* ===== 20. КАЛЬКУЛЯТОР ===== */
.calc { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-8); align-items: start; }
.calc__result { padding: var(--sp-6); background: var(--surface); }
.section--surface .calc__result { background: var(--canvas); }
/* Внутри калькулятора зелёного нет: фирменный цвет
   закреплён за кнопками, а на регуляторах и переключателях он спорил с ними.
   Зелёной остаётся только итоговая цифра окупаемости. */
.calc input[type="checkbox"] { accent-color: var(--muted); }
.calc__subsidy { margin-top: var(--sp-5); }
.calc__footnote { margin-top: var(--sp-5); }

.calc__figures { display: grid; gap: var(--sp-5); margin-bottom: var(--sp-6); }
.calc__pair { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-5); }
@media (max-width: 480px) { .calc__pair { grid-template-columns: 1fr; } }
.figure { padding-left: var(--sp-4); border-left: 2px solid var(--hairline-strong); container-type: inline-size; }
.figure--accent { border-left-color: var(--brand); }
.figure__label { display: block; font-size: var(--fs-caption); color: var(--muted); }
/* Кегль суммы считается от ширины самой колонки: в узкой паре «за станцию / за
   присоединение» знак рубля отрывался от числа и уезжал на вторую строку. */
.figure__value {
  display: block; margin: var(--sp-1) 0;
  font-size: clamp(1.5rem, 13cqi, var(--fs-stat)); font-weight: 700; line-height: 1;
  letter-spacing: var(--ls-display); color: var(--ink);
  white-space: nowrap; font-variant-numeric: tabular-nums;
}
.figure--accent .figure__value { color: var(--brand); }

.range { width: 100%; height: 32px; background: none; -webkit-appearance: none; appearance: none; }
.range::-webkit-slider-runnable-track { height: 2px; background: var(--hairline-strong); }
.range::-moz-range-track { height: 2px; background: var(--hairline-strong); }
.range::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 20px; height: 20px; margin-top: -9px;
  background: var(--muted); border: 0; border-radius: var(--radius);
  cursor: pointer;
}
.range::-moz-range-thumb {
  width: 20px; height: 20px; background: var(--muted);
  border: 0; border-radius: var(--radius); cursor: pointer;
}

.switch { display: flex; }
.switch__opt { position: relative; flex: 1; }
.switch__opt input { position: absolute; inset: 0; opacity: 0; margin: 0; cursor: pointer; }
.switch__opt span {
  display: flex; align-items: center; justify-content: center;
  min-height: 48px; padding-inline: var(--sp-4);
  font-size: var(--fs-sm); font-weight: 600; color: var(--ink-strong);
  background: var(--canvas); border: 1px solid var(--hairline-strong);
  transition: background-color .15s, color .15s, border-color .15s;
}
.switch__opt + .switch__opt span { border-left: 0; }
.switch__opt input:checked + span { background: var(--muted); border-color: var(--muted); color: #fff; }
.switch__opt input:focus-visible + span { outline: 2px solid var(--ink-strong); outline-offset: 2px; }

.chart { margin: 0 0 var(--sp-5); }
.chart__caption { margin-bottom: var(--sp-3); color: var(--muted); letter-spacing: var(--ls-label); text-transform: uppercase; }
.chart__box svg { width: 100%; height: auto; display: block; }

@media (max-width: 900px) { .calc { grid-template-columns: 1fr; gap: var(--sp-6); } }

/* ===== 21. КЕЙСЫ =====
   Лента карточек с нативной прокруткой: стрелки только помогают, без JS блок
   остаётся рабочим — палец и колесо листают его сами. */
.slider { position: relative; }

.slider__nav {
  display: flex; justify-content: flex-end; gap: var(--sp-2);
  margin-bottom: var(--sp-5);
}
.slider__btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px;
  color: #fff; background: var(--brand); border: 0; border-radius: var(--radius);
  cursor: pointer; transition: opacity .15s;
}
.slider__btn:hover { opacity: .85; }
.slider__btn[disabled] { opacity: .3; cursor: default; }

/* Ширина карточки задаётся жёстко: minmax(…, 1fr) в прокручиваемой ленте
   позволяет колонкам сжаться под контейнер, и вместо слайдера получается
   десять узких полосок в один экран. */
.slider__track {
  display: grid; grid-auto-flow: column;
  grid-auto-columns: calc((100% - var(--sp-6) * 3) / 4);
  gap: var(--sp-6);
  margin: 0; padding: 0 0 var(--sp-4); list-style: none;
  overflow-x: auto; scroll-snap-type: x mandatory; scroll-behavior: smooth;
  scrollbar-width: thin;
}
.slider__slide { scroll-snap-align: start; }

@media (max-width: 1099px) { .slider__track { grid-auto-columns: calc((100% - var(--sp-6) * 2) / 3); } }
@media (max-width: 860px)  { .slider__track { grid-auto-columns: calc((100% - var(--sp-6)) / 2); } }
/* На телефоне карточка занимает всю ширину: край соседнего слайда съедал
   заметную часть и без того узкого экрана. Что лента
   прокручивается, показывают стрелки над ней. */
@media (max-width: 620px)  { .slider__track { grid-auto-columns: 100%; } }

.case-card {
  display: flex; flex-direction: column; height: 100%;
  background: var(--canvas);
  border: 1px solid var(--hairline); border-radius: var(--radius-lg);
  overflow: hidden;
}
.case-card__img { width: 100%; aspect-ratio: 3 / 2; object-fit: cover; display: block; }
.case-card__body {
  display: flex; flex-direction: column; gap: var(--sp-3);
  flex: 1; padding: var(--sp-5);
}
.case-card__title { font-size: var(--fs-h4); margin: 0; }
.case-card__facts { margin: 0; padding: 0; list-style: none; font-size: var(--fs-sm); }
.case-card__facts li { padding-left: var(--sp-4); position: relative; color: var(--body); }
.case-card__facts li::before {
  content: ''; position: absolute; left: 0; top: .6em;
  width: 5px; height: 5px; border-radius: 50%; background: var(--brand);
}
.case-card__facts span { color: var(--muted); }
.case-card__text { font-size: var(--fs-sm); color: var(--body); margin: 0; }
.case-card__btn { margin-top: auto; align-self: flex-start; }

.cases__geo { margin-top: var(--sp-7); font-size: var(--fs-lead); color: var(--ink-strong); }

/* Страница документов: скан слева, пояснение справа — документ должен читаться
   и как картинка, и как строка списка. */
.docs-group { margin-top: var(--sp-8); }
.docs-group h2 { margin-bottom: var(--sp-3); }
.docs-list {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-5);
  margin: var(--sp-5) 0 0; padding: 0; list-style: none;
}
@media (max-width: 720px) { .docs-list { grid-template-columns: minmax(0, 1fr); } }
.docs-card {
  display: flex; gap: var(--sp-4);
  padding: var(--sp-4);
  background: var(--canvas);
  border: 1px solid var(--hairline); border-radius: var(--radius-lg);
}
.docs-card__media { flex: none; width: 120px; }
/* На телефоне миниатюра забирала 120px из 296 и тексту оставалось 160 —
   «производственному» не помещалось в строку целиком. */
@media (max-width: 480px) { .docs-card__media { width: 92px; } }
.docs-card__media img {
  width: 100%; height: auto; display: block;
  border: 1px solid var(--hairline); border-radius: var(--radius);
  transition: transform .2s;
}
.docs-card__media:hover img { transform: scale(1.03); }
/* min-width: 0 у текстовой части карточки: без него flex-элемент не становится
   уже своего самого длинного слова, и название вроде «ТехноЭкспо. Металлургия.
   Машиностроение» выносило карточку за край экрана. */
.docs-card__body { min-width: 0; }
.docs-card__title { font-size: var(--fs-h4); margin-bottom: var(--sp-2); }
.docs-card__text { font-size: var(--fs-sm); color: var(--body); margin: 0; }

/* Награды на городских страницах: три карточки в ряд равными долями, снимок
   крупный и сверху, под ним заголовок и пояснение. */
.docs-list--awards { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.docs-list--awards .docs-card { display: block; }
.docs-list--awards .docs-card__media { width: 100%; margin-bottom: var(--sp-4); }
.docs-list--awards .docs-card__media img { width: 100%; height: 340px; object-fit: cover; object-position: top center; }
@media (max-width: 900px) {
  .docs-list--awards { grid-template-columns: minmax(0, 1fr); }
  .docs-list--awards .docs-card__media img { height: auto; }
}

/* ===== Форма захвата в конце страницы =====
   Фотография под затемнением: фон должен поддержать блок, но не спорить с
   текстом и полями. Затемнение сплошное, а не градиент, —
   иначе на светлых кадрах поля теряются. */
.lead-band {
  position: relative; overflow: hidden;
  padding-block: var(--sp-8);
  background: var(--dark) var(--lead-band-image) center / cover no-repeat;
  color: var(--on-dark);
}
.lead-band::before {
  content: ''; position: absolute; inset: 0;
  background: rgba(17, 20, 21, .82);
}
/* Свой кадр для узких экранов: иначе телефон грузит и мобильное фото первого
   экрана, и десктопное фото этого блока. */
@media (max-width: 900px) {
  .lead-band[style*="--lead-band-image-mobile"] {
    background-image: var(--lead-band-image-mobile);
  }
}
.lead-band__inner {
  position: relative;
  display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-8);
  align-items: center;
}
/* Тонкая линия отделяет блок от подвала: два тёмных
   блока подряд сливались в один. Цвет непрозрачный: полупрозрачная белая
   линия смешивалась с фотографией под ней и получалась разноцветной. */
.lead-band { border-bottom: 1px solid #3A4246; }
@media (max-width: 900px) { .lead-band__inner { grid-template-columns: 1fr; gap: var(--sp-6); } }

.lead-band h2 { color: var(--on-dark); margin-bottom: var(--sp-4); }
.lead-band__sub { margin: 0; font-size: var(--fs-lead); line-height: 1.55; color: var(--on-dark-2); }
/* Полоса захвата всегда лежит на тёмном фото: здесь читается чистый --brand
   (4,99:1), а --brand-dim дал бы 2,95:1. */
.lead-band__sub b { color: var(--brand); font-weight: 700; }

.lead-band__form { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--sp-3); align-items: start; }
@media (max-width: 640px) { .lead-band__form { grid-template-columns: 1fr; } }
.lead-band__form--three { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 900px) { .lead-band__form--three { grid-template-columns: 1fr 1fr; } }
@media (max-width: 640px) { .lead-band__form--three { grid-template-columns: 1fr; } }

/* Второй вид блока: заголовок и тезисы по
   центру, форма во всю ширину под ними. Здесь блок не сопровождает страницу, а
   сам является предложением, поэтому две колонки ему тесны. */
.lead-band--center .lead-band__inner { grid-template-columns: 1fr; gap: var(--sp-7); max-width: 1200px; }
.lead-band--center .lead-band__text { text-align: center; }
/* Кегль, разрядка и интерлиньяж — значения заказчика. Заголовок
   ложится ровно в две строки по ручному переносу. */
.lead-band--center h2 {
  font-size: clamp(1.5rem, 2.5vw, 2.2rem);
  letter-spacing: 0.06rem; line-height: 1.4;
  margin-bottom: var(--sp-5);
}
.lead-band__points {
  display: inline-grid; gap: var(--sp-3);
  margin: 0; padding: 0; list-style: none; text-align: left;
}
.lead-band__points li {
  display: flex; align-items: flex-start; gap: var(--sp-3);
  font-size: var(--fs-lead); line-height: 1.4; color: var(--on-dark-2);
}
.lead-band__check { flex: none; color: var(--brand); margin-top: 2px; }
.lead-band__form .field { margin: 0; }
/* Поля прозрачные, с тонкой белой рамкой: заливка
   спорила с фотографией под блоком. */
.lead-band__form .input {
  width: 100%; min-height: 56px;
  background: transparent;
  border: 0.5px solid #fff; border-radius: 3px;
  color: var(--on-dark);
}
.lead-band__form .input::placeholder { color: var(--on-dark-3); }
.lead-band__form .btn { grid-column: 1; width: 100%; }
@media (max-width: 900px) { .lead-band__form--three .btn { grid-column: 1 / -1; } }
/* Согласие занимает всю ширину формы и остаётся читаемым на тёмном фоне. */
.lead-band__form .consent { grid-column: 1 / -1; color: var(--on-dark-3); }
/* Поле файла чертежа: в окне заявки и в полосе формы
   страницы услуги. Кнопка выбора файла — в цветах сайта, имя файла рядом. */
.input--file { padding: var(--sp-2) var(--sp-3); line-height: 1.4; cursor: pointer; }
.input--file::file-selector-button {
  margin-right: var(--sp-3); padding: 6px 14px;
  font: inherit; font-weight: 600; color: var(--ink);
  background: #E3E6E8; border: 0; border-radius: 3px; cursor: pointer;
}
/* Серая, а не фирменная: не спорит за внимание с кнопкой отправки. */
.input--file::file-selector-button:hover { background: #D2D6D9; }
.field--file .note { display: block; margin-top: 4px; }
.field--file .field__label .note { display: inline; margin: 0; font-weight: 400; }
.lead-band__form .field--file { grid-column: 1 / -1; }
.lead-band__form .input--file { min-height: 56px; padding-top: 12px; }
/* На тёмной полосе подпись поля файла видна, а кнопка выбора — контурная, приглушённая: главная здесь — кнопка отправки. */
.lead-band__form .field--file .field__label { display: block; margin-bottom: 6px; font-size: var(--fs-sm); color: var(--on-dark-2); }
.lead-band__form .field--file .field__label .note { color: var(--on-dark-3); }
.lead-band__form .input--file { color: var(--on-dark-3); }
.lead-band__form .input--file::file-selector-button { color: var(--on-dark-2); background: transparent; border: 1px solid rgba(255,255,255,.28); }
.lead-band__form .input--file::file-selector-button:hover { background: rgba(255,255,255,.08); border-color: rgba(255,255,255,.45); }
.lead-band__form .consent a { color: var(--on-dark-2); text-decoration: underline; }

/* Хлебные крошки: путь до страницы, текущая — без ссылки. */
.crumbs {
  margin-bottom: var(--sp-5);
  font-size: var(--fs-caption); color: var(--muted);
}
.crumbs a { color: var(--muted); }
.crumbs a:hover { color: var(--brand-dim); }
.crumbs__sep { margin: 0 var(--sp-2); color: var(--faint); }
.crumbs__current { color: var(--ink-strong); }

/* Страница кейса: карточка фактов, разделы и показатели объекта. */
.case-facts {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-5);
  margin: 0; padding: var(--sp-5) 0; border-block: 1px solid var(--hairline);
}
@media (max-width: 720px) { .case-facts { grid-template-columns: 1fr; gap: var(--sp-4); } }
.case-facts dt { font-size: var(--fs-caption); color: var(--muted); margin-bottom: var(--sp-1); }
.case-facts dd { margin: 0; font-weight: 600; color: var(--ink-strong); }

/* Отзывы водителей на странице объекта. Кегль основной: это то,
   ради чего блок и нужен, а не подпись под ним. Звёзды — текстом, не иконкой:
   их видно и в выдаче, и в нейроответе. */
.reviews {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: var(--sp-4); margin: var(--sp-5) 0 0; padding: 0; list-style: none;
}
.review {
  padding: var(--sp-5); border: 1px solid var(--hairline); border-radius: var(--radius);
  background: var(--surface);
}
.review__head { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); }
.review__author { color: var(--ink-strong); }
/* Тёмная охра, а не жёлтый: жёлтый #f5a623 на светлой карточке даёт 1,87:1 при
   норме 4,5 для текста. Звёзды — символы, а не иконка, и норма к ним та же. */
.review__rating { color: #8a5a00; letter-spacing: 0.08em; white-space: nowrap; }
.review__text { margin: var(--sp-3) 0 0; font-size: var(--fs-base); line-height: var(--lh-snug); }
.review__meta { margin: var(--sp-3) 0 0; font-size: var(--fs-sm); color: var(--muted); }

.case-section { margin-top: var(--sp-7); }
.case-section h2 { margin-bottom: var(--sp-4); }
.case-section p + p { margin-top: var(--sp-4); }
/* Цифры и ключевые факты в тексте страницы — фирменным зелёным: взгляд цепляется за факт, а не за сплошной
   абзац. Выделение приходит из JSON тегом <b>. */
/* Не --brand: чистый #FC5800 на белом даёт 3,91:1, а выделенные факты набраны
   кеглем основного текста. --brand-dim — 6,62:1 при том же фирменном тоне. */
.case-section b, .prose b, .event__text b, .roadmap__text b { color: var(--brand-dim); font-weight: 700; }

.case-figures__title { margin: var(--sp-8) 0 var(--sp-5); }
.case-figures {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--sp-5);
  margin: 0 0 var(--sp-4); padding: 0; list-style: none;
}
@media (max-width: 900px) { .case-figures { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 480px) { .case-figures { grid-template-columns: 1fr; } }
.case-figures li { display: flex; flex-direction: column; gap: var(--sp-1); }
.case-figures b { font-size: var(--fs-h3); font-weight: 700; color: var(--brand); }
.case-figures span { font-size: var(--fs-caption); color: var(--muted); }

/* Событие на странице выставок: заголовок, дата и место, текст, галерея. */
.event { padding-top: var(--sp-7); border-top: 1px solid var(--hairline); }
.event + .event { margin-top: var(--sp-7); }
.event__head { margin-bottom: var(--sp-4); }
.event__title { margin-bottom: var(--sp-2); }
.event__meta { color: var(--brand-dim); letter-spacing: var(--ls-label); text-transform: uppercase; font-size: var(--fs-label); }
.event__text p + p { margin-top: var(--sp-4); }

/* Галерея страниц (выставки, кейсы): та же механика просмотрщика, что была
   у блока кейсов на главной, но плитка крупнее — на странице есть место. */
.gallery {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-4);
  margin: var(--sp-6) 0 var(--sp-7); padding: 0; list-style: none;
}
/* Четыре снимка: по два в ряд. В сетке из трёх колонок четвёртый повисал в
   пустой строке, а в узкой колонке страницы кадры по 230px не читаются. */
.gallery--pair { grid-template-columns: repeat(2, 1fr); }
/* На странице решения снимки объекта идут одним рядом: четыре кадра — четыре
   колонки, миниатюры мельче, но вторая строка ради одного снимка не заводится.
   Ниже 900px работает общее правило «по два в ряд». */
.gallery--four { grid-template-columns: repeat(4, 1fr); }
.gallery--three { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 900px) { .gallery { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .gallery { grid-template-columns: 1fr; } }
.gallery a { display: block; position: relative; overflow: hidden; border-radius: var(--radius-lg); }
.gallery img {
  width: 100%; aspect-ratio: 4 / 3; object-fit: cover; display: block;
  transition: transform .3s ease-out, opacity .2s;
}
.gallery a:hover img { transform: scale(1.05); opacity: .9; }

/* Та же галерея лентой: снимки идут одним рядом и
   листаются, как кейсы на главной. Кадры берут вид от .gallery, раскладку —
   от слайдера. */
.slider--gallery { margin-top: var(--sp-6); }
.gallery__link { display: block; position: relative; overflow: hidden; border-radius: var(--radius-lg); }
.gallery__link img {
  width: 100%; aspect-ratio: 4 / 3; object-fit: cover; display: block;
  transition: transform .3s ease-out, opacity .2s;
}
.gallery__link:hover img { transform: scale(1.05); opacity: .9; }

.case__gallery {
  grid-column: 1 / -1;
  display: grid; grid-template-columns: repeat(6, 1fr); gap: var(--sp-3);
  margin: var(--sp-5) 0 0; padding: 0; list-style: none;
}
.case__gallery a { display: block; position: relative; overflow: hidden; }
.case__gallery img {
  width: 100%; aspect-ratio: 4 / 3; object-fit: cover; display: block;
  transition: transform .3s ease-out, opacity .2s;
}
.case__gallery a:hover img { transform: scale(1.06); opacity: .85; }
.case__gallery a::after {
  content: ''; position: absolute; right: 8px; bottom: 8px;
  width: 22px; height: 22px; border-radius: 2px;
  background: rgba(10,13,14,.6) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' fill='none' stroke='%23fff' stroke-width='2' viewBox='0 0 24 24'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='M21 21l-4.3-4.3M11 8v6M8 11h6'/%3E%3C/svg%3E") center / 14px no-repeat;
  opacity: 0; transition: opacity .2s;
}
.case__gallery a:hover::after { opacity: 1; }

@media (max-width: 900px) { .case__gallery { grid-template-columns: repeat(3, 1fr); } }

/* ===== Просмотрщик фотографий ===== */
.zoom {
  position: fixed; inset: 0; z-index: 90;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--sp-4); padding: var(--sp-6) var(--sp-5);
  background: rgba(10,13,14,.975);
}
.zoom__close {
  position: absolute; top: var(--sp-4); right: var(--sp-4);
  width: 48px; height: 48px;
  display: flex; align-items: center; justify-content: center;
  border: 0; background: none; color: var(--on-dark-2); cursor: pointer;
}
.zoom__close:hover { color: var(--on-dark); }
.zoom__stage {
  display: flex; align-items: center; gap: var(--sp-4);
  width: 100%; min-height: 0; flex: 1;
}
/* min-width: 0 обязателен: без него флекс-элемент не сжимается уже своего
   содержимого, и на телефоне снимок уезжал за правый край вместе со стрелками.
   */
.zoom__img {
  flex: 1 1 auto; min-width: 0;
  max-width: 100%; max-height: 100%;
  margin-inline: auto; object-fit: contain;
}
.zoom__nav {
  flex: none; width: 48px; height: 48px;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--hairline-dark); border-radius: 50%;
  background: none; color: var(--on-dark-2); cursor: pointer;
}
.zoom__nav:hover { color: var(--on-dark); border-color: var(--on-dark-3); }
.zoom__caption { margin: 0; max-width: 70ch; text-align: center; font-size: var(--fs-sm); color: var(--on-dark-2); }
.zoom__thumbs { display: flex; gap: var(--sp-2); flex-wrap: wrap; justify-content: center; }
.zoom__thumbs button {
  width: 76px; height: 57px; padding: 0; cursor: pointer;
  border: 1px solid transparent; background: none; opacity: .5;
  transition: opacity .2s, border-color .2s;
}
.zoom__thumbs button:hover { opacity: .85; }
.zoom__thumbs button.is-active { opacity: 1; border-color: var(--brand); }
.zoom__thumbs img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* На телефоне стрелки ложатся поверх кадра, а не отбирают у него ширину:
   иначе на 390px от снимка остаётся полоска. */
@media (max-width: 640px) {
  .zoom { padding: var(--sp-7) var(--sp-3) var(--sp-4); gap: var(--sp-3); }
  .zoom__stage { position: relative; }
  .zoom__nav {
    position: absolute; top: 50%; transform: translateY(-50%); z-index: 2;
    width: 40px; height: 40px;
    background: rgba(10,13,14,.55); color: var(--on-dark);
  }
  .zoom__nav--prev { left: 0; }
  .zoom__nav--next { right: 0; }
  .zoom__close { top: var(--sp-2); right: var(--sp-2); width: 40px; height: 40px; }
  .zoom__caption { font-size: var(--fs-caption); }
  .zoom__thumbs button { width: 56px; height: 42px; }
}

.case:not(.case--main) { padding-top: var(--sp-5); border-top: 1px solid var(--hairline-dark); }

@media (max-width: 900px) {
  .cases { grid-template-columns: 1fr; }
  .case--main { grid-template-columns: 1fr; gap: var(--sp-5); }
  .case__figures { grid-template-columns: repeat(2, 1fr); }
  .case__gallery { grid-template-columns: 1fr 1fr; gap: var(--sp-3); }
  .case__gallery li:last-child { grid-column: 1 / -1; }
}

.awards {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-6);
  margin: var(--sp-8) 0 0; padding: 0; list-style: none;
}
.awards__item {
  padding-left: var(--sp-4); border-left: 2px solid var(--brand);
  font-size: var(--fs-sm); color: var(--body);
}
@media (max-width: 900px) { .awards { grid-template-columns: 1fr; gap: var(--sp-4); } }

/* ===== 22. ПЛИТКИ ССЫЛОК, ДОКУМЕНТЫ, СТАТЬИ ===== */
/* Страница «не найдено»: крупный номер ошибки и одна кнопка. Плитки разделов с
   неё убраны — их текст попадал в замер сквозных слов. */
.error404 { text-align: center; }
.error404__code {
  margin: 0; font-size: clamp(96px, 22vw, 200px); line-height: 1;
  font-weight: 700; letter-spacing: -.04em; color: var(--ink-strong); opacity: .12;
}
.error404__note { margin: 0 0 var(--sp-6); font-size: var(--fs-h4); color: var(--muted); }

.docs { display: grid; gap: 1px; margin: 0; padding: 0; list-style: none; background: var(--hairline); border: 1px solid var(--hairline); }
.docs__item { background: var(--surface); }
.section--surface .docs__item { background: var(--canvas); }
.docs__item a { display: flex; align-items: center; gap: var(--sp-4); padding: var(--sp-4) var(--sp-5); color: var(--ink-strong); }
.docs__item a:hover { text-decoration: none; color: var(--brand-dim); }
.docs__title { font-size: var(--fs-sm); font-weight: 600; }
.docs__format { margin-left: auto; padding: var(--sp-1) var(--sp-2); color: var(--faint); border: 1px solid var(--hairline); }
.docs__note { margin-top: var(--sp-4); }

/* Карточка статьи: кадр, заголовок, короткий анонс и кнопка внизу карточки —
   ряд выравнивается по кнопкам независимо от длины анонса. */
.post {
  display: flex; flex-direction: column;
  border: 1px solid var(--hairline); border-radius: var(--radius-lg);
  overflow: hidden; background: var(--canvas);
}
/* ===== География =====
   Блок: три карточки условий и карта
   с флажками городов. Флажки перекрашены в фирменный зелёный, тайлы карты
   обесцвечены — цветным на ней остаётся только наше. */
.geo__cards { margin-bottom: var(--sp-6); }
.geo__card {
  padding: var(--sp-5);
  background: var(--canvas);
  border: 1px solid var(--hairline); border-radius: var(--radius-lg);
}
.geo__icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; margin-bottom: var(--sp-3);
  border-radius: var(--radius-md);
  background: rgba(252,88,0,.1); color: var(--brand);
}
.geo__card-title { font-size: var(--fs-h4); margin-bottom: var(--sp-2); }
.geo__card-text { font-size: var(--fs-sm); color: var(--body); margin: 0; }

.geo__map-wrap {
  position: relative; height: 430px;
  border: 1px solid var(--hairline); border-radius: var(--radius-lg);
  overflow: hidden; background: var(--surface);
}
.geo__map { width: 100%; height: 100%; }
.geo__map [class*="ground-pane"] { filter: grayscale(1); }   /* серо-белые тайлы */

/* Список городов идёт под картой: плашка поверх неё закрывала точки. */
.geo__cities { margin-top: var(--sp-5); }
.geo__cities-title { margin: 0 0 var(--sp-3); font-size: var(--fs-caption); color: var(--muted); }
.geo__cities .tags { margin: 0; gap: var(--sp-2); }
.geo__links { margin-top: var(--sp-5); display: flex; flex-wrap: wrap; gap: var(--sp-3) var(--sp-6); }
.geo__links .geo__cities-more { margin: 0; }
.tag--static { min-height: 34px; padding: 0 var(--sp-4); color: var(--ink-strong); }

/* ===== Поиск по сайту =====
   Страница результатов и строка запроса над ней. Оформление намеренно
   спокойное: это служебная страница, а не посадочная. */
.search-page__form {
  display: flex; gap: var(--sp-3); align-items: flex-start;
  margin: var(--sp-6) auto var(--sp-5); max-width: 40rem;
}
.search-page__box { position: relative; flex: 1 1 auto; min-width: 0; }
.search-page__form .field { flex: 1 1 auto; margin-bottom: 0; }
.search-page__form .input { width: 100%; }
.search-page__form .btn { flex: none; }

.search-results { margin: var(--sp-5) 0 0; padding: 0; list-style: none; }
.search-results__item { padding: var(--sp-4) 0; border-bottom: 1px solid var(--hairline); }
.search-results__link {
  display: flex; align-items: baseline; gap: var(--sp-3);
  color: var(--ink-strong); text-decoration: none;
}
.search-results__link:hover .search-results__title { color: var(--brand-dim); }
.search-results__title {
  font-size: var(--fs-h4);
  text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px;
}
/* Тип страницы справа от названия: «Раздел», «Статья», «Товар» — по нему видно,
   куда ведёт ссылка, до перехода. */
.search-results__kind {
  flex: none; margin-left: auto;
  font-size: var(--fs-caption); color: var(--muted); white-space: nowrap;
}
.search-results__snippet { margin: var(--sp-2) 0 0; font-size: var(--fs-sm); color: var(--body); }

.search-results__snippet mark,
.search-bar__list mark { background: none; color: var(--brand-dim); font-weight: 700; }

/* Страница, открытая из результатов поиска (?search=…): найденные слова на жёлтом фоне. */
mark.find-mark { background: var(--find-mark); color: inherit; border-radius: 2px; box-shadow: 0 0 0 2px var(--find-mark); }

/* Лупа в служебной строке шапки: там она есть на любой ширине, а главная строка
   на телефоне уже занята знаком, номером и кнопкой меню. */
.search-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; margin: -6px 0 -6px var(--sp-2);
  color: var(--on-dark-2);
}
.header__top a.search-toggle:hover { color: var(--brand); }

/* Строка поиска встаёт между служебной строкой и главной:
   светлая полоса во всю ширину, лупа-кнопка справа внутри поля. Подсказки
   выпадают поверх страницы, чтобы шапка не прыгала по высоте при вводе. */
.search-bar { position: relative; z-index: 45; background: var(--canvas); color: var(--ink-strong); }
.search-bar .wrap { padding-block: var(--sp-2); }
.search-bar__form { position: relative; display: flex; align-items: center; }
.search-bar__input {
  flex: 1 1 auto; min-width: 0; height: 44px; padding: 0 52px 0 var(--sp-3);
  font: inherit; font-size: 1rem; color: var(--ink-strong);
  background: transparent; border: 0; outline: 0;
}
.search-bar__input::placeholder { color: var(--muted); }
/* Крестик очистки у type=search в Chrome спорил с лупой справа. */
.search-bar__input::-webkit-search-cancel-button { display: none; }
.search-bar__submit {
  position: absolute; right: 0; top: 50%; transform: translateY(-50%);
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; padding: 0;
  color: var(--brand-dim); background: none; border: 0; cursor: pointer;
}
.search-bar__submit:hover { color: var(--brand); }

.search-bar__list {
  position: absolute; left: 0; right: 0; top: 100%;
  margin: 0; padding: var(--sp-2) max(var(--sp-4), calc((100% - var(--wrap)) / 2));
  list-style: none; display: grid; gap: 2px;
  background: var(--canvas); border-top: 1px solid var(--hairline);
  box-shadow: 0 12px 24px rgba(10,13,14,.18);
  max-height: min(70vh, 40rem); overflow-y: auto; overscroll-behavior: contain;
}
/* Подсказки под полем на странице результатов: ширина поля, без отступов шапки. */
.search-bar__list--page { top: calc(100% + 4px); padding: var(--sp-2); z-index: 30; border: 1px solid var(--hairline); border-radius: var(--radius); }
.search-bar__list a {
  display: flex; align-items: baseline; gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-3); border-radius: var(--radius);
  color: var(--ink-strong); font-size: var(--fs-sm);
}
.search-bar__list a:hover,
.search-bar__list a.is-active { color: var(--brand-dim); background: var(--surface-2); text-decoration: none; }
.search-bar__kind { margin-left: auto; flex: none; font-size: var(--fs-caption); color: var(--muted); }
/* «Все результаты» прилипает к низу окна подсказок, когда список длиннее экрана;
   над ссылкой — осветление, под ним прокручиваются подсказки. */
.search-bar__all { position: sticky; bottom: calc(-1 * var(--sp-2)); z-index: 1; background: var(--canvas); }
.search-bar__list.is-scrollable .search-bar__all { padding-bottom: var(--sp-2); }
.search-bar__list.is-scrollable .search-bar__all::before {
  content: ""; position: absolute; left: 0; right: 0; bottom: 100%; height: 2.5rem;
  background: linear-gradient(to bottom, rgba(255,255,255,0), var(--canvas)); pointer-events: none;
}
.search-bar__all a { color: var(--brand-dim); font-weight: 600; }
.search-bar__empty { padding: var(--sp-2) var(--sp-3); font-size: var(--fs-sm); color: var(--body); }

@media (max-width: 560px) {
  .search-bar__list a { flex-wrap: wrap; gap: 0 var(--sp-3); }
  .search-bar__kind { margin-left: 0; }
  .search-page__form { flex-direction: column; align-items: stretch; }
  .search-page__form .btn { width: 100%; }
  .search-results__link { flex-wrap: wrap; }
  .search-results__kind { margin-left: 0; }
}

/* Теги-ссылки по разделам о заводе: навигация по теме прямо под
   заголовком. Стоят в начале страницы, поэтому набраны спокойно — акцент
   остаётся на самом тексте. */
.tags--links { margin: var(--sp-5) 0 0; gap: var(--sp-2); }
.tags--links .tag {
  padding: 0 var(--sp-4); color: var(--ink-strong); background: var(--surface-2);
  border: 1px solid var(--hairline); text-decoration: none;
  transition: border-color .15s, color .15s;
}
.tags--links .tag:hover { color: var(--brand-dim); border-color: var(--brand); text-decoration: none; }
/* Текущая страница — «нажатый» тег: тёмная заливка, без ссылки и без реакции на наведение. */
.tags--links .tag--current,
.tags--links .tag--current:hover {
  color: var(--on-dark); background: var(--ink-strong); border-color: var(--ink-strong);
  box-shadow: inset 0 2px 3px rgba(0,0,0,.35); cursor: default;
}

/* Нет ключа карт или узкий экран — от блока остаётся список городов. */
.geo__map-wrap.is-fallback { display: none; }
@media (max-width: 768px) { .geo__map-wrap { display: none; } }

/* Флажок города на карте: база флагштока — точка на карте. */
.geo-pin {
  display: flex; align-items: center; gap: 6px;
  transform: translate(-6px, -40px);
  white-space: nowrap; cursor: pointer;
}
.geo-pin__flag {
  flex: none; color: var(--brand);
  filter: drop-shadow(0 0 1.5px #fff) drop-shadow(0 2px 3px rgba(0,0,0,.35));
}
.geo-pin--hub .geo-pin__flag { color: var(--brand-press); }
/* Объект со своей страницей: круглое фото вместо флажка, клик открывает карточку. */
.geo-pin--photo { transform: translate(-26px, -58px); align-items: flex-end; }
.geo-pin__photo {
  flex: none; width: 48px; height: 48px; border-radius: 50%; object-fit: cover;
  border: 3px solid var(--brand); background: #fff;
  box-shadow: 0 2px 6px rgba(10,13,14,.35);
  transition: transform .15s ease;
}
.geo-pin--photo.geo-pin--hub .geo-pin__photo { border-color: var(--brand-press); }
.geo-pin--photo:hover .geo-pin__photo { transform: scale(1.12); }
.geo-pin--photo .geo-pin__label { margin-bottom: 4px; }
.geo-pin__photo, .geo-cluster__photo { max-width: none; }
.geo-cluster.geo-cluster--photo {
  position: relative; width: 56px; height: 56px; padding: 0; background: #fff;
  border: 3px solid var(--brand); overflow: visible;
}
.geo-cluster__photo { width: 50px; height: 50px; border-radius: 50%; object-fit: cover; display: block; }
.geo-cluster__count {
  position: absolute; top: -6px; right: -8px;
  min-width: 22px; height: 22px; padding: 0 5px; border-radius: 11px;
  background: var(--brand-press); color: #fff; border: 2px solid #fff;
  font-size: 12px; font-weight: 700; line-height: 18px; text-align: center;
}
.geo-pin__label {
  font-size: 12.5px; font-weight: 700; color: var(--ink);
  background: rgba(255,255,255,.92);
  padding: 2px 7px; border-radius: 5px;
  box-shadow: 0 1px 4px rgba(10,13,14,.22);
}
.geo-cluster {
  display: flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; border-radius: 50%;
  background: var(--brand-press); color: #fff; border: 2px solid #fff;
  box-shadow: 0 2px 6px rgba(10,13,14,.3);
  font-weight: 700; font-size: 13px;
  transform: translate(-50%, -50%);
}

.section--blog { padding-top: calc(var(--sp-8) + 20px); }   /* воздух над блоком статей */

.post__media { display: block; }
.post__media img {
  width: 100%; aspect-ratio: 16 / 9; object-fit: cover; display: block;
  transition: transform .3s ease-out;
}
.post:hover .post__media img { transform: scale(1.04); }

.post__title { font-size: var(--fs-h4); margin: var(--sp-5) var(--sp-5) var(--sp-3); }
.post__title a { color: var(--ink); }
.post__title a:hover { color: var(--brand-dim); text-decoration: none; }
.post__text { flex: 1; margin: 0 var(--sp-5); font-size: var(--fs-sm); color: var(--body); }
/* Селектор с двумя классами намеренно: кнопка лежит в последнем абзаце
   карточки, а базовое `p:last-child { margin-bottom: 0 }` специфичнее одного
   класса — из-за него кнопка прижималась к нижней границе карточки.
   */
.post .post__action { margin: var(--sp-5) var(--sp-5) var(--sp-6); }
/* Карточка без кнопки: последний абзац прилипал к нижней границе. Два класса — по той же причине, что выше. */
.post .post__text:last-child { margin-bottom: var(--sp-5); }
.post__date { margin-top: var(--sp-3); color: var(--faint); }

@media (max-width: 640px) {
  .links { grid-template-columns: 1fr; }
  .links__item:nth-child(odd) { border-right: 0; }
  .links__item:nth-child(even) a { padding-left: 0; }
}

/* ===== 23. АККОРДЕОН ===== */
/* Вопросы стоят карточками на своей подложке: на сером фоне секции белая
   плашка отделяет вопрос от вопроса лучше, чем линия. */
/* minmax(0, 1fr) обязателен: у грид-элемента min-width по умолчанию auto, и
   карточка вопроса не сжимается уже таблицы внутри ответа — на телефоне из-за
   этого прокручивалась вся страница. */
.accordion { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--sp-3); }
.accordion__item {
  min-width: 0;
  background: var(--canvas);
  border: 1px solid var(--hairline); border-radius: var(--radius-lg);
  padding: 0 var(--sp-6);
}
.accordion__item.is-open { border-color: var(--brand); }
.accordion__head {
  position: relative;
  margin: 0; padding: var(--sp-5) var(--sp-8) var(--sp-5) 0;
  font-size: var(--fs-h4); font-weight: 600; color: var(--ink);
  cursor: pointer; list-style: none;
}
.accordion__head::after {
  content: ''; position: absolute; top: 50%; right: var(--sp-3);
  width: 10px; height: 10px; margin-top: -8px;
  border-right: 2px solid var(--brand); border-bottom: 2px solid var(--brand);
  transform: rotate(45deg); transition: transform .15s;
}
.accordion__item.is-open .accordion__head::after { transform: rotate(-135deg); margin-top: -3px; }
.accordion__body {
  overflow: hidden; max-height: 0;
  transition: max-height .2s ease-out;
}
.accordion__item.is-open .accordion__body { max-height: 140em; }

/* Ответ занимает всю ширину блока: ограничение по знакам здесь снято намеренно
   — вместо узкой колонки текст структурируется
   абзацами, списками и таблицами. */
.answer { padding-bottom: var(--sp-5); font-size: var(--fs-sm); }
.answer > * + * { margin-top: var(--sp-5); }
.answer p { margin: 0; }
.answer__list { margin: 0; padding-left: var(--sp-5); display: grid; gap: var(--sp-2); }
.answer__table { margin: 0; }
.answer__table th, .answer__table td { padding: var(--sp-3) var(--sp-4); }

/* ===== 24. ДВЕ КОЛОНКИ И КОНТАКТЫ ===== */
.split { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-8); align-items: start; }
.split--form { grid-template-columns: 1.4fr 1fr; gap: var(--sp-10); }
.split__aside .prose p { color: inherit; }

.split__media { position: relative; margin: 0 0 var(--sp-6); }
.split__media img { width: 100%; max-height: 420px; object-fit: cover; object-position: center 60%; }

.contacts { padding-left: var(--sp-6); border-left: 1px solid var(--hairline-dark); }
.contacts__title { color: var(--brand); letter-spacing: var(--ls-label); text-transform: uppercase; margin-bottom: var(--sp-4); font-size: var(--fs-label); }
.contacts__phones a { font-size: var(--fs-h4); font-weight: 700; color: var(--on-dark); font-variant-numeric: tabular-nums; }
.contacts a { color: var(--on-dark-2); }
.contacts__address { color: var(--on-dark-2); }
.contacts .tech { color: var(--on-dark-3); }

.form__submit { margin-top: var(--sp-5); }
.form__submit .note { margin-top: var(--sp-3); }
.section--dark .field__label { color: var(--on-dark); }
.section--dark .consent { color: var(--on-dark-3); }
.section--dark .consent a { color: var(--on-dark-2); text-decoration: underline; }

.form__done {
  padding: var(--sp-6); border-left: 2px solid var(--brand);
  background: rgba(255,255,255,.04);
}
.section:not(.section--dark) .form__done, .modal .form__done { background: var(--surface); }

.errors { margin: 0 0 var(--sp-5); padding-left: var(--sp-5); color: var(--danger); }

@media (max-width: 900px) {
  .split, .split--form { grid-template-columns: 1fr; gap: var(--sp-7); }
  .contacts { padding-left: 0; border-left: 0; padding-top: var(--sp-6); border-top: 1px solid var(--hairline-dark); }
}

/* ===== 25. МОДАЛЬНОЕ ОКНО ===== */
.modal {
  position: fixed; inset: 0; z-index: 80;
  display: flex; align-items: center; justify-content: center;
  padding: var(--gutter);
  background: rgba(10,13,14,.72);
  overflow-y: auto;
}
.modal__window {
  position: relative;
  width: 100%; max-width: 520px;
  padding: var(--sp-7);
  background: var(--canvas);
  border-radius: var(--radius);
  box-shadow: var(--shadow-menu);
}
.modal__close {
  position: absolute; top: var(--sp-3); right: var(--sp-3);
  width: 44px; height: 44px;
  display: flex; align-items: center; justify-content: center;
  border: 0; background: none; color: var(--muted); cursor: pointer;
}
.modal__close:hover { color: var(--ink); }
.modal__title { font-size: var(--fs-h3); margin-bottom: var(--sp-2); padding-right: var(--sp-7); }

.modal.is-short .field--optional { display: none; }

.field__req { color: var(--danger); }
.modal__req { margin-top: var(--sp-3); text-align: center; }

.thanks { text-align: center; }
.thanks__icon { display: inline-flex; margin-bottom: var(--sp-5); color: var(--brand); }
.thanks h1 { margin-bottom: var(--sp-4); }
.thanks .lead { margin-inline: auto; max-width: 52ch; }
.thanks__contacts { margin-top: var(--sp-6); }
.thanks__actions { display: flex; gap: var(--sp-4); justify-content: center; flex-wrap: wrap; margin-top: var(--sp-7); }

/* Проверка контактов: человек должен увидеть, что он
   написал, и заметить опечатку в телефоне. Рамка, а не карточка с тенью —
   блок служебный и не должен спорить с заголовком. */
.thanks__check {
  margin-top: var(--sp-7); padding: var(--sp-6);
  text-align: left;
  border: 1px solid var(--hairline-strong); border-radius: var(--radius-lg);
}
.thanks__check-title { font-size: var(--fs-h4); margin-bottom: var(--sp-4); }
.thanks__contacts-list {
  display: grid; grid-template-columns: auto 1fr; gap: var(--sp-2) var(--sp-5);
  margin: 0 0 var(--sp-4);
}
.thanks__contacts-list dt { color: var(--muted); font-size: var(--fs-sm); }
.thanks__contacts-list dd { margin: 0; font-weight: 600; color: var(--ink-strong); }

.thanks__own { margin-top: var(--sp-6); }
.thanks__phones {
  display: flex; gap: var(--sp-5); justify-content: center; flex-wrap: wrap;
  margin-bottom: var(--sp-2);
  font-size: var(--fs-lead); font-weight: 600;
}
.modal__submit { width: 100%; margin-top: var(--sp-5); }

/* ===== Окно выбора города ===== */
/* Светлая тема окна выбора города: тёмное
   окно поверх тёмного первого экрана сливалось с фоном. Оформление то же, что
   у окна заказа звонка. */
.city-modal { max-width: 900px; width: 100%; background: var(--canvas); color: var(--body); }
.city-modal .modal__title { color: var(--ink-strong); margin-bottom: var(--sp-5); }

.city-modal__search { position: relative; display: block; margin-bottom: var(--sp-3); }
.city-modal__search .input { width: 100%; padding-right: 44px; }
.city-modal__search-icon {
  position: absolute; right: 14px; top: 50%; transform: translateY(-50%);
  color: var(--muted); pointer-events: none;
}

.city-modal__hint { display: flex; gap: var(--sp-3); align-items: baseline; font-size: var(--fs-sm); color: var(--muted); }
.city-modal__example {
  background: none; border: 0; padding: 0; cursor: pointer;
  font: inherit; color: var(--ink-strong); text-decoration: underline;
  text-underline-offset: 3px;
}
.city-modal__example:hover { color: var(--brand-dim); }

.city-modal__list {
  margin-top: var(--sp-5); max-height: 46vh;
  overflow-y: auto; overflow-x: hidden;
  display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--sp-5) var(--sp-6);
  align-content: start;
  border-top: 1px solid var(--hairline); padding-top: var(--sp-4);
  scrollbar-width: thin;
  scrollbar-color: var(--hairline-strong) transparent;
}
.city-modal__list::-webkit-scrollbar { width: 10px; height: 10px; }
.city-modal__list::-webkit-scrollbar-track { background: var(--surface); }
.city-modal__list::-webkit-scrollbar-thumb {
  background: var(--hairline-strong); border-radius: 999px;
  border: 3px solid var(--surface);
}
.city-modal__list::-webkit-scrollbar-thumb:hover { background: var(--faint); }
.city-group { break-inside: avoid; }
.city-group__letter {
  display: block; margin-bottom: var(--sp-2);
  font-family: var(--font); font-size: var(--fs-label);
  letter-spacing: var(--ls-label); color: var(--brand-dim);
}
.city-group__items { list-style: none; margin: 0; padding: 0; }
.city-item {
  display: block; width: 100%; padding: 3px 0;
  background: none; border: 0; cursor: pointer; text-align: left;
  font: inherit; font-size: var(--fs-sm); color: var(--body);
}
.city-item:hover { color: var(--brand-dim); }
.city-item.is-active { color: var(--ink-strong); font-weight: 600; }
.city-modal__empty { margin-top: var(--sp-5); color: var(--muted); }
.city-modal__note {
  margin: var(--sp-5) 0 0; padding-top: var(--sp-4);
  border-top: 1px solid var(--hairline);
  font-size: var(--fs-sm); color: var(--muted);
}
.city-modal__note a { color: var(--ink-strong); font-weight: 600; }
.city-modal__note a:hover { color: var(--brand-dim); }

@media (max-width: 900px) { .city-modal__list { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) {
  .city-modal__list { grid-template-columns: 1fr; max-height: 50vh; }
  .city__addr { display: none; }
}

.modal .form { margin-top: var(--sp-5); }
.modal__submit { width: 100%; margin-top: var(--sp-5); }

@media (max-width: 640px) {
  .modal { align-items: flex-start; padding: 0; }
  .modal__window { max-width: none; min-height: 100%; padding: var(--sp-6) var(--sp-4); border-radius: 0; }
}

/* ===== 25.0. КНОПКА ВО ВРЕМЯ ОТПРАВКИ ===== */
/* Кружок перед надписью: между нажатием и ответом сервера проходит около двух
   секунд, и без индикатора человек жмёт «Отправить» второй раз. Спиннер —
   отдельный элемент, его вставляет main.js: оба псевдоэлемента кнопки уже
   заняты волной и подсветкой наведения. */
.btn.is-loading { cursor: progress; }
.btn.is-loading::after { animation: none; }        /* волна не спорит со спиннером */

.btn__spinner {
  flex: 0 0 auto;
  width: 16px; height: 16px;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: var(--radius-full);
  animation: btn-spin .7s linear infinite;
}
@keyframes btn-spin { to { transform: rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
  .btn__spinner { animation-duration: 1.8s; }
}

/* ===== 25.1. РЕЖИМ РАБОТЫ ===== */
/* Точка «сейчас работаем»: зелёная в рабочее время, серая вне его. Состояние
   считает сервер (work_status), скрипт к этому отношения не имеет. */
.work-dot {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  color: var(--muted); font-size: var(--fs-caption); white-space: nowrap;
}
.work-dot::before {
  content: ''; flex: 0 0 auto;
  width: 8px; height: 8px; border-radius: var(--radius-full);
  background: var(--muted);
}
.work-dot--open { color: var(--brand); }
.work-dot--open::before { background: var(--brand); }

.header__hours .work-dot { display: block; margin-top: 2px; }
.header__hours .work-dot { color: var(--on-dark-3); }
.header__hours .work-dot--open { color: var(--brand); }

.thanks__work { display: flex; align-items: center; justify-content: center; gap: var(--sp-2); }

.worktime { margin: 0; }
/* Часы и карта на «Контактах» — два серых блока подряд: без двойного отступа между ними. */
#chasy { padding-bottom: 0; }
#chasy + .geo { padding-top: var(--sp-6); }
.worktime__title { margin-bottom: var(--sp-3); }
.worktime__now {
  display: flex; align-items: center; gap: var(--sp-2);
  margin-bottom: var(--sp-4); color: var(--ink-strong);
}
/* Неделя горизонтальной таблицей: дни в шапке, часы одной строкой под ними.
   Семь колонок держатся в 480px, поэтому на телефоне
   таблица прокручивается внутри .table-scroll, а на любом настольном экране
   помещается целиком.

   Колонка сегодняшнего дня подсвечивается: зелёная, пока идёт рабочее время,
   серая, если день выходной или рабочее время уже кончилось. Состояние
   считает сервер (work_status + work_week), скрипт к этому отношения не имеет. */
.worktime__week { min-width: 480px; }
.worktime__week th, .worktime__week td { padding: var(--sp-3) var(--sp-2); text-align: center; }
.worktime__week th:first-child, .worktime__week td:first-child { padding-left: var(--sp-2); }
.worktime__week thead th { white-space: nowrap; }
.worktime__week thead th abbr { text-decoration: none; border: 0; }
.worktime__week td { color: var(--muted); white-space: nowrap; }

.worktime__week .is-today { color: var(--ink-strong); font-weight: 600; background: var(--surface-2); }
.worktime__week .is-now   { color: var(--brand-dim); font-weight: 700; background: rgba(252,88,0,.1); }
.worktime__week thead th.is-today, .worktime__week thead th.is-now { border-bottom-color: var(--hairline-strong); }
/* Фон секции здесь серый, поэтому «серая» колонка берёт тон на ступень темнее
   строк — иначе выделения не видно. */
.section--surface .worktime__week .is-today { background: var(--surface-3); }

/* На телефоне те же семь колонок помещаются целиком: часы переносятся на две
   строки по разделителю, отступы сжимаются. Прокручивать неделю пальцем,
   чтобы увидеть пятницу, — плохая замена одному взгляду. */
@media (max-width: 640px) {
  .worktime__week { min-width: 0; }
  .worktime__week th, .worktime__week td { padding: var(--sp-2) 2px; }
  /* Часы переносятся сами по тире: «7:00–» и «16:00» в две строки. */
  .worktime__week td { white-space: normal; }
  /* «выходной» в колонку шириной 46px не помещается и рвёт слово посреди
     («выхо / дной»). Слово остаётся в разметке — его читают поисковик и
     скринридер, — а в ячейке печатается сокращение. */
  .worktime__week .worktime__off {
    position: absolute; width: 1px; height: 1px; margin: -1px;
    padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
  }
  .worktime__week .worktime__hours--off::after { content: 'вых.'; }
}

/* ===== 26. УТИЛИТЫ ===== */
.visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.stack { display: grid; gap: var(--sp-4); }
.row   { display: flex; gap: var(--sp-4); align-items: center; flex-wrap: wrap; }
.text-brand { color: var(--brand); }
.nowrap { white-space: nowrap; }

.scrim {
  position: fixed; inset: 0; z-index: 50;
  background: rgba(10,13,14,.6);
  opacity: 0; visibility: hidden; transition: opacity .2s, visibility .2s;
}
body.is-menu-open .scrim { opacity: 1; visibility: visible; }

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
  html { scroll-behavior: auto; }
}


/* Страница тендеров: три кадра оборудования и контакты списком. */
.tender-photos{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--sp-4);margin:var(--sp-6) 0;padding:0;list-style:none}
@media (max-width: 720px){.tender-photos{grid-template-columns:1fr}}

.tender-photos img{width:100%;height:auto;aspect-ratio:1/1;object-fit:contain;background:var(--surface);border-radius:var(--radius-lg)}
.tender-block{margin-top:var(--sp-8)}
.tender-block h2{margin-bottom:var(--sp-4)}
.tender-contacts{display:grid;gap:var(--sp-3);margin:var(--sp-5) 0 0;padding:0;list-style:none}
.tender-contacts li{display:flex;align-items:center;gap:var(--sp-3);font-size:var(--fs-base)}
.tender-contacts .note{color:var(--muted)}


/* ===== 27. КАТАЛОГ: ФИЛЬТРЫ, ЛИСТИНГ, КАРТОЧКА ТОВАРА =====
   Разделы каталога сгруппированы по смыслу (тип, мощность, разъём) — так же,
   как фильтры у лидеров ниши power-on.su и punkt-e.ru: плоский список из
   двенадцати ссылок читается хуже. */
.filters {
  display: grid; gap: var(--sp-4);
  margin-bottom: var(--sp-7); padding: var(--sp-5) var(--sp-6);
  border: 1px solid var(--hairline); border-radius: var(--radius-lg);
  background: var(--surface);
}
.filters__group { display: flex; align-items: baseline; gap: var(--sp-4); flex-wrap: wrap; }
.filters__title {
  flex: none; min-width: 140px;
  font-family: var(--font); font-size: var(--fs-label); font-weight: 700;
  letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--muted);
}
.filters__items { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.filters__item {
  display: inline-flex; align-items: center; min-height: 36px;
  padding: 0 var(--sp-4);
  font-size: var(--fs-sm); color: var(--ink-strong);
  background: var(--canvas);
  border: 1px solid var(--hairline-strong); border-radius: var(--radius-full);
  transition: border-color .15s, color .15s;
}
a.filters__item:hover { border-color: var(--brand); color: var(--brand-dim); text-decoration: none; }
.filters__item.is-current { background: var(--brand-press); border-color: var(--brand-press); color: var(--on-brand); }
@media (max-width: 720px) {
  .filters { padding: var(--sp-4); }
  .filters__group { gap: var(--sp-2); }
  .filters__title { min-width: 0; width: 100%; }
}

.catalog__title { margin: var(--sp-7) 0 var(--sp-5); }
.catalog__note { margin-top: var(--sp-5); }
.catalog__text { margin-top: var(--sp-7); }
.catalog__text p + p { margin-top: var(--sp-4); }
/* Первая колонка сравнения — подпись строки, а не значение: она уже и тише. */
.catalog__compare th[scope="row"] { width: 26%; color: var(--muted); font-weight: 500; }
/* Названия позиций в шапке переносятся: в одну строку три названия не помещаются и таблица уезжает за край. */
.catalog__compare thead th { white-space: normal; }

/* Карточка товара: слева кадр, справа цена и действие. */
/* minmax(0, …) обязателен: в правой колонке лежит таблица комплектаций шириной
   544px в своём .table-scroll. Колонка «1fr» не уже содержимого, поэтому
   прокручивалась не таблица, а вся страница — на телефоне карточка DC 150
   уезжала вправо на 200px. */
.product-page { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: var(--sp-8); align-items: start; }
@media (max-width: 860px) { .product-page { grid-template-columns: minmax(0, 1fr); gap: var(--sp-6); } }
.product-page__media {
  position: relative;
  border: 1px solid var(--hairline); border-radius: var(--radius-lg);
  overflow: hidden; background: var(--canvas);
}
.product-page__media img { width: 100%; height: auto; display: block; }
.product-page__media a { display: block; cursor: zoom-in; }

/* Дополнительные снимки под основным: клик открывает общий просмотрщик. */
.product-page__thumbs {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--sp-3);
  margin: var(--sp-3) 0 0; padding: 0; list-style: none;
}
.product-page__thumbs a {
  display: block; aspect-ratio: 1 / 1; overflow: hidden;
  border: 1px solid var(--hairline); border-radius: var(--radius);
  background: var(--canvas); cursor: zoom-in;
}
.product-page__thumbs a:hover { border-color: var(--brand); }
.product-page__thumbs img { width: 100%; height: 100%; object-fit: contain; display: block; }
@media (max-width: 560px) { .product-page__thumbs { grid-template-columns: repeat(3, 1fr); } }
/* Позиция без снимка: заглушка держит пропорцию колонки, иначе рамка схлопывается в полоску. */
.product-page__media .product__noimage {
  aspect-ratio: 1 / 1;
  align-items: center; justify-content: center;
  background: var(--surface);
}
.product-page__media .product__noimage svg { width: 64px; height: 64px; }
.product-page__info h1 { margin-bottom: var(--sp-4); }
.product-page__buy {
  display: flex; align-items: center; gap: var(--sp-5); flex-wrap: wrap;
  margin: var(--sp-6) 0;
  padding: var(--sp-5) var(--sp-6);
  border: 1px solid var(--hairline-strong); border-radius: var(--radius-lg);
}
.product-page__price { margin: 0; font-size: var(--fs-h3); }
.product-page__price b { color: var(--ink-strong); }
.product-page__price .product__price-label { display: block; font-size: var(--fs-caption); color: var(--muted); }
.hub-head__prices { margin: var(--sp-4) 0 0; }
.product-page__price-note { flex-basis: 100%; margin: calc(var(--sp-3) * -1) 0 0; font-size: var(--fs-caption); color: var(--muted); }
.product-page__points { margin-top: var(--sp-5); }
.product-page__text { margin-top: var(--sp-7); }
.product-page__text p + p { margin-top: var(--sp-4); }
.product-page__title { margin: var(--sp-8) 0 var(--sp-5); font-size: var(--fs-h3); }
.product-page__cols { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-8); }
@media (max-width: 860px) { .product-page__cols { grid-template-columns: 1fr; gap: var(--sp-6); } }
/* Строка с моделью в окне заявки: показывается только для кнопок каталога. */
.modal__product {
  margin: 0 0 var(--sp-4); padding: var(--sp-3) var(--sp-4);
  font-size: var(--fs-sm); color: var(--body);
  background: var(--surface); border-radius: var(--radius);
}
.modal__product b { color: var(--ink-strong); }

/* Калькулятор возмещения на странице субсидии: та же сетка, что у калькулятора
   окупаемости, но проще — четыре поля и одна цифра-ответ. */
/* Городской калькулятор: та же механика и те же data-атрибуты, другой макет —
   результат идёт первым и во всю ширину, поля собраны под ним в три колонки.
   На городской странице человек сначала смотрит на цифру, а уже потом
   подкручивает параметры под свою площадку. */
.calc--city { grid-template-columns: 1fr; gap: var(--sp-6); }
.calc--city .calc__result {
  order: -1;
  padding: var(--sp-6) var(--sp-6) var(--sp-5);
  background: var(--ink); color: #fff;
}
.section--surface .calc--city .calc__result { background: var(--ink); }
.calc--city .calc__figures {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-5);
  margin-bottom: var(--sp-5);
}
.calc--city .calc__pair { display: contents; }
.calc--city .figure { border-left-color: rgba(255,255,255,.24); }
.calc--city .figure--accent { border-left-color: var(--brand); }
.calc--city .figure__label,
.calc--city .calc__result .note { color: rgba(255,255,255,.62); }
.calc--city .figure__value { color: #fff; }
.calc--city .figure--accent .figure__value { color: var(--brand); }
.calc--city .chart__caption { color: rgba(255,255,255,.62); }
.calc--city .chart__box { max-height: 300px; }
.calc--city .chart__box svg { max-height: 300px; }
.calc--city .calc__form {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-5);
  align-items: start;
}
/* Поля, которым нужна вся ширина строки: переключатель мощности и подписи под формой. */
.calc--city .calc__form > .grid--2 { display: contents; }
.calc--city .calc__subsidy,
.calc--city .calc__footnote { grid-column: 1 / -1; margin-top: 0; }
@media (max-width: 900px) {
  .calc--city .calc__figures { grid-template-columns: 1fr; }
  .calc--city .calc__form { grid-template-columns: 1fr; }
}
.calc--subsidy { margin-top: var(--sp-7); }
.calc__title { font-size: var(--fs-h3); margin-bottom: var(--sp-3); }

/* ---------------------------------------------------------------------------
   Каталог: фильтр слева, товары справа
   ---------------------------------------------------------------------------
   Компоновка каталогов топа (punkt-e.ru, power-on.su — сканы в выгрузке ГАР):
   человек сразу видит и товары, и по чему их отбирать. Фильтр — обычная форма
   GET, без скриптов; JS нужен ровно для одного — схлопнуть панель на телефоне.
   --------------------------------------------------------------------------- */
.catalog-layout {
  display: grid;
  grid-template-columns: 280px minmax(0, 1fr);
  gap: var(--sp-6);
  align-items: start;
}
.catalog-layout__bar {
  display: flex; align-items: baseline; justify-content: space-between;
  /* Перенос обязателен: счётчик «30 из 30 позиций» набран white-space: nowrap,
     и на узком экране строка «заголовок + счётчик» не помещалась — страница
     получала горизонтальную прокрутку. С переносом счётчик уходит под заголовок. */
  flex-wrap: wrap;
  gap: var(--sp-4); margin-bottom: var(--sp-5);
}
.catalog-layout__bar .catalog__title { margin: 0; }
.catalog-layout__count { color: var(--muted); font-size: var(--fs-caption); white-space: nowrap; }

/* Панель фильтра */
.cat-filter-wrap { border: 1px solid var(--hairline); border-radius: var(--radius-lg); background: var(--canvas); }
.cat-filter-wrap__toggle {
  display: none;                      /* на десктопе панель всегда раскрыта */
  padding: var(--sp-4) var(--sp-5);
  font-weight: 700; cursor: pointer;
}
.cat-filter-wrap__toggle::-webkit-details-marker { display: none; }
.cat-filter { padding: var(--sp-5); }
.cat-filter__head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--sp-3); margin-bottom: var(--sp-4);
}
.cat-filter__title { font-weight: 700; }
.cat-filter__reset { font-size: var(--fs-caption); }
.cat-filter__group { border: 0; padding: 0; margin: 0 0 var(--sp-5); }
.cat-filter__group legend {
  padding: 0; margin-bottom: var(--sp-3);
  font-size: var(--fs-caption); font-weight: 700; text-transform: uppercase;
  letter-spacing: .04em; color: var(--muted);
}
.cat-filter__opt {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: 6px 0; cursor: pointer;
}
.cat-filter__opt span { flex: 1 1 auto; }
/* Число позиций в срезе — подсказка, а не значение: приглушаем. */
.cat-filter__opt b { color: var(--muted); font-weight: 400; font-size: var(--fs-caption); }
.cat-filter__opt input { accent-color: var(--brand); width: 16px; height: 16px; }
.cat-filter__submit { width: 100%; }

@media (max-width: 1024px) {
  .catalog-layout { grid-template-columns: 240px minmax(0, 1fr); }
}
@media (max-width: 900px) {
  /* minmax(0, 1fr), а не 1fr: колонка «1fr» не уже своего содержимого, а внутри
     лежит панель фильтра с <select>. На экране 320px она распирала раскладку до
     347px и вся страница получала горизонтальную прокрутку. */
  .catalog-layout { grid-template-columns: minmax(0, 1fr); }
  .cat-filter-wrap__toggle { display: block; }   /* появляется кнопка-раскрытие */
}

/* ---------------------------------------------------------------------------
   Хаб в формате интернет-магазина: /services
   ---------------------------------------------------------------------------
   Без первого экрана с фоном: крошки, h1 и подзаголовок, под ними плитки
   разделов (картинка + подпись, 5 в ряд), ниже — фильтр слева и листинг.
   Фильтр — .cat-filter выше, листинг — компактные горизонтальные карточки:
   семьдесят вертикальных карточек с кадром растянули бы страницу на десять
   экранов. */
.section--hub-head { padding-bottom: var(--sp-8); }
.hub-head { max-width: 920px; margin-bottom: var(--sp-7); }
.hub-head h1 { margin-bottom: var(--sp-4); text-wrap: balance; }
.hub-head .lead { margin: 0; }

.cat-tiles {
  display: grid; grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: var(--sp-4); margin: 0; padding: 0; list-style: none;
}
.cat-tile {
  display: flex; flex-direction: column; height: 100%;
  border: 1px solid var(--hairline); border-radius: var(--radius-lg);
  background: var(--canvas); color: var(--ink-strong); text-decoration: none;
  overflow: hidden; transition: border-color .15s ease;
}
.cat-tile:hover { border-color: var(--brand); text-decoration: none; }
.cat-tile__media { display: block; aspect-ratio: 2 / 1; overflow: hidden; background: var(--surface); }
.cat-tile__media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.cat-tile__title {
  display: block; padding: var(--sp-3) var(--sp-4);
  font-size: var(--fs-sm); font-weight: 600; line-height: 1.3;
  hyphens: auto; -webkit-hyphens: auto;   /* «резинотехнических» на телефоне не помещается в строку: без переноса слово рвалось по букве */
}
.cat-tile:hover .cat-tile__title { color: var(--brand-dim); }

.svc-list {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sp-4); margin: 0; padding: 0; list-style: none;
}
.svc-list__item[hidden] { display: none; }
.svc-card {
  display: grid; grid-template-columns: 132px minmax(0, 1fr); gap: var(--sp-4);
  height: 100%; padding: var(--sp-3);
  border: 1px solid var(--hairline); border-radius: var(--radius-lg);
  background: var(--canvas); color: var(--body); text-decoration: none;
  transition: border-color .15s ease;
}
.svc-card:hover { border-color: var(--brand); text-decoration: none; }
.svc-card__media { display: block; aspect-ratio: 4 / 3; border-radius: 8px; overflow: hidden; background: var(--surface); }
.svc-card__media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.svc-card__body { display: block; min-width: 0; }
.svc-card__tag {
  display: block; margin-bottom: 2px;
  font-size: var(--fs-caption); color: var(--muted);
}
.svc-card__title { display: block; margin-bottom: var(--sp-1, 4px); font-size: 1rem; line-height: 1.3; color: var(--ink-strong); }
.svc-card:hover .svc-card__title { color: var(--brand-dim); }
/* Анонс — в две строки: целиком он в html (его читает поисковик), а глазу
   хватает начала, дальше — страница услуги. */
.svc-card__text {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
  font-size: var(--fs-caption); line-height: 1.45;
}
.svc-empty {
  padding: var(--sp-6); border: 1px dashed var(--hairline); border-radius: var(--radius-lg);
  background: var(--canvas); text-align: center;
}
.svc-empty[hidden] { display: none; }
.svc-empty p { margin: 0 auto var(--sp-4); max-width: 520px; }

/* Отбор мгновенный: на 350 мс приглушаем листинг — метка, что фильтр сработал.
   */
[data-list] { transition: opacity .2s ease; }
[data-list].is-filtering { opacity: .45; }
.cat-filter__opt.is-empty { color: var(--faint); cursor: default; }
/* Подпись варианта в две строки («Гибка и пробивка листа») — плотнее общего текста, иначе группа рассыпается. */
.cat-filter__opt span { line-height: 1.3; }
/* «Сбросить» — ссылкой, а не системной кнопкой: правило было только в стилях лендинга elli-t. */
.cat-filter__reset { padding: 0; border: 0; background: none; color: var(--brand-dim); cursor: pointer; text-decoration: underline; font: inherit; font-size: var(--fs-caption); }

@media (max-width: 1200px) {
  .cat-tiles { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .svc-list { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 900px) {
  .cat-tiles { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  /* на телефоне панель раскрывается кнопкой с тем же названием — второй заголовок внутри не нужен */
  .cat-filter__head .cat-filter__title { visibility: hidden; }
  .svc-list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 640px) {
  .cat-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-3); }
  .cat-tile__title { padding: var(--sp-2) var(--sp-3); font-size: var(--fs-caption); }
  .svc-list { grid-template-columns: minmax(0, 1fr); gap: var(--sp-3); }
  .svc-card { grid-template-columns: 96px minmax(0, 1fr); gap: var(--sp-3); }
}

/* ЖД-каталог: фильтр строкой над сеткой — позиций десять, колонка слева для них избыточна.
   Варианты — «пилюли»; разметка и скрипт те же, что у фильтра /services, поэтому .cat-filter__opt на месте. */
.hub-head__actions { display: flex; flex-wrap: wrap; gap: var(--sp-3); margin-top: var(--sp-5); }
.chip-filter { margin-bottom: var(--sp-6); }
.chip-filter__group { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); border: 0; padding: 0; margin: 0 0 var(--sp-3); }
.chip-filter__group legend {
  float: left; margin-right: var(--sp-3); padding: 0;
  font-size: var(--fs-caption); font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--muted);
}
.chip-filter__opt.cat-filter__opt {
  position: relative; gap: var(--sp-2); padding: 6px 14px;
  border: 1px solid var(--hairline); border-radius: 999px; background: var(--canvas);
  font-size: var(--fs-sm);
}
.chip-filter__opt input { position: absolute; opacity: 0; pointer-events: none; }
.chip-filter__opt:has(input:checked) { border-color: var(--brand-press); background: var(--brand-press); color: var(--on-brand); }
.chip-filter__opt:has(input:checked) b { color: var(--on-brand); }
.chip-filter__opt:has(input:focus-visible) { outline: 2px solid var(--brand); outline-offset: 2px; }
.chip-filter__opt:not(.is-empty):hover { border-color: var(--brand); }
.chip-filter__bar { display: flex; gap: var(--sp-4); align-items: baseline; margin: var(--sp-2) 0 0; }
.cat-tile__text {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden;
  margin: calc(var(--sp-2) * -1) var(--sp-4) var(--sp-4);
  font-size: var(--fs-caption); line-height: 1.45; color: var(--body);
}
.cat-tiles--goods .cat-tile__media { aspect-ratio: 3 / 2; }
.cat-tiles li[hidden] { display: none; }
@media (max-width: 640px) {
  .cat-tile__text { margin: calc(var(--sp-1) * -1) var(--sp-3) var(--sp-3); }
  /* «Железнодорожное электрооборудование» одним словом шире экрана 360 px: без уменьшения h1 рвался по букве */
  .hub-head h1 { font-size: 1.625rem; }
  /* Плитка товара в две колонки по 170 px не вмещает «Электропневматические» — на телефоне карточка горизонтальная, как у услуг */
  .cat-tiles--goods { grid-template-columns: minmax(0, 1fr); }
  .cat-tiles--goods .cat-tile { display: grid; grid-template-columns: 84px minmax(0, 1fr); grid-template-rows: auto 1fr; column-gap: var(--sp-3); padding: var(--sp-3); }
  .cat-tiles--goods .cat-tile__media { grid-row: 1 / 3; aspect-ratio: 4 / 3; border-radius: 8px; }
  .cat-tiles--goods .cat-tile__title { padding: 0 0 var(--sp-1); font-size: var(--fs-sm); }
  .cat-tiles--goods .cat-tile__text { margin: 0; -webkit-line-clamp: 2; }
}

/* Карточка станции Elli: кадр станции вертикальный, поэтому колонка под
   него уже, чем у карточки ЖД; подзаголовки блоков внутри колонки — размером h3. */
.product-page--narrow-media { grid-template-columns: minmax(0, 4fr) minmax(0, 8fr); }
.product-page--narrow-media .product-page__media img { max-height: 760px; object-fit: contain; }
.product-page__info .h3 { font-size: var(--fs-h3, 1.375rem); margin: var(--sp-7) 0 var(--sp-4); }
.product-page__info .prose { margin-top: var(--sp-6); }
.cat-tiles--two { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.cat-tiles--two .cat-tile__media { aspect-ratio: 4 / 3; }
.cat-tiles--two .cat-tile__media img { object-fit: contain; background: var(--surface); }
/* Три станции на хабе /catalog/stantsii-dlya-zaryadki-elektromobiley-elli: кадры вертикальные, как у --two;
   на телефоне — горизонтальные карточки товара из правила .cat-tiles--goods выше */
.cat-tiles--three { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.cat-tiles--three .cat-tile__media { aspect-ratio: 4 / 3; }
.cat-tiles--three .cat-tile__media img { object-fit: contain; background: var(--surface); }
@media (max-width: 640px) { .cat-tiles--three { grid-template-columns: minmax(0, 1fr); } }

/* Подпись отдела под номером на «Контактах» */
.contacts-facts__phones small { display: block; margin: 2px 0 var(--sp-3); font-size: var(--fs-caption); color: var(--muted); }

/* Условия заказа под шагами «Как заказать» на /services */
.points--terms { margin: var(--sp-7) 0 0; padding-top: var(--sp-6); border-top: 1px solid var(--hairline); }

/* Сетка плашек-фактов (отрасли на /services): промежуток задаёт сетка, у плашки свой нижний отступ снят;
   первая строка плашки — заголовок карточки, жирным */
.grid--callouts { gap: var(--sp-5); }
.grid--callouts .callout { margin: 0; }
.grid--callouts .callout__lead { font-weight: 700; color: var(--ink-strong); }

/* ===========================================================================
   Уведомление о cookie
   Полоса внизу экрана до первого «Принять» (blocks.php → cookie_bar,
   показ и запоминание — main.js). Тёмная, как подвал: это служебное сообщение,
   а не часть контента, и оно не должно спорить с блоками страницы.
   =========================================================================== */
/* Уведомление о cookie — небольшая карточка в углу, а не полоса во всю ширину
: прежняя занимала треть экрана телефона и закрывала
   кнопки первого экрана. Показывается не сразу — main.js выводит её после
   прокрутки на два экрана: до этого человек ещё не начал пользоваться сайтом.
   Угол левый: правый занят кнопкой чата. */
.cookie {
  position: fixed; left: 20px; bottom: 20px; z-index: 59;
  width: min(320px, calc(100vw - 40px));
  background: var(--dark-2); color: var(--on-dark-2);
  border: 1px solid var(--hairline-dark); border-radius: var(--radius-lg);
  box-shadow: 0 12px 32px rgba(10,13,14,.4);
  opacity: 0; transform: translateY(12px);
  transition: opacity .25s ease, transform .25s ease;
}
.cookie.is-visible { opacity: 1; transform: none; }
.cookie__inner { display: grid; gap: var(--sp-3); padding: var(--sp-4); }
.cookie__text { margin: 0; font-size: var(--fs-caption); line-height: 1.45; }
.cookie__text a { color: var(--on-dark); text-decoration: underline; text-underline-offset: 3px; }
.cookie__text a:hover { color: var(--brand-light); }
.cookie__accept { flex: 0 0 auto; }

/* На телефоне карточка занимает почти всю ширину, и круг чата ложится на её
   текст и кнопку «Принять». Пока плашка видна, кнопки чата и «наверх» встают
   над ней: высоту карточки главному элементу проставляет main.js. */
@media (max-width: 720px) {
  body:has(.cookie.is-visible) { --dock-lift: calc(var(--cookie-h, 0px) + 12px); }
}

/* ===========================================================================
   Юридические документы (/law/*)
   Длинный текст с нумерованными пунктами. Читается редко, но должен читаться
   без усилий: узкая колонка, спокойные интервалы, заметные подзаголовки.
   =========================================================================== */
.legal h3 { margin: var(--sp-6) 0 var(--sp-3); font-size: var(--fs-h4); }
.legal p, .legal li { color: var(--body); }
.legal ul, .legal ol { margin: 0 0 var(--sp-4); padding-left: var(--sp-5); }
.legal li { margin-bottom: var(--sp-2); }
.legal i { color: var(--muted); font-style: normal; }   /* пояснения в скобках */

/* Плашка «документ не готов»: видна только пока не заполнены реквизиты. */
.note--warning {
  background: var(--surface); border: 1px solid var(--badge-amber);
  color: var(--ink-strong); padding: var(--sp-4); margin-bottom: var(--sp-5);
  font-size: var(--fs-body);
}

/* Список документов в разделе «Юридическая информация» */
.law-list { list-style: none; margin: var(--sp-6) 0 0; padding: 0; display: grid; gap: var(--sp-4); }
.law-list__item {
  border-top: 1px solid var(--hairline); padding-top: var(--sp-4);
  display: grid; gap: var(--sp-1);
}
.law-list__link { font-size: var(--fs-h4); font-weight: 600; color: var(--ink-strong); }
.law-list__link:hover { color: var(--brand-dim); }
.law-list__note { color: var(--muted); font-size: var(--fs-caption); }

/* ===========================================================================
   Расширенный калькулятор окупаемости
   Четыре колонки в один ряд на широком мониторе: параметры оборудования,
   параметры эксплуатации, результат и накопленная прибыль по годам. Ниже
   1280px колонки встают попарно, на телефоне — друг под другом.
   =========================================================================== */
/* Колонки калькулятора одной высоты: разная длина подписей делала карточки
   разного роста, и ряд читался неровно. */
.calcpro {
  display: grid; gap: var(--sp-4); margin: var(--sp-6) 0;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  align-items: stretch;
}
.calcpro__col {
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: 2px; padding: var(--sp-5); min-width: 0;
  display: grid; gap: var(--sp-4); align-content: start;
}
/* Колонка результата: тёмная плашка с диагональной штриховкой вместо плоской заливки: плоский чёрный
   читался мрачно. Линии 6% белого, шаг 6px: под текстом
   не видны, на фоне дают фактуру. */
.calcpro__col--result {
  background:
    repeating-linear-gradient(135deg, rgba(255,255,255,.06) 0 1px, transparent 1px 6px),
    var(--dark-2);
  border-color: var(--dark-3); color: var(--on-dark);
}
.calcpro__col--chart { background: var(--canvas); }

.calcpro__title { font-size: var(--fs-h4); margin: 0; }
.calcpro__title--on-brand { color: var(--on-dark); }

.calcpro__figure { display: grid; gap: 2px; padding-bottom: var(--sp-4); border-bottom: 1px solid var(--dark-3); }
.calcpro__figure:last-child { border-bottom: 0; padding-bottom: 0; }
.calcpro__cap { font-size: var(--fs-caption); color: #98A2A7; }
.calcpro__value { font-size: 1.75rem; font-weight: 700; line-height: 1.15; color: var(--brand-light); }
.calcpro__note { font-size: var(--fs-caption); color: #98A2A7; }

.calcpro__col--result .field__label,
.calcpro__col--result .note { color: #C9D1D3; }
.calcpro__subsidy { margin-top: auto; }

/* Подсказка по наведению и с клавиатуры: у иконки есть tabindex, поэтому
   :focus-within открывает её без мыши. */
.hint {
  position: relative; display: inline-grid; place-items: center;
  width: 1.125rem; height: 1.125rem; margin-left: .25rem; vertical-align: middle;
  border: 1px solid var(--hairline-strong); border-radius: 50%;
  font-size: .6875rem; color: var(--muted); cursor: help;
}
.hint__text {
  position: absolute; bottom: calc(100% + .5rem); left: 50%; transform: translateX(-50%);
  width: 16rem; padding: .625rem .75rem; z-index: 5;
  background: var(--dark-2); color: var(--on-dark); font-size: var(--fs-caption);
  line-height: 1.45; text-align: left; border-radius: 2px; box-shadow: var(--shadow-menu);
  opacity: 0; visibility: hidden; transition: opacity .15s;
}
.hint:hover .hint__text, .hint:focus-within .hint__text { opacity: 1; visibility: visible; }
@media (max-width: 560px) {
  /* у края экрана всплывающая подсказка уезжала за границу */
  .hint__text { left: auto; right: 0; transform: none; width: min(16rem, 70vw); }
}

/* ---- Накопленная прибыль: полосы влево-вправо от оси ---------------------- */
.bars { display: grid; gap: var(--sp-3); }
.bars__row { display: grid; grid-template-columns: 4.5rem minmax(0, 1fr); align-items: center; gap: var(--sp-2); }
.bars__year { font-size: var(--fs-caption); color: var(--muted); }
.bars__track {
  position: relative; display: block; height: 1.5rem;
  /* ось по центру: от неё полосы расходятся в обе стороны */
  background: linear-gradient(var(--hairline-strong), var(--hairline-strong)) 50% 0 / 1px 100% no-repeat;
}
.bars__bar { position: absolute; top: .25rem; height: 1rem; border-radius: 1px; }
.bars__bar.is-minus { right: 50%; background: var(--hairline-strong); }
.bars__bar.is-plus  { left: 50%; background: var(--brand); }
/* Позицию подписи задаёт скрипт: она встаёт за концом полосы, иначе
   перекрывается ею и не читается. */
.bars__value {
  position: absolute; top: 50%; transform: translateY(-50%);
  font-size: var(--fs-caption); color: var(--muted); white-space: nowrap;
}
.bars__value.is-plus { color: var(--ink-strong); font-weight: 600; }

@media (max-width: 1280px) {
  .calcpro { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 720px) {
  .calcpro { grid-template-columns: minmax(0, 1fr); }
  .calcpro__col { padding: var(--sp-4); }
}

@media (max-width: 720px) {
  /* на узком экране подпись у длинной полосы упиралась в край карточки */
  .bars__row { grid-template-columns: 3.75rem minmax(0, 1fr); }
  .bars__year, .bars__value { font-size: .8125rem; }
}

/* Содержание страницы: якорная навигация по длинному документу.
   Две колонки на широком экране, одна на мобильном — восемь пунктов в столбик
   съедали бы целый экран до первого блока текста. */
.toc {
  margin: var(--sp-6) 0 var(--sp-7);
  padding: var(--sp-5) var(--sp-6);
  border: 1px solid var(--hairline);
  border-left: 3px solid var(--brand);
  border-radius: var(--radius-md);
  background: var(--surface);
}
.toc__title {
  margin: 0 0 var(--sp-4);
  font-size: var(--fs-caption); font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; color: var(--muted);
}
.toc__list {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sp-2) var(--sp-6);
  margin: 0; padding: 0 0 0 var(--sp-5);
  font-size: var(--fs-sm);
}
.toc__item { margin: 0; padding-left: var(--sp-1); }
.toc__link { color: var(--body); text-decoration: none; }
.toc__link:hover { color: var(--brand-dim); text-decoration: underline; }

@media (max-width: 768px) {
  .toc { padding: var(--sp-4) var(--sp-5); }
  .toc__list { grid-template-columns: 1fr; }
}

/* Содержание виджетом сбоку: на широком экране оно уходит в узкую
   колонку рядом с текстом и едет вместе с прокруткой — второй экран начинается
   сразу с содержательного блока. Ниже 1000px возвращается обычным блоком над
   текстом: колонка в 280px и текст на телефоне рядом не помещаются. */
/* До 1000px обёртка ничего не делает: обычный блок ужимается по экрану сам,
   а сетка на узком экране вытягивала страницу вбок на 7px. */
.article-aside { max-width: var(--wrap-narrow); margin-inline: auto; }
/* Содержание-виджет живёт без зелёной полосы слева: рядом с колонкой текста она читается как цитата, а не как навигация. */
.toc--aside { border-left: 1px solid var(--hairline); }   /* до порога сайдбара обёртка держит ширину текста, иначе содержание шире абзацев */
.article-aside > * { min-width: 0; }

/* Содержание занимает левое поле страницы, а колонка текста остаётся той же
   ширины и на том же месте, что в остальных секциях:
   средняя колонка сетки равна текстовой, боковые забирают свободные поля. */
@media (min-width: 1500px) {
  .article-aside {
    max-width: none; display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, var(--wrap-narrow)) minmax(0, 1fr);
    gap: var(--sp-6); align-items: start;
  }
  .toc--aside { position: sticky; top: var(--sp-5); margin: 0; padding: var(--sp-4) var(--sp-5); }
  .toc--aside .toc__list { grid-template-columns: 1fr; gap: var(--sp-2); padding-left: var(--sp-4); }
  .toc--aside .toc__link { font-size: var(--fs-caption); }
  .article-aside .prose { margin-inline: 0; }
}

/* Смежные услуги: сетка ссылок-карточек внизу страницы услуги. */
.related-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: var(--sp-4);
  margin: var(--sp-6) 0 0; padding: 0; list-style: none;
}
.related-card {
  display: block; height: 100%;
  padding: var(--sp-5);
  border: 1px solid var(--hairline); border-radius: var(--radius-md);
  background: var(--canvas); color: var(--body); text-decoration: none;
  transition: border-color .15s, box-shadow .15s;
}
.related-card:hover { border-color: var(--brand); box-shadow: 0 2px 12px rgba(0,0,0,.06); text-decoration: none; }
.related-card__title {
  display: block; margin-bottom: var(--sp-2);
  font-size: var(--fs-sm); font-weight: 600; color: var(--ink-strong);
}
.related-card:hover .related-card__title { color: var(--brand-dim); }
.related-card__text { display: block; font-size: var(--fs-caption); color: var(--muted); }

/* Изображение с обтеканием справа — переиспользуемый вариант того, что было
   сделано для блока субсидии на главной. Нужен на каждой длинной
   странице под ГАР: сплошной текст без картинок снижает вовлечённость, а
   отдельного компонента под это не было. */
.media-float {
  float: right; width: min(460px, 36%);
  margin: 0 0 var(--sp-5) var(--sp-7);
}
.media-float img { width: 100%; height: auto; border-radius: var(--radius-lg); }
.media-float figcaption {
  margin-top: var(--sp-2);
  font-size: var(--fs-caption); color: var(--muted); text-align: center;
}
/* Раздел с картинкой замыкает обтекание: при коротком тексте кадр с подписью иначе наезжал на следующий раздел.
   Только у разделов с .media-float. */
.section .wrap:has(.media-float)::after { content: ""; display: block; clear: both; }
/* Плашка примечания рядом с кадром обходит его, а не подлезает фоном под картинку. */
.wrap:has(.media-float) .note--block { display: flow-root; }
/* Таблица после кадра уходит под него: рядом с обтеканием столбцы сжимаются и обрезаются */
.media-float ~ .table-scroll { clear: both; }
/* Сетка карточек после кадра — тоже под него: рядом с обтеканием шесть карточек сжимались в узкую колонку слева, а справа
   под кадром оставалась пустота. Отступ — чтобы список
   над сеткой не прилипал к карточкам. */
.media-float ~ .grid--list { clear: both; margin-top: var(--sp-6); }
@media (max-width: 800px) {
  .media-float { float: none; width: 100%; margin: 0 0 var(--sp-5); }
}

/* Видео объекта в теле страницы: постер до нажатия, подпись под кадром. */
.video-block { margin: var(--sp-7) 0 0; }
.video-block video {
  width: 100%; height: auto; border-radius: var(--radius-lg);
  background: var(--surface-3);
}
.video-block figcaption {
  margin-top: var(--sp-2);
  font-size: var(--fs-caption); color: var(--muted); text-align: center;
}

/* Нумерованный список порядка действий — когда шаги важны последовательностью,
   но карточки «дорожной карты» избыточны. */
.steps-list {
  margin: var(--sp-5) 0 var(--sp-4); padding-left: var(--sp-6);
  display: grid; gap: var(--sp-3);
  font-size: var(--fs-sm);
}
.steps-list li { padding-left: var(--sp-2); }
.steps-list li::marker { color: var(--brand); font-weight: 600; }

/* ===========================================================================
   КАРТОЧКА ТОВАРА: СУБСИДИЯ, ДОСТАВКА, ДОКУМЕНТАЦИЯ, ОТЗЫВЫ
   Каждый блок — своя секция с якорем, поэтому первый заголовок в секции
   не должен добавлять верхний отступ поверх отступа самой секции.
   =========================================================================== */
.product-page__title--first { margin-top: 0; }
.product-page__subtitle {
  margin: var(--sp-6) 0 var(--sp-4);
  font-size: var(--fs-h4, 1.125rem); font-weight: 600;
}
/* Текст сразу под подзаголовком: отступ даёт сам подзаголовок, а верхний отступ текста (--sp-7) отрывал абзац от него.
   */
.product-page__subtitle + .product-page__text { margin-top: 0; }
.product-page__more { margin-top: var(--sp-5); }

/* Пояснение в рамке: длинная оговорка про подтверждение документами читается
   хуже, если идёт тем же потоком, что и абзацы выше. */
.note--block {
  margin-top: var(--sp-5);
  padding: var(--sp-4) var(--sp-5);
  border-left: 3px solid var(--hairline-strong);
  background: var(--surface);
  border-radius: var(--radius-md);
}
.section--surface .note--block { background: #fff; }

/* Перелинковка списком: ссылки на смежные страницы под блоком. */
.links-list {
  margin: var(--sp-5) 0 0; padding: 0; list-style: none;
  display: grid; gap: var(--sp-2);
  font-size: var(--fs-sm);
}
.links-list a { color: var(--brand-dim); }

/* Логотипы транспортных компаний. Приведены к одной высоте: файлы заказчика
   разного кегля, и без ограничения строка выглядит рваной. */
.carriers {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--sp-5) var(--sp-6);
  margin: var(--sp-4) 0 0; padding: 0; list-style: none;
}
.carriers__item { display: flex; align-items: center; }
.carriers__item img {
  width: auto; height: 28px; max-width: 150px; object-fit: contain;
  filter: grayscale(1); opacity: .75;
}
.carriers__item img:hover { filter: none; opacity: 1; }

/* Файлы к скачиванию. */
.files {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: var(--sp-4);
  margin: var(--sp-6) 0 0; padding: 0; list-style: none;
}
.files__link {
  display: flex; gap: var(--sp-4); align-items: flex-start;
  padding: var(--sp-5);
  border: 1px solid var(--hairline); border-radius: var(--radius-lg);
  background: #fff; color: var(--body); text-decoration: none;
  transition: border-color .15s ease;
}
.files__link:hover { border-color: var(--brand); }
.files__icon { flex: 0 0 auto; color: var(--brand); }
.files__body { display: block; }
.files__title { display: block; margin-bottom: var(--sp-1); }
.files__link:hover .files__title { color: var(--brand-dim); }
.files__text { display: block; font-size: var(--fs-sm); color: var(--muted); }
.files__size {
  display: block; margin-top: var(--sp-2);
  font-family: var(--font-mono); font-size: var(--fs-caption); color: var(--muted);
}

/* Обложки документов в ряд: первая страница файла как миниатюра. Пропорции у
   листов разные (презентация 16:9, документы A4), поэтому высота кадра задана,
   а снимок вписывается целиком. */
.covers {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: var(--sp-5);
  margin: var(--sp-6) 0 0; padding: 0; list-style: none;
}
@media (max-width: 900px) { .covers { grid-template-columns: 1fr; } }
.cover-card__link {
  display: block; height: 100%;
  padding: var(--sp-4) var(--sp-4) var(--sp-5);
  border: 1px solid var(--hairline); border-radius: var(--radius-lg);
  background: #fff; color: var(--body); text-decoration: none;
  transition: border-color .15s ease;
}
.cover-card__link:hover { border-color: var(--brand); }
.cover-card__media {
  display: flex; align-items: center; justify-content: center;
  height: 260px; margin-bottom: var(--sp-4);
  background: var(--surface-2); border: 1px solid var(--hairline);
  overflow: hidden;
}
.cover-card__media img { max-width: 100%; max-height: 100%; width: auto; height: auto; object-fit: contain; }
.cover-card__title { display: block; margin-bottom: var(--sp-2); }
.cover-card__link:hover .cover-card__title { color: var(--brand-dim); }
.cover-card__text { display: block; font-size: var(--fs-sm); color: var(--muted); }
.cover-card__meta {
  display: block; margin-top: var(--sp-3);
  font-family: var(--font-mono); font-size: var(--fs-caption); color: var(--muted);
}
/* Отзывы. Пустого рейтинга «0.0» здесь нет намеренно: пока отзывов нет, блок
   показывает приглашение, а не ноль. */
.reviews {
  display: grid; gap: var(--sp-4);
  margin: 0 0 var(--sp-7); padding: 0; list-style: none;
}
.reviews__item {
  padding: var(--sp-5) var(--sp-6);
  border: 1px solid var(--hairline); border-radius: var(--radius-lg);
  background: #fff;
}
.reviews__head {
  display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-4); align-items: baseline;
  margin: 0 0 var(--sp-3);
}
.reviews__company, .reviews__date { font-size: var(--fs-caption); color: var(--muted); }
.reviews__text { margin: 0; }

.review-form {
  margin-top: var(--sp-6);
  padding: var(--sp-6) var(--sp-7);
  border: 1px solid var(--hairline); border-radius: var(--radius-lg);
  background: #fff;
}
.review-form__invite { margin: 0 0 var(--sp-5); color: var(--muted); }
.review-form__grid {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0 var(--sp-5);
}
.review-form .btn { margin-top: var(--sp-4); }
.review-form .consent { margin-top: var(--sp-5); }

@media (max-width: 700px) {
  .review-form { padding: var(--sp-5); }
  .review-form__grid { grid-template-columns: 1fr; }
  .carriers { gap: var(--sp-4) var(--sp-5); }
}

/* Список после абзацев в колонке «Оплата»: без отступа первый пункт прилипает
   к последней строке текста. */
.product-page__cols .prose + .points { margin-top: var(--sp-4); }
.review-form .consent + .note { margin-top: var(--sp-3); }

/* Баннер услуги в колонке фильтра каталога.
   Держится на светлой подложке и зелёной кнопке — тёмная плашка в узкой
   колонке спорила бы с шапкой. */
.promo-card {
  margin-top: var(--sp-5);
  padding: var(--sp-5);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-lg);
  background: var(--surface);
}
.promo-card__title { margin: 0 0 var(--sp-3); font-size: var(--fs-h4); }
.promo-card__text { margin: 0 0 var(--sp-4); font-size: var(--fs-sm); }
.promo-card__points {
  display: grid; gap: var(--sp-2);
  margin: 0 0 var(--sp-5); padding: 0; list-style: none;
  font-size: var(--fs-caption);
}
.promo-card__points li { display: flex; gap: var(--sp-2); align-items: flex-start; }
.promo-card__icon { flex: 0 0 auto; color: var(--brand); margin-top: 2px; }
.promo-card__btn { width: 100%; }
.promo-card__more { margin: var(--sp-4) 0 0; font-size: var(--fs-caption); }

.catalog__carriers-title {
  margin: var(--sp-7) 0 0;
  font-size: var(--fs-caption); font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; color: var(--muted);
}

/* ===========================================================================
   БЛОГ: ХАБ И СТАТЬЯ
   Классы статьи названы article__*, а не post__*: post — это карточка статьи
   в ленте на главной, у неё свои размеры заголовка и отступы.
   =========================================================================== */
.posts {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: var(--sp-6);
  margin: var(--sp-7) 0 0; padding: 0; list-style: none;
}
.post-card {
  display: flex; flex-direction: column; height: 100%;
  border: 1px solid var(--hairline); border-radius: var(--radius-lg);
  background: #fff; color: var(--body); text-decoration: none;
  overflow: hidden;
  transition: border-color .15s ease;
}
.post-card:hover { border-color: var(--brand); }
.post-card__media { display: block; aspect-ratio: 16 / 10; overflow: hidden; }
.post-card__media img { width: 100%; height: 100%; object-fit: cover; }
.post-card__body { display: block; padding: var(--sp-5); }
.post-card__tag {
  display: inline-block; margin-bottom: var(--sp-3);
  font-size: var(--fs-caption); font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; color: var(--brand-dim);
}
.post-card__title { display: block; margin-bottom: var(--sp-3); font-size: var(--fs-h4); }
.post-card:hover .post-card__title { color: var(--brand-dim); }
.post-card__text { display: block; font-size: var(--fs-sm); }
.post-card__meta {
  display: block; margin-top: var(--sp-4);
  font-size: var(--fs-caption); color: var(--muted);
}

.article__meta {
  display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-5);
  margin: 0 0 var(--sp-6);
  font-size: var(--fs-caption); color: var(--muted);
}
.article__cover { margin: 0 0 var(--sp-6); }
.article__cover img { width: 100%; height: auto; border-radius: var(--radius-lg); }
.article__cover figcaption,
.article__figure figcaption {
  margin-top: var(--sp-2);
  font-size: var(--fs-caption); color: var(--muted);
}
.article__body > p { margin-bottom: var(--sp-4); }
.article__title { margin: var(--sp-8) 0 var(--sp-4); font-size: var(--fs-h3); }
.article__subtitle { margin: var(--sp-6) 0 var(--sp-3); font-size: var(--fs-h4); }
.article__list { margin: var(--sp-4) 0 var(--sp-5); padding-left: var(--sp-6); display: grid; gap: var(--sp-3); }
.article__list--ol li::marker { color: var(--brand); font-weight: 600; }
.article__list--ul { list-style: none; padding-left: 0; }
.article__list--ul li { position: relative; padding-left: var(--sp-6); }
.article__list--ul li::before {
  content: ''; position: absolute; left: 0; top: .55em;
  width: 8px; height: 8px; border-radius: 50%; background: var(--brand);
}
.article__table { margin: var(--sp-5) 0 var(--sp-4); }
.article__note { margin: var(--sp-5) 0; }
.article__figure { margin: var(--sp-6) 0; }
.article__figure img { width: 100%; height: auto; border-radius: var(--radius-lg); }
/* Вертикальный снимок во всю ширину колонки вырастает на полтора экрана — держим его уже. */
.article__figure--portrait { max-width: 460px; margin-inline: auto; }
.article__cta {
  display: flex; flex-wrap: wrap; gap: var(--sp-4); align-items: center;
  justify-content: space-between;
  margin: var(--sp-6) 0;
  padding: var(--sp-5) var(--sp-6);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-lg); background: var(--surface);
}
.article__cta-text { margin: 0; flex: 1 1 320px; }

@media (max-width: 700px) {
  .posts { grid-template-columns: 1fr; gap: var(--sp-5); }
  .article__cta { padding: var(--sp-5); }
}

/* Обложка статьи: кадры проекта бывают вертикальными (съёмка станции в рост),
   и без ограничения пропорций такая обложка занимает три экрана. */
.article__cover img {
  aspect-ratio: 16 / 9; object-fit: cover; object-position: center 40%;
  max-height: 460px;
}

/* Список сразу после абзацев: без отступа первый пункт прилипает к последней
   строке текста. Правило общее — раньше оно стояло только для колонок карточки. */
.prose + .points { margin-top: var(--sp-5); }

/* Фото в карточке каталога резалось сверху и снизу.
   Кадр был флексом с aspect-ratio, а картинка внутри — flex-элементом: при
   вертикальном снимке она не сжималась до квадрата и уезжала под overflow.
   Теперь кадр — обычный блок фиксированной высоты, а вписыванием занимается
   сама картинка через object-fit. */
.product__media { display: block; height: 280px; aspect-ratio: auto; }
.product__media img { width: 100%; height: 100%; object-fit: contain; }

/* Вкладки карточки товара. Имитация табов интернет-магазина:
   содержимое остаётся на странице целиком, вкладка — якорь на свой блок.
   Так и человеку понятнее, и текст полностью виден поисковику. */
.tabs {
  display: flex; flex-wrap: wrap; gap: var(--sp-1);
  margin: var(--sp-7) 0 0;
  border-bottom: 1px solid var(--hairline);
}
.tabs__item {
  padding: var(--sp-3) var(--sp-5);
  font-size: var(--fs-sm); font-weight: 600;
  color: var(--muted); text-decoration: none; white-space: nowrap;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}
.tabs__item:hover { color: var(--body); }
.tabs__item.is-active { color: var(--ink); border-bottom-color: var(--brand); }

@media (max-width: 860px) {
  /* Лентой с прокруткой: восемь вкладок в столбик занимают целый экран. */
  .tabs { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; }
  .tabs::-webkit-scrollbar { display: none; }
  .tabs__item { padding: var(--sp-3) var(--sp-4); }
}

/* Файл документации: иконка с подписью PDF. Подчёркивание при
   наведении — только на названии, хотя кликабельна вся карточка. */
.files__icon {
  flex: 0 0 auto; display: flex; flex-direction: column; align-items: center;
  gap: var(--sp-1); color: var(--brand);
}
.files__icon svg { width: 40px; height: 40px; }
.files__type {
  font-family: var(--font-mono); font-size: .75rem; font-weight: 700;
  letter-spacing: .08em; color: var(--muted);
}
.files__link:hover .files__title { text-decoration: underline; }
.files__link:hover .files__text,
.files__link:hover .files__size { text-decoration: none; }

/* «Читайте также» — ссылки на смежные страницы с миниатюрой.
   Заменил простой список: у ссылки без картинки нет якоря для глаза, и такие
   блоки читатель пролистывает. */
/* Разделы каталога: те же карточки, что «Читайте также», но плотнее — их двенадцать. */
.read-also--sections { --read-also-cols: 3; }

.read-also {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: var(--sp-4);
  /* Нижнее поле нужно: под блоком идёт примечание или кнопка, и без отступа
     текст читается как подпись к последней карточке. */
  margin: var(--sp-5) 0 var(--sp-5); padding: 0; list-style: none;
}
.read-also__link {
  display: flex; gap: var(--sp-4); align-items: center; height: 100%;
  padding: var(--sp-3) var(--sp-5) var(--sp-3) var(--sp-3);
  border: 1px solid var(--hairline); border-radius: var(--radius-lg);
  background: #fff; color: var(--body); text-decoration: none;
  transition: border-color .15s ease;
}
.read-also__link:hover { border-color: var(--brand); }
.read-also__media {
  flex: 0 0 auto; width: 92px; height: 72px; overflow: hidden;
  border-radius: var(--radius-md); background: var(--surface);
}
.read-also__media img { width: 100%; height: 100%; object-fit: cover; }
.read-also__text { font-size: var(--fs-sm); font-weight: 600; }
.read-also__link:hover .read-also__text { color: var(--brand-dim); }
.read-also__text::after {
  content: '\2192'; margin-left: .4em; color: var(--brand);
  display: inline-block; transition: transform .15s ease;
}
.read-also__link:hover .read-also__text::after { transform: translateX(3px); }

@media (max-width: 700px) {
  /* Разделы каталога: те же карточки, что «Читайте также», но плотнее — их двенадцать. */
.read-also--sections { --read-also-cols: 3; }

.read-also { grid-template-columns: 1fr; }
}

/* ===========================================================================
   ТИПОГРАФИКА ТЕКСТОВЫХ БЛОКОВ
   Строка во весь экран читается плохо, но и обрезать её справа нельзя — рядом
   с текстом появляется пустое поле. Поэтому колонка текста ограничена шириной
   узкого контейнера и стоит по центру блока, а таблицы, изображения и листинги
   остаются во всю ширину секции.
   Карточка товара — исключение: там текст идёт в узкой колонке рядом с фото.
   =========================================================================== */
/* Колонка ограничивается целиком, а не по абзацам: тогда заголовки, текст,
   таблицы и картинки идут по одному левому краю. */
.prose,
.article__body {
  max-width: var(--wrap-narrow);
  margin-inline: auto;
  /* Нижнее поле: под текстом обычно идут карточки, таблица или галерея, и без
     него вводный абзац читается как подпись к ним. */
  margin-bottom: var(--sp-6);
}

/* Сетки карточек, колонка рядом с фото товара и карточка выставки живут во всю ширину секции. */
.prose.catalog__text,
.prose.product-page__text,
.prose.event__text {
  max-width: none;
}

/* Раздел каталога с развёрнутым текстом: колонка ограничена, как в статье. */
.prose.catalog__text--doc { max-width: var(--wrap-narrow); }

/* Таблица не обтекает картинку с обтеканием: в узкой колонке её столбцы схлопываются. */
.prose .table-scroll,
.article__body .table-scroll { clear: both; }

.product-page__text p,
.table-scroll,
.article__table,
.post__table,
.prose .table-scroll,
.prose figure {
  max-width: none;
}

/* Заголовок внутри текстового блока: без верхнего отступа он прилипает к
   предыдущему абзацу — так было на разделах каталога. */
.catalog__text h2,
.catalog__text h3,
.prose h2,
.prose h3,
.article__body h2,
.article__body h3 {
  margin-top: var(--sp-8);
}
.catalog__text h3,
.prose h3,
.article__body h3 { margin-top: var(--sp-6); }

.catalog__text > :first-child,
.prose > :first-child,
.article__body > :first-child { margin-top: 0; }

/* Заголовок карточки живёт не в текстовом потоке: правило выше отодвигало его
   вниз, и обтекающая иконка вставала отдельной строкой над заголовком. */
.catalog__text .card__title,
.prose .card__title,
.article__body .card__title { margin-top: 0; }

/* Текст после блока с цифрами: рамка стоит вплотную к следующему абзацу. */
.stats--framed + .prose,
.stats--framed + .section__head { margin-top: var(--sp-7); }

/* Квиз ужат по ширине: 1180px растягивали плитки в ленту. */
.quiz { max-width: 993px; }

/* Заголовок таблицы сравнения стоит сразу после текста раздела и прилипал к
   последнему абзацу. */
.catalog__compare-title,
.catalog__faq-title { margin-top: var(--sp-8); }

/* Контакты: тот же список фактов, но в две колонки и с обычным начертанием у длинных значений */
.contacts-facts { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-5) var(--sp-8); }

/* Форма обращения на странице контактов: три поля в ряд, сообщение во всю ширину. */
.contacts-form { margin-top: var(--sp-8); }
.contacts-form h2 { margin-bottom: var(--sp-2); }
.contacts-form .form { display: grid; gap: var(--sp-4); margin-top: var(--sp-5); }
.contacts-form .form .btn { justify-self: start; }

/* Заголовок блока отдела зарядных станций стоит над списком фактов и не должен
   отрываться от него: сверху воздух от тегов-перелинковки, снизу — вплотную. */
.contacts-dept__head { margin-top: var(--sp-7); margin-bottom: var(--sp-5); }

/* Карточки подразделений завода: строка контакта — иконка и ссылка в одну
   линию, высота строки сбита под размер иконки, чтобы телефоны шли ровным
   столбцом. Заголовок карточки здесь короткий, и резерв в две строки не нужен. */
.contacts-dept .card__title { min-height: 0; }
.contacts-dept .note { margin-bottom: var(--sp-4); }
.contacts-dept__line {
  display: flex; align-items: center; gap: var(--sp-2);
  margin: 0 0 var(--sp-2); font-weight: 600;
}
.contacts-dept__line:last-child { margin-bottom: 0; }
.contacts-dept__icon { flex: none; color: var(--brand); }

.contacts-facts dd { font-weight: 500; }
.contacts-facts a { color: inherit; }
.contacts-facts__phones { font-size: var(--fs-h3); font-weight: 700; line-height: 1.45; font-variant-numeric: tabular-nums; }
@media (max-width: 720px) { .contacts-facts { grid-template-columns: 1fr; } }

/* Таблица сравнения токов идёт по ширине текстового блока и отделена от него отступом. */
.catalog__compare-scroll {
  max-width: var(--wrap-narrow);
  margin: var(--sp-7) auto 0;
}

/* Пара снимков с обтеканием: миниатюры открываются общим просмотрщиком. */
.media-float--pair { display: grid; gap: var(--sp-3); }
.media-float--pair a { display: block; }

/* Две комплектации станции: цены не должны переноситься по цифрам. */
.product-kits { margin-top: var(--sp-6); }
.product-kits__title { font-size: var(--fs-h3); margin-bottom: var(--sp-4); }
/* Таблица стоит в колонке рядом с фотографией: 752px в 623px не помещались, и
   правый столбец уезжал за край. Ширину задаём долями,
   заголовки переносим по словам — суммы при этом остаются в одну строку. */
/* Доли колонок — только на широком экране. На телефоне таблица по-прежнему
   уезжает в горизонтальную прокрутку обёртки: при фиксированных долях сумма
   «2 200 000 ₽» не помещалась в свои 83px. */
@media (min-width: 901px) {
  .product-kits__table { table-layout: fixed; width: 100%; }
  .product-kits__table thead th,
  .product-kits__table tbody th,
  .product-kits__table tbody td { white-space: normal; }
  /* Суммы в одну строку: разорванное по пробелу «3 200 000 ₽» не читается. */
  .product-kits__table td:nth-child(2), .product-kits__table td:nth-child(4) { white-space: nowrap; }
  .product-kits__table th, .product-kits__table td { padding-inline: var(--sp-3); }
  .product-kits__table thead th:nth-child(1) { width: 24%; }
  .product-kits__table thead th:nth-child(2) { width: 22%; }
  .product-kits__table thead th:nth-child(3) { width: 27%; }
  .product-kits__table thead th:nth-child(4) { width: 27%; }
}
.product-kits .note { margin-top: var(--sp-3); }

/* Документы позиции на первом экране карточки: выписка из реестра и декларация. */
.product-docs { list-style: none; margin: var(--sp-5) 0 0; padding: 0; display: grid; gap: var(--sp-2); }
.product-docs__link {
  display: flex; gap: var(--sp-3); align-items: center;
  padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--hairline); border-radius: var(--radius-md);
  background: var(--surface); color: var(--ink-strong);
}
.product-docs__link:hover { border-color: var(--brand); }
.product-docs__icon { flex: 0 0 auto; color: var(--brand); }
.product-docs__title { display: block; font-size: var(--fs-sm); font-weight: 600; }
.product-docs__note { display: block; font-size: var(--fs-caption); color: var(--muted); }

/* ===== 30. ВОЗДУХ МЕЖДУ СОСЕДНИМИ БЛОКАМИ =====================================
   Текст или заголовок, идущий сразу за сеткой карточек, лентой, списком шагов
   или рамкой с цифрами, прилипал к ним вплотную: у самих блоков нижнего поля
   нет, а верхнее у абзаца съедалось правилом «первый элемент без отступа».
   Заказчик ловил это на боевом сайте по одной странице за раз,
   поэтому правило общее, а не точечное. Проверяется скриптом: он обходит карту
   сайта и ищет соседей с разрывом меньше 16px. */
.grid + .prose,
.grid + .note,
.grid + h2,
.grid + h3,
.grid + .section__head,
.products + .prose,
.products + .note,
.roadmap + .prose,
.roadmap + .article__body,
.roadmap + .note,
.roadmap + h2,
.carriers + .note,
.related-grid + .note,
.gallery + h2,
.list-check + h2,
.prose + .section__head,
.prose + .checklist,
.prose + .roadmap,
.prose.legal + .note,
.stats + .prose,
.stats + .note,
.benefits + .prose,
.benefits + .note,
.table-scroll + .prose { margin-top: var(--sp-7); }

/* Текст сразу под таблицей: у таблицы нижнего поля нет, и абзац вставал
   вплотную к последней линии — читалось как продолжение ячейки.
   Правило общее, а не для конкретной страницы.

   ⚠️ Отступ задан самой обёртке, а не соседу через `+`: под таблицей
   main.js печатает указатель прокрутки `.table-scroll__bar--bottom`, и
   селектор `.table-scroll + p` не срабатывает — соседей разделяет он. */
.table-scroll { margin-bottom: var(--sp-6); }

/* Служебная строка шапки на очень узких экранах: «Санкт-Петербург» вместе с «Контактами» и
   значком Telegram не помещался в 320px и распирал страницу. У строки стоит
   nowrap, поэтому названию города нужен запасной план — обрезка эллипсисом (правило §3.14.4). */
@media (max-width: 400px) {
  .header__top .wrap { gap: var(--sp-3); }
  .city { min-width: 0; flex: 0 1 auto; }
  .city__name { overflow: hidden; text-overflow: ellipsis; }
  /* Осознанное отклонение от правила «видимый текст не мельче 13px»: в главной строке шапки знак, дескриптор, номер и
     кнопка меню при 13px не помещаются — номер налезает на дескриптор
     (проверено замером: правый край дескриптора 203px при начале контактов на
     190px). На 401px и шире кегль штатный. */
  .header__phone { font-size: 0.6875rem; }
  /* Дескриптор ступенью мельче номера: на 360px номер обрезался
     даже при равных 11px — подпись уступает ширину номеру. */
  .logo__text { font-size: 0.625rem; }
}

/* Совсем узкие экраны: дескриптор накладывался на номер даже при 11px (замер на
   320px: край надписи 185px, контакты с 150px). Надпись уступает место номеру —
   знак Elli на месте, а «Электрозарядные станции» есть в первом экране. */
@media (max-width: 340px) {
  .logo__text { display: none; }
}

/* Карточки доводов на светлом фоне: главное в абзаце выделено фирменным
   зелёным. */
.cards--hl .card p b { color: var(--brand-dim); font-weight: 700; }

/* Крупные значки разъёмов в статье: векторные, поэтому
   увеличение не мылит; насыщенный чёрный вместо серого растра. */
.connectors--lg { justify-content: center; gap: var(--sp-7); margin-top: var(--sp-5); }
.connectors--lg .connectors__item img { height: 100px; }
.connectors--lg .connectors__item { font-size: var(--fs-body, 1rem); font-weight: 600; color: var(--ink, #111); }
@media (max-width: 480px) { .connectors--lg { gap: var(--sp-5); } .connectors--lg .connectors__item img { height: 72px; } }

/* Миниатюра-значок (SVG разъёма) в «Читайте также»: вписываем целиком, а не
   обрезаем по кадру — растровые значки 52px растягивались и мылились. */
.read-also__media img[src*=".svg"] { object-fit: contain; padding: 8px; background: #fff; }

/* Зарядный хаб на странице дилеров: блок в рамке на ту же ширину и
   сетку, что три карточки объектов ниже — текст в первой колонке, два кадра
   объекта во второй и третьей. */
.hub-offer {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp-5);
  align-items: stretch;
  margin: 0 0 var(--sp-7); padding: var(--sp-5);
  border: 1px solid var(--hairline); border-radius: var(--radius-lg); background: #fff;
}
.hub-offer__text h3 { margin-top: 0; }
.hub-offer__text p { margin: 0 0 var(--sp-3); }
.hub-offer__text p:last-child { margin-bottom: 0; }
.hub-offer__photo { display: block; border-radius: var(--radius-md); overflow: hidden; }
.hub-offer__photo img { display: block; width: 100%; height: 100%; object-fit: cover; }
@media (max-width: 900px) {
  .hub-offer { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .hub-offer__text { grid-column: 1 / -1; }
  .hub-offer__photo { aspect-ratio: 4 / 3; }
}
@media (max-width: 560px) {
  .hub-offer { grid-template-columns: minmax(0, 1fr); padding: var(--sp-4); }
}

/* Заголовок страниц темы «НПО «Электромашина»: на 60px длинные названия с юрлицом
   рвались на две-три строки. 40px остаётся крупнее H2 (33px); на телефоне действует общая
   ступень --fs-display, она и так меньше. */
.h1--compact { font-size: min(var(--fs-display), 2.5rem); line-height: 1.15; }

/* Варианты поставок: крупные карточки с фото,
   три в ряд на широком экране. Цифры выделены тем же зелёным, что в тексте страниц. */
/* Флекс, а не сетка: неполный последний ряд встаёт по центру, а не прижимается влево. */
.supply-cards {
  display: flex; flex-wrap: wrap; justify-content: center; gap: var(--sp-5);
  margin: 0; padding: 0; list-style: none;
}
.supply-card { flex: 0 1 calc((100% - 2 * var(--sp-5)) / 3); min-width: 0; }
.supply-card {
  display: flex; flex-direction: column; overflow: hidden;
  background: var(--canvas); border: 1px solid var(--hairline); border-radius: var(--radius-lg);
}
.supply-card__img { display: block; width: 100%; aspect-ratio: 16 / 10; height: auto; object-fit: cover; }
.supply-card__body { display: flex; flex-direction: column; flex: 1; padding: var(--sp-5); }
.supply-card__title { margin: 0 0 var(--sp-3); font-size: var(--fs-h4); }
.supply-card__body p { margin: 0 0 var(--sp-3); }
.supply-card__body b { color: var(--brand-dim); }
/* Опорный факт карточки прижат к низу: у карточек разной длины текста он стоит на одной линии. */
.supply-card__body .supply-card__fact { margin: auto 0 0; padding-top: var(--sp-3); border-top: 1px solid var(--hairline); font-size: var(--fs-sm); }
@media (max-width: 1000px) { .supply-card { flex-basis: calc((100% - var(--sp-5)) / 2); } }
@media (max-width: 620px)  { .supply-card { flex-basis: 100%; } }

/* Четыре шага в ряд: у поставки для сети шагов четыре, и в сетке на три последний повисал отдельной строкой. */
.steps--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 1000px) { .steps--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 620px)  { .steps--4 { grid-template-columns: minmax(0, 1fr); } }

/* ===== Служебный раздел /service =====
   Внутренние отчёты для заказчика: закрыты паролем, оформление рабочее. */
.service-menu { margin: var(--sp-5) 0 0; padding: 0; list-style: none; display: grid; gap: var(--sp-4); }
.service-menu__link { font-size: var(--fs-h4); font-weight: 700; color: var(--brand-dim); }
.registry-stats {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr)); gap: var(--sp-3);
  margin: var(--sp-5) 0 var(--sp-4);
}
.registry-stats__item { padding: var(--sp-4); border: 1px solid var(--hairline); border-radius: var(--radius); background: var(--canvas); }
.registry-stats__item b { display: block; font-size: 2rem; line-height: 1.1; color: var(--ink-strong); }
.registry-stats__item span { font-size: var(--fs-sm); color: var(--muted); }
.registry-nav { margin: 0; }
/* заголовок раздела реестра и ссылка «Скачать опросник» справа */
.registry-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--sp-2) var(--sp-4); }
.registry-head h2 { margin-bottom: 0; }
.registry-head__file { font-weight: 700; white-space: nowrap; }
.registry-legend { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); margin: 0 0 var(--sp-4); }
.registry-table .badge { position: static; white-space: nowrap; }
.registry-table__url { display: block; font-size: var(--fs-caption); color: var(--muted); }
.registry-table__date { white-space: nowrap; }

/* Оформленные блоки внутри текстовой колонки раздела каталога. Правило «.prose h3 — отступ сверху» отодвигало название шага
   от номера в кружке, а абзац после шагов и цифр прилипал к ним. */
.prose .roadmap { margin: var(--sp-6) 0; }
.prose .roadmap__title { margin-top: 0; }
.prose .roadmap + p,
.prose .stats--framed + p,
.prose .checklist + p { margin-top: var(--sp-6); }
.prose .stats--framed { margin-block: var(--sp-6); }
/* Шаги сразу после вводного абзаца (блок агентского договора на /dileram) прилипали к нему. */
p + .roadmap { margin-top: var(--sp-6); }
.roadmap + h3 { margin-top: var(--sp-8); }

/* ===== Отчёт о работах (/report) ===== */
.report-tabs { margin: 0 0 var(--sp-6); }
.report-picker { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--sp-3); margin: 0 0 var(--sp-6); }
.report-picker__label { display: flex; flex-direction: column; gap: var(--sp-1); font-size: var(--fs-sm); color: var(--muted); }
.report-picker__label select { min-height: 44px; font-size: 1rem; padding: 0 var(--sp-3); border: 1px solid var(--hairline); border-radius: var(--radius); background: var(--canvas); color: var(--ink); }
.report-picker__step { display: inline-flex; align-items: center; justify-content: center; min-width: 44px; min-height: 44px; border: 1px solid var(--hairline); border-radius: var(--radius); color: var(--ink); text-decoration: none; font-size: 1.25rem; }
.report-day { margin-top: 0; }
.report-summary { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr)); gap: var(--sp-4); margin: 0 0 var(--sp-7); }
.report-summary__card { min-width: 0; padding: var(--sp-5); border: 1px solid var(--hairline); border-radius: var(--radius); background: var(--canvas); }
.report-summary__head { display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--sp-2); margin: 0 0 var(--sp-3); }
.report-summary__head span { color: var(--muted); font-size: var(--fs-sm); }
.report-summary__card ul { margin: 0; padding-left: 1.2em; }
.report-summary__card li { margin-bottom: var(--sp-2); }
.report-table__time { white-space: nowrap; font-variant-numeric: tabular-nums; }
.report-project { display: inline-block; padding: 2px 8px; border-radius: var(--radius); background: var(--surface-2); font-size: var(--fs-caption); font-weight: 600; color: var(--ink-strong); white-space: nowrap; }
.report-project--ptzem { background: var(--report-ptzem); }
.report-updated { color: var(--muted); }

/* Страница товарного знака: снимок записи реестра слева, сведения справа */
.tm-reg { display: grid; grid-template-columns: 260px minmax(0, 1fr); gap: var(--sp-5); align-items: start; margin-bottom: var(--sp-6); }
.tm-reg__media img { display: block; width: 100%; height: auto; border: 1px solid var(--line); border-radius: var(--radius); }
.tm-reg__body p { margin-top: var(--sp-3); }
@media (max-width: 700px) { .tm-reg { grid-template-columns: minmax(0, 1fr); } .tm-reg__media { max-width: 260px; } }

/* Калькулятор лизинга (/lizing): ползунки слева, расчёт справа */
.calc-leasing { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 420px); gap: var(--sp-6); align-items: start; }
.calc-leasing__field { margin-bottom: var(--sp-5); }
.calc-leasing__label { display: block; font-size: var(--fs-sm); color: var(--muted); }
.calc-leasing__value { display: block; margin: var(--sp-1) 0 var(--sp-2); font-size: var(--fs-h3); font-weight: 600; font-variant-numeric: tabular-nums; }
.calc-leasing__field input[type="range"] { width: 100%; accent-color: var(--brand); min-height: 44px; }
.calc-leasing__presets { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin: var(--sp-2) 0 0; }
/* Кнопки с готовой ценой стоят на тёмной секции: базовый .btn--outline тёмного цвета на ней не виден */
.calc-leasing__presets .btn.is-active { border-color: var(--brand); color: var(--brand); }
.calc-leasing__result { padding: var(--sp-5); border: 1px solid var(--hairline); border-radius: var(--radius); background: var(--surface); }
.section--surface .calc-leasing__result { background: var(--canvas); }
.calc-leasing__main { margin: 0 0 var(--sp-4); }
.calc-leasing__main-label { display: block; font-size: var(--fs-sm); color: var(--muted); }
.calc-leasing__main-value { display: block; margin-top: var(--sp-1); font-size: clamp(28px, 4vw, 40px); font-weight: 700; color: var(--brand); font-variant-numeric: tabular-nums; }
.calc-leasing__rows { margin: 0; }
.calc-leasing__rows > div { display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--sp-2); padding: var(--sp-2) 0; border-top: 1px solid var(--hairline); }
.calc-leasing__rows dt { color: var(--muted); font-size: var(--fs-sm); }
.calc-leasing__rows dd { margin: 0; font-weight: 600; font-variant-numeric: tabular-nums; }
.calc-leasing__note { margin: var(--sp-4) 0 0; font-size: var(--fs-sm); color: var(--muted); }
.calc-leasing__actions { margin: var(--sp-5) 0 0; }
@media (max-width: 900px) { .calc-leasing { grid-template-columns: minmax(0, 1fr); } }

/* Кнопка внутри плитки направления на главной: отступ от текста */
.post-card__action { display: block; margin-top: var(--sp-4); }

/* ptzem: номер 8 800 200-64-53 длиннее, а знак шире, чем у elli, поэтому на телефоне до 400px дескриптор
   уступает место номеру целиком, и номер возвращается к штатным 13px (правило «видимый текст не мельче 13px»). */
@media (max-width: 400px) {
  .logo__text { display: none; }
  .header__phone { font-size: 0.8125rem; }
}

/* ===== ПЕРВЫЙ ЭКРАН ГЛАВНОЙ: ТРИ РАВНОПРАВНЫХ БАННЕРА =====
   Границы баннеров — три параллельные линии с наклоном вправо («/»): верхний край панели сдвинут вправо на --sk,
   нижний — нет. Панели наезжают друг на друга на (--sk - --tri-gap), поэтому между ними остаётся косая полоса
   цвета подложки — она и есть граница, толщиной в волосяную линию. Панели равной
   ширины и без акцента: под курсором только приближается картинка. На телефоне панели идут столбцом,
   границы — наклонные горизонтали. */
.tri {
  position: relative; isolation: isolate;
  display: flex; align-items: center;
  /* Ровно видимая область под шапкой. Раньше было clamp(520px, 100dvh − --header-h, 760px): потолок 760px и
     высота только основной строки шапки. В окне выше ~880px (Firefox с меньшими панелями, большой монитор)
     первый экран заканчивался раньше края и снизу выглядывали цифры следующей секции.
     Высоту шапки целиком пишет main.js в --header-total. */
  min-height: max(520px, calc(100dvh - var(--header-total, 119px)));
  padding-block: var(--sp-8);
  background: var(--dark); color: var(--on-dark); overflow: hidden;
}

/* Фон первого экрана: заставка лежит всегда, видео подключает main.js и только на
   широком экране — на телефоне 4 МБ в мобильный трафик не отдаём. Видео проявляется
   по событию canplay, до этого виден кадр. */
.tri__poster, .tri__poster img, .tri__video {
  position: absolute; inset: 0; z-index: 0;
  width: 100%; height: 100%; object-fit: cover;
}
.tri__video { opacity: 0; transition: opacity .8s; }
.tri__video.is-ready { opacity: 1; }
.tri__veil {
  position: absolute; inset: 0; z-index: 1;
  background: linear-gradient(to bottom, rgba(10,13,14,.72) 0%, rgba(10,13,14,.62) 45%, rgba(10,13,14,.86) 100%);
}
.tri__inner { position: relative; z-index: 2; }

/* Заголовок первого экрана и подзаголовок: одно предложение, цифры и главное — фирменным цветом. */
.tri__head { margin-bottom: var(--sp-7); max-width: 62ch; }
/* Заголовок держим в одну строку: кегль тянется от ширины экрана,
   а ниже 700px перенос разрешаем — иначе на телефоне строка не помещается. */
.tri__head h1 { margin: 0 0 var(--sp-3); color: var(--on-dark); font-size: clamp(1.75rem, 3.6vw, 3rem); white-space: nowrap; }
@media (max-width: 700px) { .tri__head h1 { white-space: normal; } }
.tri__lead { margin: 0; font-size: var(--fs-lead, 1.0625rem); line-height: var(--lh-snug); color: var(--on-dark-2); }
.tri__lead b { color: var(--brand-light); font-weight: 700; }

/* Три направления: заголовки стоят на одной линии независимо от длины описания,
   поэтому колонки — сетка, а не блоки разной высоты.
   Разделителей между колонками нет — их достаточно отделяет воздух. */
.tri__stage { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-6); }
.tri__panel { padding: 0; }
.tri__title { margin: 0 0 var(--sp-3); font-size: clamp(1.25rem, 1.8vw, 1.75rem); line-height: var(--lh-tight); letter-spacing: var(--ls-h3); text-wrap: balance; }
.tri__title a { color: var(--on-dark); text-decoration: none; }
/* Иконка раздела слева от заголовка */
.tri__title { display: flex; align-items: center; gap: var(--sp-3); }
.tri__icon { flex: none; color: var(--brand); }
.tri__title a:hover { color: var(--brand-light, var(--brand)); }
.tri__text { margin: 0; font-size: var(--fs-sm); line-height: var(--lh-snug); color: var(--on-dark-2); }

/* Преимущества стоят ниже направлений и относятся ко всему заводу, а не к отдельному
   из них, поэтому идут одной строкой во всю ширину. */
.tri__facts { margin-top: var(--sp-8); }
/* Кнопка подсказки на телефоне — полноценная цель для пальца (норма 44×44). */
@media (max-width: 900px) {
  .tri__facts .hero__fact-toggle { width: 44px; height: 44px; margin: calc(var(--sp-2) * -1); }
}

@media (max-width: 899px) {
  .tri { min-height: 0; padding-block: var(--sp-7); }
  .tri__stage { grid-template-columns: 1fr; gap: var(--sp-6); }
  .tri__head { margin-bottom: var(--sp-6); }
  .tri__facts { grid-template-columns: 1fr; gap: var(--sp-4); margin-top: var(--sp-7); }
  .tri__facts li { flex-direction: row; align-items: flex-start; text-align: left; }
}

/* Появление при загрузке: колонки проявляются по очереди. Движение выключается,
   если человек попросил уменьшить анимацию. */
@keyframes tri-in { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: none; } }
.tri__panel { animation: tri-in .6s cubic-bezier(.2,.7,.2,1) both; animation-delay: calc(var(--i, 0) * .12s + .1s); }

@media (prefers-reduced-motion: reduce) {
  .tri__panel { animation: none; }
  .tri__video { display: none; }
}

/* Раздел ЖД: сетка карточек списком без маркеров; десять плиток идут по пять в ряд, на средних экранах по две — без карточки-сироты в последнем ряду. */
.grid--list { list-style: none; margin: 0; padding: 0; }
.grid--5 { grid-template-columns: repeat(5, minmax(0, 1fr)); gap: var(--sp-5); }
.grid--5 .post__title { font-size: 1.0625rem; margin: var(--sp-4) var(--sp-4) var(--sp-2); }
.grid--5 .post__text { margin: 0 var(--sp-4); }
.grid--5 .post .post__action { margin: var(--sp-4) var(--sp-4) var(--sp-5); }
@media (max-width: 1200px) { .grid--5 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 640px) { .grid--5 { grid-template-columns: minmax(0, 1fr); } }
.grid--list > li { display: flex; }
.grid--list > li > .post { flex: 1; }
/* «Читайте также» на узком экране: длинное слово в подписи («электропневматический») рядом с миниатюрой распирало страницу на 3px. */
.read-also__text { min-width: 0; overflow-wrap: anywhere; hyphens: auto; }
/* Длинное название изделия в H1 карточки («Быстродействующие») на телефоне рвалось без переноса. */
@media (max-width: 640px) { .product-page__info h1 { font-size: 1.75rem; hyphens: auto; } }

/* ===== Светлая шапка и меню-кнопки =====
   Шапка белая: тёмно-оранжевое на чёрном выглядит мрачно. Цвета шапки переопределены токенами внутри
   .header — все правила выше (ссылки, телефон, выпадающие списки, бургер-панель) берут светлую палитру сами.
   «Каталог» и «Услуги» — кнопки по образцу Ozon: значок из четырёх квадратов, по клику — крестик; панель
   открывается только по клику, без задержек. Обводка у кнопок тёмная, а не белая, как в задании: белая линия на
   белой шапке не видна. Кнопка прозрачная и не спорит с оранжевой «Заказать звонок». */
.header {
  --header-bg:     #FFFFFF;
  --on-dark:       var(--ink-strong);
  --on-dark-2:     var(--body);
  --on-dark-3:     var(--muted);
  --hairline-dark: var(--hairline);
  --dark-2:        #FFFFFF;
  --dark-3:        #FFFFFF;
  position: relative; z-index: 55;
  border-bottom: 1px solid var(--hairline);
}
.header__top { background: var(--surface); }
.nav__sub a:hover { background: var(--surface); color: var(--brand-dim); }
.nav__item:has(.nav__sub) > .nav__link { cursor: pointer; }
.header__main .wrap { position: relative; }

.menu-btn {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  height: 44px; padding: 0 var(--sp-4);
  font: 600 var(--fs-base)/1 var(--font); color: var(--ink-strong);
  background: transparent; border: 1.5px solid var(--hairline-strong); border-radius: 10px;
  cursor: pointer; white-space: nowrap;
}
.menu-btn:hover { border-color: var(--ink-strong); }
.menu-btn[aria-expanded="true"] { border-color: var(--ink-strong); background: var(--surface); }
.menu-btn__icon { flex: none; }
.menu-btn__close { display: none; }
.menu-btn[aria-expanded="true"] .menu-btn__grid { display: none; }
.menu-btn[aria-expanded="true"] .menu-btn__close { display: inline; }
.nav__item--mega { position: static; display: flex; align-items: center; }
.nav__list { align-items: center; }

/* Панель: во всю ширину контейнера (от логотипа до кнопки звонка), высота — 85 % места под шапкой
   (--mega-h считает main.js), прокрутка внутри колонок; страница под панелью затемнена. */
.mega {
  position: absolute; top: 100%; left: 0; right: 0; z-index: 60;
  height: var(--mega-h, 70vh);
  display: grid; grid-template-columns: minmax(260px, 340px) 1fr;
  background: #FFFFFF; color: var(--ink-strong);
  border-radius: 0 0 var(--radius-lg) var(--radius-lg);
  box-shadow: 0 24px 48px rgba(10,13,14,.18);
  overflow: hidden;
}
.mega[hidden] { display: none; }
.mega__side { overflow-y: auto; padding: var(--sp-4); border-right: 1px solid var(--hairline); }
.mega__hubs { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.mega__hub {
  display: block; padding: 10px var(--sp-4); border-radius: 10px;
  font-size: var(--fs-sm); font-weight: 500; line-height: 1.3; color: var(--ink-strong);
}
.mega__hub:hover, .mega__hub.is-current { background: var(--surface); color: var(--brand-dim); text-decoration: none; }
/* Стрелка вправо у раздела: показывает, что справа откроются его страницы. */
.mega__hub { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); }
.mega__hub::after { content: ""; flex: none; width: 7px; height: 7px; border-top: 2px solid currentColor; border-right: 2px solid currentColor; transform: rotate(45deg); opacity: .45; }
.mega__hub:hover::after, .mega__hub.is-current::after { opacity: 1; }
/* Ссылка на весь раздел под списком разделов */
.mega__all { display: block; margin-bottom: var(--sp-3); padding: 10px var(--sp-4); border-bottom: 1px solid var(--hairline); font-size: var(--fs-sm); font-weight: 600; color: var(--brand-dim); }
.mega__all:hover { text-decoration: underline; }
.mega__main { overflow-y: auto; padding: var(--sp-5) var(--sp-6) var(--sp-6); }
.mega__title {
  display: inline-block; margin-bottom: var(--sp-4);
  font-size: var(--fs-h3); font-weight: 700; line-height: var(--lh-tight); letter-spacing: var(--ls-h3); color: var(--ink);
}
.mega__title:hover { color: var(--brand-dim); text-decoration: none; }
.mega__list { list-style: none; margin: 0; padding: 0; }
/* две колонки — колонками текста, а не сеткой: группа «основная услуга + её узкие» не рвётся между колонками */
.mega__list--cols { column-count: 2; column-gap: var(--sp-7); }
.mega__list > li { break-inside: avoid; padding-bottom: 2px; }
/* второй уровень — строкой без маркера; третий (узкие услуги под основной) — с серым кружком */
.mega__list a.mega__item { font-weight: 600; color: var(--ink-strong); }
.mega__sub { list-style: none; margin: 0 0 var(--sp-2); padding: 0; }
.mega__sub li { position: relative; padding-left: 18px; }
.mega__sub li::before { content: ""; position: absolute; left: 2px; top: 11px; width: 7px; height: 7px; border: 1.5px solid var(--muted); border-radius: 50%; background: transparent; }
.mega__list a { display: block; padding: 6px 0; font-size: var(--fs-sm); line-height: 1.35; color: var(--body); }
.mega__list .mega__sub a { padding: 3px 0; }
.mega__list a:hover { color: var(--brand-dim); text-decoration: none; }

body.is-mega-open { overflow: hidden; }
body.is-mega-open .scrim { opacity: 1; visibility: visible; }

/* Узкий экран: меню — выезжающая панель (бургер). Кнопка раскрывает список разделов прямо в ней,
   правой колонки нет: страницы раздела человек найдёт на странице раздела. */
@media (max-width: 1200px) {
  .nav__item--mega { display: block; }
  .menu-btn { width: 100%; height: auto; padding: var(--sp-4) 0; border: 0; border-radius: 0; background: none; justify-content: flex-start; }
  .menu-btn[aria-expanded="true"] { background: none; }
  .mega { position: static; height: auto; display: block; box-shadow: none; border-radius: 0; background: none; }
  .mega__side { border: 0; padding: 0 0 var(--sp-3); overflow: visible; }
  .mega__main { display: none; }
  .mega__hub.is-current { background: none; color: var(--ink-strong); }
  body.is-mega-open { overflow: hidden; }
}
/* Кнопки «Каталог» и «Услуги» стоят парой у логотипа, как у Ozon; остальные пункты уходят вправо. */
@media (min-width: 1201px) {
  .nav__list { justify-content: flex-start; gap: var(--sp-5); }
  .nav__item--mega + .nav__item:not(.nav__item--mega) { margin-left: auto; }
}
/* Панель ровно по контейнеру: от левого края логотипа до правого края кнопки звонка (поля .wrap не входят). */
@media (min-width: 1201px) { .mega { left: var(--gutter); right: var(--gutter); } }
@media (max-width: 1200px) { .nav__list { align-items: stretch; } }
/* Ссылка без href: выглядит и ведёт себя как ссылка. */
a[data-href] { cursor: pointer; }
a[data-href]:hover { text-decoration: underline; }

/* ==========================================================================
   Статьи раздела /articles

   Перенесено со статей лендинга ELLI (elli-t/assets/css/article.css) под
   оформление основного сайта. Узкая колонка текста — 760 px (65–75 знаков в
   строке), кадры и схемы шире — до 1120 px, выходят из колонки симметрично.
   Разметку печатает app/include/article.php. Содержание (.toc), «Читайте
   также» (.read-also), гармошка и полоса заявки — общие правила сайта выше.
   ========================================================================== */

:root {
  --article-col:  760px;
  --article-wide: 1120px;
}

.article-head { max-width: var(--article-col); margin: 0 auto var(--sp-6); }
.article-head h1 { margin-bottom: var(--sp-4); }
.article-head .lead { margin: 0; }
.article__meta {
  display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-5);
  margin: var(--sp-4) 0 0; font-size: var(--fs-caption); color: var(--muted);
}

.article-body { max-width: var(--article-col); margin-inline: auto; }
.article-body > p { margin: 0 0 var(--sp-4); }
.article-body h2 { margin: var(--sp-8) 0 var(--sp-4); font-size: var(--fs-h2); line-height: 1.2; scroll-margin-top: 90px; }
.article-body h3 { margin: var(--sp-6) 0 var(--sp-3); font-size: var(--fs-h4); }
.article-body > :first-child { margin-top: 0; }
.article-body a:not(.btn):not(.read-also__link) { text-decoration: underline; text-underline-offset: 3px; }
.article-body .toc { margin-top: 0; }

/* Списки: оранжевая точка или оранжевая цифра. */
.article__list { margin: var(--sp-4) 0 var(--sp-5); padding-left: var(--sp-6); display: grid; gap: var(--sp-3); }
.article__list--ol li::marker { color: var(--brand); font-weight: 700; }
.article__list--ul { list-style: none; padding-left: 0; }
.article__list--ul li { position: relative; padding-left: var(--sp-6); }
.article__list--ul li::before {
  content: ""; position: absolute; left: 0; top: .6em;
  width: 8px; height: 8px; border-radius: 50%; background: var(--brand);
}

/* Широкая вставка: выходит из колонки текста до 1120 px. */
.article-wide {
  --wide: min(var(--article-wide), calc(100vw - 2 * var(--gutter, 24px)));
  width: var(--wide); max-width: none;
}

.article-shot { margin: var(--sp-5) 0 var(--sp-6); }
.article-shot img {
  display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover;
  border-radius: var(--radius-lg); background: var(--surface);
}
.article-shot figcaption { margin-top: var(--sp-2); font-size: var(--fs-caption); color: var(--muted); }
.article-shot a { display: block; }

.article-note {
  margin: var(--sp-5) 0; padding: var(--sp-4) var(--sp-5);
  border-left: 3px solid var(--brand); background: var(--surface); border-radius: 0 var(--radius-md) var(--radius-md) 0;
}
.article-note p { margin: 0; }
.article-note p + p { margin-top: var(--sp-2); }

/* Сравнение двух вещей — две колонки фактов. */
.versus { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-5); margin: var(--sp-5) 0 var(--sp-6); }
.versus__col { padding: var(--sp-5); border: 1px solid var(--hairline); border-radius: var(--radius-lg); background: #fff; }
.versus__title { margin: 0 0 var(--sp-3); font-size: var(--fs-h4); font-weight: 700; color: var(--ink-strong); }
.versus__col p { margin: 0 0 var(--sp-3); font-size: var(--fs-sm); }
.versus__col p:last-child { margin-bottom: 0; }
@media (max-width: 700px) { .versus { grid-template-columns: 1fr; } }

/* Призыв в тексте статьи: квадрат со значком по смыслу формы, вопрос, кнопка. Без цветной полосы слева.
   */
.article__cta {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: var(--sp-5); align-items: center;
  margin: var(--sp-7) 0; padding: var(--sp-5) var(--sp-6);
  border: 1px solid var(--hairline); border-radius: var(--radius-lg); background: var(--surface);
}
.article__cta-icon {
  display: grid; place-items: center; width: 56px; height: 56px;
  border-radius: var(--radius-md); background: var(--canvas); color: var(--brand);
  box-shadow: inset 0 0 0 1px var(--hairline);
}
.article__cta-text { margin: 0; font-weight: 600; color: var(--ink-strong); }
@media (max-width: 700px) {
  .article__cta { grid-template-columns: minmax(0, 1fr); padding: var(--sp-5); gap: var(--sp-4); }
  .article__cta-icon { width: 44px; height: 44px; }
  .article__cta .btn { width: 100%; }
}

.article-body .table-scroll { margin-block: var(--sp-5) var(--sp-6); }   /* только по вертикали: боковые поля задаёт .article-wide у широкой таблицы */

.article-sources { margin: var(--sp-8) 0 0; padding-top: var(--sp-4); border-top: 1px solid var(--hairline); }
.article-body .article-sources h2 { margin: 0 0 var(--sp-3); font-size: var(--fs-sm); text-transform: uppercase; letter-spacing: .06em; color: var(--muted); }
.article-sources ol { margin: 0; padding-left: var(--sp-5); display: grid; gap: var(--sp-1); font-size: var(--fs-caption); color: var(--muted); }
.article-sources a { color: var(--muted); overflow-wrap: anywhere; }

/* Схема в статье (inline SVG): на всю широкую колонку, белая подложка. */
.article-scheme { margin: var(--sp-5) 0 var(--sp-6); }
.article-scheme svg { display: block; width: 100%; height: auto; border: 1px solid var(--hairline); border-radius: var(--radius-lg); background: #fff; }
.article-scheme figcaption { margin-top: var(--sp-2); font-size: var(--fs-caption); color: var(--muted); }

/* Плитки кодов: крупный код, что значит, где ставят. Ряд по три, на телефоне — один. */
.code-cards { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp-4); margin: var(--sp-5) 0 var(--sp-6); padding: 0; list-style: none; }
.code-card { padding: var(--sp-5); border: 1px solid var(--hairline); border-radius: var(--radius-lg); background: #fff; }
.code-card__code { display: block; margin-bottom: var(--sp-2); font-size: 1.75rem; font-weight: 700; line-height: 1; color: var(--brand-dim); }
.code-card__what { display: block; margin-bottom: var(--sp-2); font-weight: 600; color: var(--ink-strong); }
.code-card__where { display: block; font-size: var(--fs-sm); color: var(--body); }
@media (max-width: 900px) { .code-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .code-cards { grid-template-columns: minmax(0, 1fr); } }

/* Хаб статей: плитки с кадром, названием, анонсом. */
.article-tiles { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp-5); margin: var(--sp-6) 0 0; padding: 0; list-style: none; }
.article-tile { display: flex; flex-direction: column; height: 100%; border: 1px solid var(--hairline); border-radius: var(--radius-lg); overflow: hidden; background: #fff; color: var(--body); text-decoration: none; transition: border-color .15s ease; }
.article-tile:hover { border-color: var(--brand); text-decoration: none; }
.article-tile img { display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover; }
.article-tile__body { display: block; padding: var(--sp-4) var(--sp-5) var(--sp-5); }
.article-tile__title { display: block; margin-bottom: var(--sp-2); font-size: var(--fs-h4); font-weight: 700; line-height: 1.25; color: var(--ink-strong); }
.article-tile:hover .article-tile__title { color: var(--brand-dim); }
.article-tile__text { display: block; font-size: var(--fs-sm); }
@media (max-width: 900px) { .article-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .article-tiles { grid-template-columns: minmax(0, 1fr); } }

/* Расшифровщик кода IP: поле ввода или два списка, ниже — что значит каждая цифра. */
.ip-decoder { margin: var(--sp-5) 0 var(--sp-6); padding: var(--sp-6); border: 1px solid var(--hairline); border-top: 3px solid var(--brand); border-radius: var(--radius-lg); background: var(--surface); }
.ip-decoder__title { margin: 0 0 var(--sp-4); font-size: var(--fs-h4); font-weight: 700; color: var(--ink-strong); }
.ip-decoder__controls { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr) minmax(0, 1fr); gap: var(--sp-4); align-items: end; }
.ip-decoder__field { display: grid; gap: var(--sp-2); font-size: var(--fs-sm); font-weight: 600; color: var(--ink-strong); }
.ip-decoder__field .input, .ip-decoder__field select { width: 100%; }
.ip-decoder__field select { min-height: 48px; padding: 0 var(--sp-3); border: 1px solid var(--hairline-strong); border-radius: var(--radius-md); background: #fff; font: inherit; font-weight: 400; color: var(--ink); }
.ip-decoder__result { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-4); margin-top: var(--sp-5); }
.ip-decoder__part { padding: var(--sp-4) var(--sp-5); border-radius: var(--radius-md); background: #fff; border: 1px solid var(--hairline); }
.ip-decoder__part b { display: block; margin-bottom: var(--sp-1); font-size: 1.5rem; line-height: 1.1; color: var(--brand-dim); }
.ip-decoder__part span { display: block; font-size: var(--fs-sm); }
.ip-decoder__part em { display: block; margin-top: var(--sp-2); font-style: normal; font-size: var(--fs-caption); color: var(--muted); }
.ip-decoder__extra { margin: var(--sp-4) 0 0; font-size: var(--fs-sm); }
.ip-decoder__extra:empty, .ip-decoder__error:empty { display: none; }
.ip-decoder__error { margin: var(--sp-3) 0 0; font-size: var(--fs-sm); color: var(--danger); }
@media (max-width: 700px) {
  .ip-decoder { padding: var(--sp-5) var(--sp-4); }
  .ip-decoder__controls { grid-template-columns: 1fr 1fr; }
  .ip-decoder__controls .ip-decoder__field:first-child { grid-column: 1 / -1; }
  .ip-decoder__result { grid-template-columns: 1fr; }
}

/* Калькулятор допусков и посадок (статья /articles/dopuski-i-posadki): рамка и поля как у расшифровщика IP. */
.fit-calc { margin: var(--sp-5) 0 var(--sp-6); padding: var(--sp-6); border: 1px solid var(--hairline); border-top: 3px solid var(--brand); border-radius: var(--radius-lg); background: var(--surface); }
.fit-calc__title { margin: 0 0 var(--sp-4); font-size: var(--fs-h4); font-weight: 700; color: var(--ink-strong); }
.fit-calc__controls { display: grid; grid-template-columns: minmax(0, 1.3fr) minmax(0, 0.8fr) minmax(0, 1fr) minmax(0, 1fr); gap: var(--sp-4); align-items: end; }
.fit-calc__field { display: grid; gap: var(--sp-2); font-size: var(--fs-sm); font-weight: 600; color: var(--ink-strong); }
.fit-calc__field .input { width: 100%; }
.fit-calc__pair { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-2); }
.fit-calc__field select { width: 100%; min-height: 48px; padding: 0 var(--sp-2); border: 1px solid var(--hairline-strong); border-radius: var(--radius-md); background: #fff; font: inherit; font-weight: 400; color: var(--ink); }
.fit-calc__result { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp-4); margin-top: var(--sp-5); }
.fit-calc__part { padding: var(--sp-4) var(--sp-5); border-radius: var(--radius-md); background: #fff; border: 1px solid var(--hairline); }
.fit-calc__part[hidden] { display: none; }
.fit-calc__part b { display: block; margin-bottom: var(--sp-2); font-size: 1.25rem; line-height: 1.2; color: var(--brand-dim); }
.fit-calc__part span { display: block; font-size: var(--fs-sm); }
.fit-calc__part em { display: block; margin-top: var(--sp-2); font-style: normal; font-size: var(--fs-caption); color: var(--muted); }
.fit-calc__part--fit { border-color: var(--brand); }
.fit-calc__error { margin: var(--sp-3) 0 0; font-size: var(--fs-sm); color: var(--danger); }
.fit-calc__error:empty { display: none; }
@media (max-width: 900px) {
  .fit-calc__controls { grid-template-columns: 1fr 1fr; }
  .fit-calc__result { grid-template-columns: 1fr; }
}
@media (max-width: 700px) {
  .fit-calc { padding: var(--sp-5) var(--sp-4); }
}

/* Переводчик шероховатости (статья /articles/sherokhovatost-poverkhnosti) — по образцу .fit-calc. */
.sher-calc { margin: var(--sp-5) 0 var(--sp-6); padding: var(--sp-6); border: 1px solid var(--hairline); border-top: 3px solid var(--brand); border-radius: var(--radius-lg); background: var(--surface); }
.sher-calc__title { margin: 0 0 var(--sp-4); font-size: var(--fs-h4); font-weight: 700; color: var(--ink-strong); }
.sher-calc__controls { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) minmax(0, 1fr); gap: var(--sp-4); align-items: end; }
.sher-calc__field { display: grid; gap: var(--sp-2); font-size: var(--fs-sm); font-weight: 600; color: var(--ink-strong); }
.sher-calc__field .input { width: 100%; }
.sher-calc__field select { width: 100%; min-height: 48px; padding: 0 var(--sp-2); border: 1px solid var(--hairline-strong); border-radius: var(--radius-md); background: #fff; font: inherit; font-weight: 400; color: var(--ink); }
.sher-calc__result { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp-4); margin-top: var(--sp-5); }
.sher-calc__part { padding: var(--sp-4) var(--sp-5); border-radius: var(--radius-md); background: #fff; border: 1px solid var(--hairline); }
.sher-calc__part b { display: block; margin-bottom: var(--sp-2); font-size: 1.25rem; line-height: 1.2; color: var(--brand-dim); }
.sher-calc__part span { display: block; font-size: var(--fs-sm); }
.sher-calc__part em { display: block; margin-top: var(--sp-2); font-style: normal; font-size: var(--fs-caption); color: var(--muted); }
.sher-calc__part--cls { border-color: var(--brand); }
.sher-calc__proc { margin-top: var(--sp-5); }
.sher-calc__proc-title { margin: 0 0 var(--sp-2); font-size: var(--fs-sm); font-weight: 700; color: var(--ink-strong); }
.sher-calc__proc ul { margin: 0; padding: 0; list-style: none; display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-1) var(--sp-5); font-size: var(--fs-sm); }
.sher-calc__error { margin: var(--sp-3) 0 0; font-size: var(--fs-sm); color: var(--danger); }
.sher-calc__error:empty { display: none; }
@media (max-width: 900px) {
  .sher-calc__controls { grid-template-columns: 1fr 1fr; }
  .sher-calc__controls .sher-calc__field--wide { grid-column: 1 / -1; }
  .sher-calc__result, .sher-calc__proc ul { grid-template-columns: 1fr; }
}
@media (max-width: 700px) {
  .sher-calc { padding: var(--sp-5) var(--sp-4); }
}

/* Калькулятор веса металла (страница /kalkulyatory/ves-metalla): два ряда полей, три карточки результата. */
.ves-calc { margin: var(--sp-5) 0 var(--sp-6); padding: var(--sp-6); border: 1px solid var(--hairline); border-top: 3px solid var(--brand); border-radius: var(--radius-lg); background: var(--surface); }
.ves-calc__title { margin: 0 0 var(--sp-4); font-size: var(--fs-h4); font-weight: 700; color: var(--ink-strong); }
.ves-calc__controls { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.6fr) minmax(0, 1fr); gap: var(--sp-4); align-items: end; }
.ves-calc__controls--dims { margin-top: var(--sp-4); grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
.ves-calc__field { display: grid; gap: var(--sp-2); font-size: var(--fs-sm); font-weight: 600; color: var(--ink-strong); }
.ves-calc__field[hidden] { display: none; }
.ves-calc__field .input { width: 100%; }
.ves-calc__field select { width: 100%; min-height: 48px; padding: 0 var(--sp-2); border: 1px solid var(--hairline-strong); border-radius: var(--radius-md); background: #fff; font: inherit; font-weight: 400; color: var(--ink); }
.ves-calc__result { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp-4); margin-top: var(--sp-5); }
.ves-calc__part { padding: var(--sp-4) var(--sp-5); border-radius: var(--radius-md); background: #fff; border: 1px solid var(--hairline); }
.ves-calc__part b { display: block; margin-bottom: var(--sp-2); font-size: 1.25rem; line-height: 1.2; color: var(--brand-dim); }
.ves-calc__part span { display: block; font-size: var(--fs-sm); }
.ves-calc__part em { display: block; margin-top: var(--sp-2); font-style: normal; font-size: var(--fs-caption); color: var(--muted); }
.ves-calc__part--main { border-color: var(--brand); }
.ves-calc__part--main b { font-size: 1.6rem; }
.ves-calc__note { margin: var(--sp-4) 0 0; font-size: var(--fs-caption); color: var(--muted); }
.ves-calc__error { margin: var(--sp-3) 0 0; font-size: var(--fs-sm); color: var(--danger); }
.ves-calc__error:empty { display: none; }
.ves-calc.is-error .ves-calc__result { opacity: .35; }
@media (max-width: 900px) {
  .ves-calc__controls { grid-template-columns: 1fr 1fr; }
  .ves-calc__controls .ves-calc__field--wide { grid-column: 1 / -1; order: 3; }
  .ves-calc__result { grid-template-columns: 1fr; }
}
@media (max-width: 700px) {
  .ves-calc { padding: var(--sp-5) var(--sp-4); }
  .ves-calc__controls--dims { grid-template-columns: 1fr 1fr; }
}

/* Переводчик твёрдости (страница /kalkulyatory/perevod-tverdosti) — по образцу .sher-calc, четыре карточки результата.
   Таблица перевода длинная (59 строк), поэтому живёт в окне с прокруткой и закреплённой шапкой; строки,
   найденные переводчиком, подсвечиваются (.is-hit), окно прокручивается к ним само. */
.tv-calc { margin: var(--sp-5) 0 var(--sp-6); padding: var(--sp-6); border: 1px solid var(--hairline); border-top: 3px solid var(--brand); border-radius: var(--radius-lg); background: var(--surface); }
.tv-calc__title { margin: 0 0 var(--sp-4); font-size: var(--fs-h4); font-weight: 700; color: var(--ink-strong); }
.tv-calc__controls { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) minmax(0, 1fr); gap: var(--sp-4); align-items: end; }
.tv-calc__field { display: grid; gap: var(--sp-2); font-size: var(--fs-sm); font-weight: 600; color: var(--ink-strong); }
.tv-calc__field .input { width: 100%; }
.tv-calc__field select { width: 100%; min-height: 48px; padding: 0 var(--sp-2); border: 1px solid var(--hairline-strong); border-radius: var(--radius-md); background: #fff; font: inherit; font-weight: 400; color: var(--ink); }
.tv-calc__result { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--sp-4); margin-top: var(--sp-5); }
.tv-calc__part { padding: var(--sp-4) var(--sp-5); border-radius: var(--radius-md); background: #fff; border: 1px solid var(--hairline); }
.tv-calc__part b { display: block; margin-bottom: var(--sp-2); font-size: 1.25rem; line-height: 1.2; color: var(--brand-dim); }
.tv-calc__part span { display: block; font-size: var(--fs-sm); }
.tv-calc__part em { display: block; margin-top: var(--sp-2); font-style: normal; font-size: var(--fs-caption); color: var(--muted); }
.tv-calc__part--main { border-color: var(--brand); }
.tv-calc__more { margin: var(--sp-4) 0 0; font-size: var(--fs-sm); }
.tv-calc__more:empty { display: none; }
.tv-calc__error { margin: var(--sp-3) 0 0; font-size: var(--fs-sm); color: var(--danger); }
.tv-calc__error:empty { display: none; }
.tv-calc.is-error .tv-calc__result, .tv-calc.is-error .tv-calc__more { opacity: .35; }
.tv-table { max-height: 640px; overflow-y: auto; border-bottom: 1px solid var(--hairline); }
.tv-table thead th { position: sticky; top: 0; z-index: 1; }
.tv-table td { white-space: nowrap; }
.tv-table tr.is-hit > th, .tv-table tr.is-hit > td { background: rgba(252, 88, 0, .12); }
.tv-table tr.is-hit > th { color: var(--brand-dim); }
@media (max-width: 900px) {
  .tv-calc__controls { grid-template-columns: 1fr 1fr; }
  .tv-calc__controls .tv-calc__field--wide { grid-column: 1 / -1; }
  .tv-calc__result { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 700px) {
  .tv-calc { padding: var(--sp-5) var(--sp-4); }
  .tv-table { max-height: 70vh; }
}

/* Расшифровщик обозначения покрытий (статья /articles/oboznachenie-pokrytiy) — по образцу .ip-decoder:
   поле записи, кнопки примеров, карточки составляющих в порядке ГОСТ 9.306, строка участка технопарка. */
.pk-calc { margin: var(--sp-5) 0 var(--sp-6); padding: var(--sp-6); border: 1px solid var(--hairline); border-top: 3px solid var(--brand); border-radius: var(--radius-lg); background: var(--surface); scroll-margin-top: 96px; }
.pk-calc__title { margin: 0 0 var(--sp-4); font-size: var(--fs-h4); font-weight: 700; color: var(--ink-strong); }
.pk-calc__field { display: grid; gap: var(--sp-2); font-size: var(--fs-sm); font-weight: 600; color: var(--ink-strong); }
.pk-calc__field .input { width: 100%; font-size: 1.25rem; font-weight: 600; letter-spacing: .02em; }
.pk-calc__examples { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); margin: var(--sp-3) 0 0; font-size: var(--fs-sm); color: var(--muted); }
.pk-calc__ex, .pk-code { padding: 2px var(--sp-2); border: 1px solid var(--hairline-strong); border-radius: var(--radius-sm, 6px); background: #fff; font: inherit; font-weight: 600; color: var(--brand-dim); cursor: pointer; }
.pk-calc__ex:hover, .pk-code:hover, .pk-calc__ex:focus-visible, .pk-code:focus-visible { border-color: var(--brand); color: var(--ink-strong); }
.pk-code { font-size: var(--fs-sm); white-space: nowrap; }
.pk-calc__head { margin: var(--sp-5) 0 0; font-size: 1.125rem; line-height: 1.35; color: var(--ink-strong); }
.pk-calc__parts { margin: var(--sp-4) 0 0; padding: 0; list-style: none; display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: var(--sp-3); }
.pk-calc__parts li { padding: var(--sp-3) var(--sp-4); border-radius: var(--radius-md); background: #fff; border: 1px solid var(--hairline); }
.pk-calc__parts b { display: block; font-size: 1.25rem; line-height: 1.2; color: var(--brand-dim); overflow-wrap: anywhere; }
.pk-calc__parts span { display: block; margin-top: var(--sp-1); font-size: var(--fs-caption); font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); }
.pk-calc__parts em { display: block; margin-top: var(--sp-2); font-style: normal; font-size: var(--fs-sm); }
.pk-calc__note { margin: var(--sp-4) 0 0; padding: var(--sp-3) var(--sp-4); border-left: 3px solid var(--brand); background: #fff; font-size: var(--fs-sm); }
.pk-calc__note:empty { display: none; }
.pk-calc__shop { margin: var(--sp-4) 0 0; font-size: var(--fs-sm); }
.pk-calc__error { margin: var(--sp-3) 0 0; font-size: var(--fs-sm); color: var(--danger); }
.pk-calc__error:empty { display: none; }
.pk-calc.is-error .pk-calc__head, .pk-calc.is-error .pk-calc__parts, .pk-calc.is-error .pk-calc__note, .pk-calc.is-error .pk-calc__shop { opacity: .35; }
/* Две справочные таблицы рядом: на узком экране — одна под другой */
.pk-two { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-5); align-items: start; }
.pk-two .table-scroll { margin: 0; }
.pk-thick th, .pk-thick td { text-align: center; white-space: nowrap; }
.pk-thick tbody th { text-align: left; }
@media (max-width: 900px) {
  .pk-two { grid-template-columns: 1fr; }
}
@media (max-width: 700px) {
  .pk-calc { padding: var(--sp-5) var(--sp-4); }
  .pk-calc__parts { grid-template-columns: 1fr; }
}

/* ===== Таблица режимов закалки с фильтром (статья /articles/temperatura-zakalki-stali) ===== */
.zk-filter { margin: var(--sp-5) 0 var(--sp-3); padding: var(--sp-5) var(--sp-6); border: 1px solid var(--hairline); border-top: 3px solid var(--brand); border-radius: var(--radius-lg); background: var(--surface); scroll-margin-top: 96px; }
.zk-filter__field { display: grid; gap: var(--sp-2); max-width: 360px; font-size: var(--fs-sm); font-weight: 600; color: var(--ink-strong); }
.zk-filter__field .input { width: 100%; font-size: 1.125rem; font-weight: 600; }
.zk-filter__groups { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-top: var(--sp-4); }
.zk-chip { padding: 6px var(--sp-3); border: 1px solid var(--hairline-strong); border-radius: 999px; background: #fff; font: inherit; font-size: var(--fs-sm); font-weight: 600; color: var(--ink); cursor: pointer; }
.zk-chip:hover, .zk-chip:focus-visible { border-color: var(--brand); color: var(--brand-dim); }
.zk-chip.is-active { border-color: var(--brand); background: var(--brand); color: #fff; }
.zk-filter__count { margin: var(--sp-3) 0 0; font-size: var(--fs-sm); color: var(--muted); }
.zk-table { max-height: 720px; overflow-y: auto; border-bottom: 1px solid var(--hairline); }
.zk-table thead th { position: sticky; top: 0; z-index: 2; }
.zk-table tbody th small { display: block; margin-top: 2px; font-size: var(--fs-caption); font-weight: 400; color: var(--muted); white-space: normal; }
.zk-table tbody th { min-width: 150px; }
.zk-table .zk-table__group th { background: var(--surface); color: var(--brand-dim); font-size: var(--fs-sm); text-transform: uppercase; letter-spacing: .04em; }
.zk-marks { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-4); margin: var(--sp-5) 0 var(--sp-6); }
.zk-mark { display: flex; flex-direction: column; align-items: flex-start; padding: var(--sp-4) var(--sp-5); border: 1px solid var(--hairline); border-radius: var(--radius-md); background: #fff; }
.article-body .zk-mark h3 { margin: 0 0 var(--sp-2); font-size: 1.125rem; }
.zk-mark p { margin: 0 0 var(--sp-3); font-size: var(--fs-sm); }
.zk-mark .zk-chip { margin-top: auto; }
@media (max-width: 700px) {
  .zk-filter { padding: var(--sp-4); }
  .zk-filter__field { max-width: none; }
  .zk-marks { grid-template-columns: 1fr; }
  /* Кнопки групп — одной строкой с прокруткой, строки таблицы — карточками: шесть столбцов в 390 px не помещаются */
  .zk-filter__groups { flex-wrap: nowrap; overflow-x: auto; margin-left: calc(-1 * var(--sp-4)); margin-right: calc(-1 * var(--sp-4)); padding: 0 var(--sp-4) var(--sp-2); }
  .zk-chip { flex: 0 0 auto; }
  .zk-table { max-height: none; overflow: visible; border-bottom: 0; }
  .zk-table table, .zk-table tbody, .zk-table tr, .zk-table th, .zk-table td { display: block; width: auto; }
  .zk-table table { table-layout: auto; min-width: 0; }
  .zk-table thead { display: none; }
  .zk-table tbody[hidden], .zk-table tr[hidden] { display: none; }
  .zk-table tr[data-zk-mark] { margin: 0 0 var(--sp-3); border: 1px solid var(--hairline); border-radius: var(--radius-md); background: #fff; }
  .zk-table tr[data-zk-mark] > th { border: 0; padding: var(--sp-3) var(--sp-4) var(--sp-1); font-size: 1.125rem; }
  .zk-table tr[data-zk-mark] > td { display: flex; gap: var(--sp-3); border: 0; padding: 2px var(--sp-4); }
  .zk-table tr[data-zk-mark] > td:last-child { padding-bottom: var(--sp-3); }
  .zk-table td[data-l]::before { content: attr(data-l); flex: 0 0 104px; color: var(--muted); font-size: var(--fs-sm); }
  .zk-table .zk-table__group th { border: 0; padding: var(--sp-4) 0 var(--sp-2); background: none; }
  .zk-table, .zk-table table { border: 0; }
  .zk-table caption { display: block; width: auto; text-align: left; padding: 0 0 var(--sp-2); }
  .zk-table tbody th, .zk-table tr[data-zk-mark] > th { min-width: 0; width: auto; max-width: none; border-right: 0; }
}

/* Калькулятор пружин сжатия (страница /kalkulyatory/pruzhiny-szhatiya) — на классах .ves-calc, четыре карточки результата,
   предупреждение об осадке и инерционном зазоре — в строке под карточками (.is-warn). */
.pr-calc .ves-calc__controls { margin-top: var(--sp-4); }
.pr-calc .ves-calc__controls--dims { margin-top: 0; }
.pr-calc__result { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.pr-calc .ves-calc__part b { font-size: 1.15rem; }
.pr-calc .ves-calc__part--main b { font-size: 1.45rem; }
.ves-calc__note.is-warn { padding: var(--sp-3) var(--sp-4); border-left: 3px solid var(--danger); border-radius: var(--radius-md); background: #fff; color: var(--ink); }
@media (max-width: 1100px) {
  .pr-calc__result { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 560px) {
  .pr-calc__result { grid-template-columns: 1fr; }
}

/* Логотипы резидентов и партнёров с названием под логотипом. */
.logo-cards { list-style: none; margin: var(--sp-6) 0 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: var(--sp-5); }
.logo-card { display: flex; flex-direction: column; height: 100%; padding: var(--sp-5); border: 1px solid var(--hairline); border-radius: var(--radius-lg); background: #fff; color: var(--ink); text-decoration: none; }
a.logo-card:hover { border-color: var(--brand); text-decoration: none; }
.logo-card__img { display: flex; align-items: center; justify-content: center; height: 120px; margin-bottom: var(--sp-4); }
.logo-card__img img { max-width: 100%; max-height: 100%; width: auto; height: auto; object-fit: contain; }
.logo-card__name { font-size: var(--fs-base); line-height: 1.35; color: var(--ink-strong); }
.logo-card__text { margin-top: var(--sp-2); font-size: var(--fs-sm); color: var(--muted); }
.resident { display: grid; grid-template-columns: 200px minmax(0, 1fr); gap: var(--sp-6); align-items: center; margin-bottom: var(--sp-6); }
.resident__logo { display: flex; align-items: center; justify-content: center; height: 160px; padding: var(--sp-4); border: 1px solid var(--hairline); border-radius: var(--radius-lg); background: #fff; }
.resident__logo img { max-width: 100%; max-height: 100%; object-fit: contain; }
.resident h1 { margin-bottom: var(--sp-3); }
@media (max-width: 640px) { .resident { grid-template-columns: 1fr; } .resident__logo { height: 120px; } }

/* Отступы широкой вставки — последними: у .article-shot и .article-scheme свой margin. */
.article-wide {
  margin-left: calc((100% - var(--wide)) / 2);
  margin-right: calc((100% - var(--wide)) / 2);
}
.article-body .toc__title { margin: 0 0 var(--sp-4); font-size: var(--fs-caption); line-height: inherit; }
/* Схема на телефоне: подписи в 15 px при ужатии до 360 px не читались — схема держит ширину 640 px и прокручивается вбок. */
@media (max-width: 700px) {
  .article-scheme { overflow-x: auto; }
  .article-scheme svg { min-width: 640px; }
}

/* Сравнение станций на хабе Elli: название модели в первой колонке одной строкой */
.table-scroll--st th[scope="row"] { white-space: nowrap; }
@media (max-width: 640px) { .table-scroll--st table { min-width: 680px; } }

/* Карточка изделия ЖД: цена и две кнопки помещаются в одну строку рамки,
   подзаголовок под H1 — обычным кеглем текста, кнопка запроса под порядком заказа. */
.product-page__buy { gap: var(--sp-4); padding: var(--sp-5); }
.product-page__buy .btn--lg { padding-inline: var(--sp-5); }
.product-page__info .lead { font-size: inherit; line-height: 1.6; }
.product-page__order-cta { margin: var(--sp-6) 0 var(--sp-7); }
/* Кнопки заявки по центру вместо телефонов в тексте (cta_buttons()) */
.cta-row { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--sp-3); margin: var(--sp-6) 0; }
/* восемь вкладок карточки ЖД (с «Доставкой», «Оплатой», «Гарантией») — в одну строку на десктопе */
.tabs .tabs__item { padding-inline: var(--sp-4); }

/* Хаб калькуляторов: второй блок плиток «Расчёты в статьях» отделён от первого */
.article-tiles + h2 { margin-top: 56px; }

/* Калькулятор усилия гибки (страница /kalkulyatory/usilie-gibki) — по образцу .ves-calc.
   Боковые отступы не задаём: правило стоит после .article-wide и сбило бы его центровку. */
.bend-calc { margin-top: var(--sp-5); margin-bottom: var(--sp-6); padding: var(--sp-6); border: 1px solid var(--hairline); border-top: 3px solid var(--brand); border-radius: var(--radius-lg); background: var(--surface); }
.bend-calc__title { margin: 0 0 var(--sp-4); font-size: var(--fs-h4); font-weight: 700; color: var(--ink-strong); }
.bend-calc__controls { display: grid; grid-template-columns: minmax(0, 2fr) repeat(2, minmax(0, 1fr)); gap: var(--sp-4); align-items: end; }
.bend-calc__field { display: grid; gap: var(--sp-2); font-size: var(--fs-sm); font-weight: 600; color: var(--ink-strong); }
.bend-calc__field .input { width: 100%; }
.bend-calc__field select { width: 100%; min-height: 48px; padding: 0 var(--sp-2); border: 1px solid var(--hairline-strong); border-radius: var(--radius-md); background: #fff; font: inherit; font-weight: 400; color: var(--ink); }
.bend-calc__result { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp-4); margin-top: var(--sp-5); }
.bend-calc__part { padding: var(--sp-4) var(--sp-5); border-radius: var(--radius-md); background: #fff; border: 1px solid var(--hairline); }
.bend-calc__part b { display: block; margin-bottom: var(--sp-2); font-size: 1.25rem; line-height: 1.2; color: var(--brand-dim); }
.bend-calc__part span { display: block; font-size: var(--fs-sm); }
.bend-calc__part em { display: block; margin-top: var(--sp-2); font-style: normal; font-size: var(--fs-caption); color: var(--muted); }
.bend-calc__part--force { border-color: var(--brand); }
.bend-calc__part--force b { font-size: 1.6rem; }
.bend-calc__part--bad b { color: var(--danger); }
.bend-calc__error { margin: var(--sp-3) 0 0; font-size: var(--fs-sm); color: var(--danger); }
.bend-calc__error:empty { display: none; }
.bend-calc.is-error .bend-calc__result { opacity: .35; }
.bend-formula { margin: var(--sp-4) 0; padding: var(--sp-4) var(--sp-5); border-left: 3px solid var(--brand); background: var(--surface); font-size: 1.25rem; font-weight: 600; color: var(--ink-strong); }
@media (max-width: 900px) {
  .bend-calc__controls { grid-template-columns: 1fr 1fr; }
  .bend-calc__controls .bend-calc__field--wide { grid-column: 1 / -1; }
  .bend-calc__controls .bend-calc__field:last-child { grid-column: 1 / -1; }
  .bend-calc__result { grid-template-columns: 1fr; }
}
@media (max-width: 700px) {
  .bend-calc { padding: var(--sp-5) var(--sp-4); }
  .bend-formula { font-size: 1.05rem; }
}

/* Калькуляторы с четырьмя полями в ряд (отверстие под резьбу, режимы резания) — оформление .bend-calc, модификатор --4. */
.bend-calc--4 .bend-calc__controls { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 900px) {
  .bend-calc--4 .bend-calc__controls { grid-template-columns: 1fr 1fr; }
  .bend-calc--4 .bend-calc__controls .bend-calc__field:last-child { grid-column: auto; }
}
@media (max-width: 480px) {
  .bend-calc--4 .bend-calc__controls { grid-template-columns: 1fr; }
}

/* Калькулятор с широким полем и двумя короткими (твёрдость по Шору): на планшете и телефоне короткие поля — парой в строку. */
@media (max-width: 900px) {
  .bend-calc--pair .bend-calc__controls .bend-calc__field:last-child { grid-column: auto; }
}

/* Строка-заголовок группы внутри таблицы (аналоги марок стали) — как у таблицы режимов закалки .zk-table__group. */
.table .table__group th { background: var(--surface); color: var(--brand-dim); font-size: var(--fs-sm); text-transform: uppercase; letter-spacing: .04em; }

/* Таблицы размеров по группам, раскрываются по нажатию (размеры уплотнительных колец). */
.ring-table { margin: 0 0 var(--sp-3); border: 1px solid var(--hairline); border-radius: var(--radius-md); background: var(--surface); }
.ring-table > summary { padding: var(--sp-3) var(--sp-4); cursor: pointer; font-weight: 600; color: var(--ink-strong); }
.ring-table[open] > summary { border-bottom: 1px solid var(--hairline); }
.ring-table .table-scroll { margin: 0; padding: var(--sp-3); background: #fff; border-radius: 0 0 var(--radius-md) var(--radius-md); }
.ring-table .table { margin: 0; }

/* Расшифровщик марки стали (статья /articles/marki-stali) — по образцу .bend-calc.
   Боковые отступы не задаём: правило стоит после .article-wide и сбило бы его центровку. */
.ms-decoder { margin-top: var(--sp-5); margin-bottom: var(--sp-6); padding: var(--sp-6); border: 1px solid var(--hairline); border-top: 3px solid var(--brand); border-radius: var(--radius-lg); background: var(--surface); }
.ms-decoder__title { margin: 0 0 var(--sp-4); font-size: var(--fs-h4); font-weight: 700; color: var(--ink-strong); }
.ms-decoder__field { display: grid; gap: var(--sp-2); max-width: 360px; font-size: var(--fs-sm); font-weight: 600; color: var(--ink-strong); }
.ms-decoder__field .input { width: 100%; font-size: 1.25rem; font-weight: 700; letter-spacing: .02em; }
.ms-decoder__result { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp-4); margin-top: var(--sp-5); }
.ms-decoder__part { padding: var(--sp-4) var(--sp-5); border-radius: var(--radius-md); background: #fff; border: 1px solid var(--hairline); }
.ms-decoder__part b { display: block; margin-bottom: var(--sp-2); font-size: 1.25rem; line-height: 1.2; color: var(--brand-dim); }
.ms-decoder__part span { display: block; font-size: var(--fs-sm); }
.ms-decoder__part em { display: block; margin-top: var(--sp-2); font-style: normal; font-size: var(--fs-caption); color: var(--muted); }
.ms-decoder__part em:empty { display: none; }
.ms-decoder__part ul { margin: 0; padding: 0; list-style: none; display: grid; gap: var(--sp-1); font-size: var(--fs-sm); }
.ms-decoder__part--main { border-color: var(--brand); }
.ms-decoder__extra { margin: var(--sp-4) 0 0; font-size: var(--fs-sm); }
.ms-decoder__extra:empty { display: none; }
.ms-decoder__error { margin: var(--sp-3) 0 0; font-size: var(--fs-sm); color: var(--danger); }
.ms-decoder__error:empty { display: none; }
.ms-decoder.is-error .ms-decoder__result { opacity: .35; }
@media (max-width: 900px) {
  .ms-decoder__result { grid-template-columns: 1fr; }
}
@media (max-width: 700px) {
  .ms-decoder { padding: var(--sp-5) var(--sp-4); }
  .ms-decoder__field { max-width: none; }
}


/* Калькулятор массы отливки (страница /kalkulyatory/massa-otlivki) — по образцу .bend-calc.
   Боковые отступы не задаём: правило стоит после .article-wide и сбило бы его центровку. */
.cast-calc { margin-top: var(--sp-5); margin-bottom: var(--sp-6); padding: var(--sp-6); border: 1px solid var(--hairline); border-top: 3px solid var(--brand); border-radius: var(--radius-lg); background: var(--surface); }
.cast-calc__title { margin: 0 0 var(--sp-4); font-size: var(--fs-h4); font-weight: 700; color: var(--ink-strong); }
.cast-calc__controls { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--sp-4); align-items: end; }
.cast-calc__field { display: grid; gap: var(--sp-2); font-size: var(--fs-sm); font-weight: 600; color: var(--ink-strong); }
.cast-calc__field[hidden] { display: none; }
.cast-calc__field--wide { grid-column: span 2; }
.cast-calc__field .input { width: 100%; }
.cast-calc__field select { width: 100%; min-height: 48px; padding: 0 var(--sp-2); border: 1px solid var(--hairline-strong); border-radius: var(--radius-md); background: #fff; font: inherit; font-weight: 400; color: var(--ink); }
.cast-calc__result { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp-4); margin-top: var(--sp-5); }
.cast-calc__part { padding: var(--sp-4) var(--sp-5); border-radius: var(--radius-md); background: #fff; border: 1px solid var(--hairline); }
.cast-calc__part b { display: block; margin-bottom: var(--sp-2); font-size: 1.25rem; line-height: 1.2; color: var(--brand-dim); }
.cast-calc__part span { display: block; font-size: var(--fs-sm); }
.cast-calc__part em { display: block; margin-top: var(--sp-2); font-style: normal; font-size: var(--fs-caption); color: var(--muted); }
.cast-calc__part--main { border-color: var(--brand); }
.cast-calc__part--main b { font-size: 1.6rem; }
.cast-calc__part--bad b { color: var(--ink-strong); }
.cast-calc__error { margin: var(--sp-3) 0 0; font-size: var(--fs-sm); color: var(--danger); }
.cast-calc__error:empty { display: none; }
.cast-calc.is-error .cast-calc__result { opacity: .35; }
.cast-formula { margin: var(--sp-4) 0; padding: var(--sp-4) var(--sp-5); border-left: 3px solid var(--brand); background: var(--surface); font-size: 1.25rem; font-weight: 600; color: var(--ink-strong); }
@media (max-width: 900px) {
  .cast-calc__controls { grid-template-columns: 1fr 1fr; }
  .cast-calc__field--wide { grid-column: 1 / -1; }
  .cast-calc__result { grid-template-columns: 1fr; }
}
@media (max-width: 700px) {
  .cast-calc { padding: var(--sp-5) var(--sp-4); }
  .cast-formula { font-size: 1.05rem; }
}

/* ===========================================================================
   Калькуляторы: интерактивная страница — крошки, H1 и сам калькулятор на всю ширину контейнера
   шапки (от логотипа до кнопки звонка), подзаголовка нет, под H1 только дата обновления. «Читайте также» — той же
   ширины и в статьях. Ширина считается от контейнера (.wrap, единицы cqw), а не от окна: 100vw включает полосу
   прокрутки и на узких мониторах давал бы прокрутку вбок.
   ========================================================================== */
.wrap:has(> .article-body) { container-type: inline-size; }
.article-head--calc { max-width: none; margin-bottom: var(--sp-5); }
.article-head--calc h1 { margin-bottom: var(--sp-3); }
.article-head--calc .article__meta { margin-top: 0; }
.article-full {
  width: 100cqw; max-width: none;
  margin-left: calc((100% - 100cqw) / 2);
  margin-right: calc((100% - 100cqw) / 2);
}
.article-body > .article-full:first-child { margin-top: 0; }
.calc-after { margin-top: var(--sp-6); }
.read-also-block { margin-top: var(--sp-8); }
.read-also-block > h2 { margin-top: 0; }
/* Ручной перенос в H1 калькулятора — только на широком экране: на телефоне строки короткие, перенос дал бы обрывок. */
@media (max-width: 900px) { .article-head--calc h1 br { display: none; } }
/* Перевод твёрдости: на 320–400 px две карточки результата в ряд не помещаются */
@media (max-width: 420px) { .tv-calc__result { grid-template-columns: minmax(0, 1fr); } }

/* Фотогалерея /gallery: та же сетка .gallery, но под кадром — подпись, а над группой — ссылка на раздел услуг. */
.gallery--captions figure { margin: 0; }
.gallery--captions figcaption { margin-top: var(--sp-2); font-size: .9375rem; line-height: 1.4; color: var(--muted); }
.photo-group__link { margin-top: var(--sp-2); }
.gallery--captions { margin-top: var(--sp-4); }

/* Карта сайта /sitemap: блоки разделов в две колонки, вложенные страницы — с отступом и тонкой линией слева. */
/* Колонками, а не сеткой: в сетке короткий блок «Продукция» стоял в одной строке с длинными «Услугами» и под ним зияла пустота. */
.site-map { columns: 2; column-gap: var(--sp-7); }
@media (max-width: 900px) { .site-map { columns: 1; } }
.site-map__block { break-inside: avoid; margin-bottom: var(--sp-6); }
.site-map__block h2 { margin-top: 0; }
.site-map__block h2 a { color: inherit; text-decoration: none; }
.site-map__block h2 a:hover { color: var(--brand-dim); }
.site-map__list { list-style: none; margin: var(--sp-2) 0 0; padding: 0; }
.site-map__list li { margin: 6px 0; line-height: 1.4; }
.site-map__list .site-map__list { margin: 4px 0 var(--sp-3) 4px; padding-left: var(--sp-4); border-left: 1px solid var(--hairline); font-size: .9375rem; }

/* Плитки по три в ряд: шесть плиток ложатся 3 + 3, а не 4 + 2 с пустотой. */
@media (min-width: 1000px) { .read-also--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
/* На телефоне текст первого экрана лежит на всей ширине кадра, а не только слева: светлая крыша цеха
   съедала серый лид — затемняем кадр равномерно. */
@media (max-width: 900px) {
  .hero--page .hero__veil::after { background: linear-gradient(180deg, rgba(10,13,14,.72) 0%, rgba(10,13,14,.62) 100%); }
}

/* Окно заявки с файлом чертежа — горизонтально: в одну колонку оно не помещалось в высоту даже на
   23-дюймовом мониторе. Слева контакты, справа почта и файл; служебные строки и кнопка — на всю ширину. */
.modal__window { margin: auto 0; }
@media (min-width: 1000px) {
  .modal--wide .modal__window { max-width: 880px; }
  .modal--wide .form { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: var(--sp-5); align-items: start; }
  .modal--wide .form > * { margin-top: 0; }
  .modal--wide .form > .modal__product, .modal--wide .form > .form-why, .modal--wide .form > .consent,
  .modal--wide .form > .modal__submit, .modal--wide .form > .modal__req, .modal--wide .form > [data-modal-question], .modal--wide .form > .field--file { grid-column: 1 / -1; }
  .modal--wide .form > .field, .modal--wide .form > .consent, .modal--wide .form > .form-why { margin-bottom: var(--sp-4); }
}
