/* ══════════════════════════════════════════════════════════════════════════
   components.css — общий каркас и блоки, переносимые из утверждённого
   заказчиком варианта design/variants/gmrz-preview-modern.html с применением
   таблицы ремаппинга (см. комментарий в tokens.css).

   Отступления от варианта — все до одного исправления реальных дефектов:
     • надзаголовок секции и иконки плиток в покое больше не акцентные:
       акцент зарезервирован под CTA, ссылки, активный пункт навигации,
       счётчик корзины и кольцо фокуса, и ни подо что больше (UI-SPEC §Color);
     • радиусы сведены к трём, отступы — к кратным четырём (D-02);
     • заголовки набраны плоскими токенами, без clamp() (D-01);
     • начертание 800 → 700, 500 → 400 (D-01);
     • .variant-switch — служебный элемент превью, не переносится.

   Ни одного литерала цвета: проверка no-raw-color требует, чтобы всё
   красящее приходило из tokens.css.
   ══════════════════════════════════════════════════════════════════════════ */

/* ══ ВЕРХНЯЯ ПОЛОСА ═══════════════════════════════════════════════════════ */

.topbar{
  background:var(--color-surface-brand-deep);
  color:var(--color-text-on-brand-muted);
  font-size:var(--text-label);
}
.topbar .container{
  display:flex;
  align-items:center;
  flex-wrap:wrap;
  gap:var(--space-5);
  padding:var(--space-2) var(--layout-gutter);
}
.topbar a{ color:var(--color-text-on-brand-link); text-decoration:none; }
.topbar a:hover{ color:var(--color-text-on-brand); }
.topbar__mail{ margin-right:auto; }

/* На самых узких экранах верхняя полоса сжимается до телефона и
   переключателя языка — пункты навигации никогда не обрезаются. */
@media (max-width:575px){
  .topbar__mail,.topbar__hours{ display:none; }
}

/* Переключатель языка — настоящий навигационный элемент. В утверждённом
   варианте доступное имя висело на голом <div> (строка 224): ошибка
   валидатора ровно на том элементе, от которого зависит двуязычность. */
.lang{
  display:flex;
  margin-left:auto;
  padding:var(--space-1);
  border-radius:var(--radius-pill);
  background:var(--color-control-on-brand);
}
.lang a{
  padding:var(--space-1) var(--space-3);
  border-radius:var(--radius-pill);
  font-size:var(--text-label);
  text-decoration:none;
}
.lang a[aria-current]{
  background:var(--color-surface);
  color:var(--color-surface-brand);
  font-weight:var(--weight-bold);
}


/* ══ ШАПКА ════════════════════════════════════════════════════════════════ */

.site-header{
  position:sticky;
  top:0;
  z-index:50;
  background:var(--color-surface-blur);
  backdrop-filter:blur(14px);
  -webkit-backdrop-filter:blur(14px);
  border-bottom:1px solid var(--color-hairline);
}
.hrow{
  display:flex;
  align-items:center;
  gap:var(--space-6);
  padding:var(--space-4) var(--layout-gutter);
  min-height:var(--header-height);
}

/* Бренд. Знак — ВНЕШНИЙ файл, а не встроенный <svg>: иначе тридцать строк
   размножатся по семи страницам и подмена реального вектора перестанет быть
   подменой одного файла (D-07). */
.brand{
  display:flex;
  align-items:center;
  gap:var(--space-3);
  color:var(--color-surface-brand);
  text-decoration:none;
}
.brand__mark{ width:var(--icon-tile); height:auto; flex:none; }
.brand__name{
  display:block;
  font-size:var(--text-lead);
  font-weight:var(--weight-bold);
  line-height:1.1;
}
.brand__sub{
  display:block;
  font-size:var(--text-caption);
  font-weight:var(--weight-regular);
  line-height:1.3;
  color:var(--color-text-muted);
}

/* Навигация. ПОРОГ БУРГЕРА ПОДНЯТ С 992px ДО 1200px ПЛАНОМ 05-07 — это
   исполнение правила §P9 дизайн-контракта Фазы 5: семь пунктов обязаны
   помещаться в одну строку БЕЗ уменьшения кегля, а не помещаются — значит
   двигается порог, а не шрифт. Кегль зафиксирован D-01 Фазы 1 и не трогается.

   Замер (Inter, метрики шрифта из assets/fonts/, ширины в пикселях при
   16px/400 и жирном текущем пункте): семь подписей 469, поля ссылок 7×32,
   зазоры 6×4 — навигация 717. Бренд 290, корзина 44, два зазора строки 64:
   ряду нужно 1115. На 992px в контейнере остаётся 944 — не помещается, и на
   этом пороге шестой пункт помещался с запасом всего 8. На 1200px доступно
   1152 против нужных 1115 — помещается. Пункты не переносятся на вторую
   строку ни на одном брейкпоинте: ряд не переносится, у ссылок nowrap. */
.site-nav{ margin-left:auto; }
.site-nav ul{ display:flex; gap:var(--space-1); }
.site-nav a{
  display:flex;
  align-items:center;
  min-height:var(--tap-min);
  padding:0 var(--space-4);
  border-radius:var(--radius-pill);
  color:var(--color-text);
  font-size:var(--text-body);
  font-weight:var(--weight-regular);
  text-decoration:none;
  white-space:nowrap;
}
.site-nav a:hover{
  background:var(--color-accent-surface);
  color:var(--color-accent);
}
.site-nav a[aria-current]{
  color:var(--color-accent);
  font-weight:var(--weight-bold);
}

.burger{
  display:none;
  align-items:center;
  justify-content:center;
  width:var(--tap-min);
  height:var(--tap-min);
  border-radius:var(--radius-sm);
  background:var(--color-surface-alt);
  color:var(--color-surface-brand);
}

/* Ниже 1200px навигация сворачивается. Правила скрытия гейтятся классом .js
   на корневом элементе: если скрипт не выполнился, класса нет, навигация
   остаётся видимой и работоспособной. */
@media (max-width:1199.98px){
  .burger{ display:flex; }
  .js .site-nav{
    position:absolute;
    left:0;
    right:0;
    top:100%;
    display:none;
    background:var(--color-surface);
    border-bottom:1px solid var(--color-hairline);
    box-shadow:var(--shadow-lg);
  }
  .js .site-nav.is-open{ display:block; }
  .site-nav ul{
    flex-direction:column;
    gap:0;
    padding:var(--space-3) var(--layout-gutter) var(--space-5);
  }
  .site-nav a{ border-radius:var(--radius-sm); }
}

/* Корзина. Счётчик скрыт при нуле — контракт zero-one-many; в Фазе 4
   доступное имя станет склоняемой по числу строкой Twig. */
.cart{
  position:relative;
  display:flex;
  align-items:center;
  justify-content:center;
  width:var(--tap-min);
  height:var(--tap-min);
  border-radius:var(--radius-sm);
  background:var(--color-surface-alt);
  color:var(--color-surface-brand);
  text-decoration:none;
}
.cart:hover{ background:var(--color-accent-surface); }
.cart__badge{
  position:absolute;
  top:calc(-1 * var(--space-1));
  right:calc(-1 * var(--space-1));
  min-width:var(--badge-min-w);
  height:var(--badge-min-w);
  padding:0 var(--space-2);
  border-radius:var(--radius-pill);
  background:var(--color-accent);
  color:var(--color-text-on-brand);
  font-size:var(--text-caption);
  font-weight:var(--weight-bold);
  line-height:var(--badge-min-w);
  text-align:center;
  box-shadow:var(--shadow-badge);
}
.cart__badge[hidden]{ display:none; }


/* ══ КНОПКИ ═══════════════════════════════════════════════════════════════ */

.btn{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  gap:var(--space-2);
  min-height:var(--button-height);
  padding:0 var(--space-6);
  border-radius:var(--radius-button);
  font-size:var(--text-body);
  font-weight:var(--weight-bold);
  text-decoration:none;
  transition:transform .15s, box-shadow .15s;
}
.btn svg{ flex:none; }
.btn-accent{
  background:var(--color-accent);
  color:var(--color-text-on-brand);
  box-shadow:var(--shadow-accent);
}
.btn-accent:hover{ transform:translateY(-2px); box-shadow:var(--shadow-lg); }
.btn-ghost{
  background:var(--color-surface-on-brand);
  color:var(--color-text-on-brand);
  border:1px solid var(--color-surface-on-brand-hover);
}
.btn-ghost:hover{ background:var(--color-surface-on-brand-hover); }


/* ══ ЧИП ══════════════════════════════════════════════════════════════════ */

.chip{
  display:inline-flex;
  align-items:center;
  gap:var(--space-2);
  padding:var(--space-2) var(--space-4);
  border-radius:var(--radius-pill);
  background:var(--color-surface-on-brand);
  border:1px solid var(--color-hairline-on-brand);
  color:var(--color-text-on-brand-link);
  font-size:var(--text-label);
  font-weight:var(--weight-semibold);
}
.chip::before{
  content:"";
  width:var(--space-2);
  height:var(--space-2);
  border-radius:var(--radius-pill);
  background:var(--color-success);
}


/* ══ ГЕРОЙ ════════════════════════════════════════════════════════════════
   Многослойный тёмно-синий градиент и сетка-наложение переносятся из
   утверждённого варианта без изменений — это подпись облика, который
   заказчик утвердил. Изменён ровно один параметр: размер заголовка. */

.hero{
  position:relative;
  overflow:hidden;
  color:var(--color-text-on-brand);
  background:
    radial-gradient(900px 500px at 85% 10%, var(--color-accent-glow), transparent 60%),
    radial-gradient(700px 500px at -5% 100%, var(--color-accent-glow-soft), transparent 55%),
    linear-gradient(150deg, var(--color-surface-brand) 0%, var(--color-surface-brand-deep) 70%);
}
.hero::after{
  content:"";
  position:absolute;
  inset:0;
  pointer-events:none;
  background-image:
    linear-gradient(var(--color-grid-on-brand) 1px, transparent 1px),
    linear-gradient(90deg, var(--color-grid-on-brand) 1px, transparent 1px);
  background-size:var(--space-7) var(--space-7);
  mask-image:radial-gradient(800px 600px at 70% 40%, var(--mask-opaque) 30%, transparent 75%);
  -webkit-mask-image:radial-gradient(800px 600px at 70% 40%, var(--mask-opaque) 30%, transparent 75%);
}
.hero .container{
  position:relative;
  z-index:1;
  padding-top:var(--layout-section-y);
  padding-bottom:var(--layout-section-y);
}

/* Плоский --text-display вместо clamp(34px,4.6vw,58px) — самая заметная
   дельта относительно того, что видел заказчик. Выносится ему на ревью
   планом 01-06 отдельной строкой, а не поглощается молча. */
.hero h1{
  margin-top:var(--space-5);
  max-width:24ch;
  font-size:var(--text-display);
  font-weight:var(--weight-bold);
  line-height:1.12;
  /* СТРАХОВКА, не замена ступени ниже. На текущем тексте это правило не
     срабатывает ни на одной ширине — ступень 26px ниже 400px уже уводит самое
     длинное слово внутрь колонки. Оно стоит здесь потому, что запас у ступени
     мал и держится на длине конкретного слова: замер на ширине окна 401px, где
     кегль возвращается к 32px, даёт 369px доступной ширины против 364.5px у
     слова «электрооборудование» — 4.5px. Любая правка текста, смена насыщенности
     или подстановка настоящего логотипа этот запас съедает, а отказ молчаливый:
     .hero{overflow:hidden} срезает вылет, горизонтальной прокрутки не возникает,
     и ни одна проверка на прокрутку дефекта не видит (так он и был пропущен —
     находка 2 прохода 01-09). С этим правилом худший исход — перенос внутри
     слова, а не исчезнувшие буквы.

     hyphens:auto СЮДА НЕ ДОБАВЛЯТЬ. Испробовано и отвергнуто: Chromium
     переносит «электрооборудование» как «элек-трооборудование» — это не точка
     переноса русского слова, и словарь переносов у каждого браузера свой.
     overflow-wrap:break-word дефис не вставляет и словаря не требует. */
  overflow-wrap:break-word;
}
.hero h1 em{ font-style:normal; color:var(--color-accent-on-brand); }

/* Ниже 400px заголовок героя опускается на соседнюю ступень шкалы — 26px.
   Замер при ширине окна 360px: содержимое .container.grid-hero — 328px, а
   самое длинное слово «электрооборудование» кеглем 32px занимает 364px.
   Перенос внутри слова запрещён (overflow-wrap:normal, word-break:normal,
   hyphens:manual), поэтому слово распирало колонку до 364px, а
   .hero{overflow:hidden} молча срезал вылет: у слов пропадали последние буквы,
   и вместе с заголовком обрезался лид — он стоит в той же распёртой колонке.
   Кеглем 26px то же слово занимает 296px и умещается в 328px.

   ОТВЕРГНУТО и переоткрывать не надо: overflow-wrap:break-word вместе с
   hyphens:auto обрезку тоже снимает, но Chromium переносит
   «электрооборудование» как «элек-трооборудование» — это не точка переноса
   русского слова, и словарь переносов у каждого браузера свой. Ступень шкалы
   оставляет слова целыми и словаря не требует. 26px уже входит в утверждённую
   шкалу из шести размеров (--text-heading), поэтому D-01 не нарушается.

   Ступень остаётся как есть, но одна она защищает только сегодняшний текст:
   на 401px, где кегль возвращается к 32px, запас всего 4.5px (369px колонки
   против 364.5px у слова). Приемлемо это ровно потому, что выше на .hero h1 и
   .hero p стоит overflow-wrap:break-word — страховка, превращающая будущий
   отказ из молчаливой обрезки в видимый перенос. */
@media (max-width:400px){
  .hero h1{ font-size:var(--text-heading); }
}
.hero p{
  margin-top:var(--space-5);
  max-width:40ch;
  font-size:var(--text-lead);
  color:var(--color-text-on-brand-lead);
  /* Та же страховка и по той же причине: лид стоит в одной колонке с
     заголовком, и когда колонку распирало словом заголовка, обрезался он
     тоже — «ремон‹т›», «насосо‹в›». */
  overflow-wrap:break-word;
}
.hero-cta{
  display:flex;
  flex-wrap:wrap;
  gap:var(--space-4);
  margin-top:var(--space-6);
}

.stats{
  display:flex;
  flex-wrap:wrap;
  gap:0;
  margin-top:var(--space-7);
  padding-top:var(--space-6);
  border-top:1px solid var(--color-hairline-on-brand);
}
.stat{
  padding-right:var(--space-7);
  margin-right:var(--space-7);
  border-right:1px solid var(--color-hairline-on-brand);
}
.stat:last-child{ border-right:0; margin-right:0; padding-right:0; }
.stat b{
  display:block;
  font-size:var(--text-display);
  font-weight:var(--weight-bold);
  line-height:1.1;
}
.stat span{ font-size:var(--text-label); color:var(--color-text-on-brand-muted); }
@media (max-width:575px){
  .stat{ padding-right:var(--space-5); margin-right:var(--space-5); }
  .stat b{ font-size:var(--text-heading); }
}

.hero-art{ display:none; }
@media (min-width:992px){ .hero-art{ display:block; } }
/* СНИМОК ЗАВОДА В ПРАВОЙ КОЛОНКЕ ГЕРОЯ. Пропорция и скругление взяты у
   .photo-slot ниже — того самого слота, который стоял здесь в утверждённом
   макете: снимок обязан занять ЕГО место, а не завести рядом второй вид
   медиа-блока. `object-fit:cover` кадрирует 1024×600 (1,71:1) до 16/10 на
   считанные пиксели по краям и не даёт растяжения по одной оси. Своей
   высоты у снимка нет — её задаёт пропорция, поэтому вёрстка не прыгает,
   пока файл грузится. */
.hero-art img{
  width:100%;
  aspect-ratio:16/10;
  object-fit:cover;
  border-radius:var(--radius-card);
}


/* ══ ЗАГОЛОВОК СЕКЦИИ ═════════════════════════════════════════════════════ */

.sec-head{
  display:flex;
  align-items:flex-end;
  flex-wrap:wrap;
  gap:var(--space-5);
  margin-bottom:var(--space-7);
}
/* Надзаголовок приглушённый, а не акцентный: акцент зарезервирован. */
.overline{
  margin-bottom:var(--space-4);
  font-size:var(--text-label);
  font-weight:var(--weight-bold);
  letter-spacing:.14em;
  text-transform:uppercase;
  color:var(--color-text-muted);
}
.sec-head h2{ font-size:var(--text-heading); font-weight:var(--weight-bold); }
.sec-head .all{
  display:inline-flex;
  align-items:center;
  gap:var(--space-2);
  min-height:var(--tap-min);
  margin-left:auto;
  white-space:nowrap;
  font-weight:var(--weight-semibold);
  text-decoration:none;
}
.sec-head .all:hover{ gap:var(--space-3); }
.sec-head .all svg{ transition:transform .15s; }


/* ══ ПЛИТКИ КАТЕГОРИЙ ═════════════════════════════════════════════════════
   Разделы различаются иконкой и фотографией, а не цветом: единый фирменный
   тёмно-синий на всех плитках (D-05). Цветовое кодирование разделов из
   фирменного каталога на сайт не переносится. */

.card-cat{
  display:flex;
  flex-direction:column;
  gap:var(--space-4);
  padding:var(--card-padding);
  min-height:var(--cat-tile-min-h);
  border:1px solid var(--color-hairline);
  border-radius:var(--radius-card);
  background:var(--color-surface);
  color:var(--color-text);
  text-decoration:none;
  transition:transform .18s, box-shadow .18s;
}
.card-cat:hover{
  transform:translateY(-4px);
  box-shadow:var(--shadow-lg);
  border-color:transparent;
}
/* Иконка в покое — navy на нейтральной подложке; акцент только на наведении. */
.card-cat__ic{
  display:flex;
  align-items:center;
  justify-content:center;
  width:var(--icon-tile);
  height:var(--icon-tile);
  border-radius:var(--radius-sm);
  background:var(--color-surface-alt);
  color:var(--color-surface-brand);
}
.card-cat:hover .card-cat__ic{
  background:var(--color-accent-surface);
  color:var(--color-accent);
}
/* Необязательная медиа-полоса плитки раздела (D-13). Рендерится ТОЛЬКО
   когда у раздела загружена фотография; пока фотографий нет, плитка
   совпадает с утверждённой байт в байт — то есть заказчик видит ровно то,
   что утвердил, а место под фотографию уже существует. Пропорция та же,
   что у .card-product__media и .photo-slot: плитки в ряду не разъезжаются
   по высоте из-за разных исходных снимков. */
.card-cat__media{
  position:relative;
  aspect-ratio:16/10;
  overflow:hidden;
  border-radius:var(--radius-sm);
  background:var(--color-surface-alt);
}
.card-cat__media img{ width:100%; height:100%; object-fit:cover; }

/* Заголовок плитки — h2 в списке услуг (над ним на странице только h1) и
   h3 на главной (над ним h2 секции «Разделы каталога»). Уровень выбирает
   страница по своей иерархии заголовков, а размер и начертание приходят
   отсюда: облик плитки не зависит от того, каким уровнем она размечена. */
.card-cat h2,
.card-cat h3{
  font-size:var(--text-lead);
  font-weight:var(--weight-bold);
  line-height:1.3;
}
.card-cat__meta{
  display:flex;
  align-items:center;
  margin-top:auto;
  font-size:var(--text-label);
  color:var(--color-text-muted);
}
.card-cat__meta svg{ margin-left:auto; transition:transform .18s; }
.card-cat:hover .card-cat__meta svg{ transform:translateX(4px); }


/* ══ ФОТО-СЛОТ ════════════════════════════════════════════════════════════
   Тот же слот обслуживает «нет фото» карточки товара и ведущее изображение
   страницы новости — пропорция 16/10 фиксирована, чтобы карточки в ряду
   не разъезжались по высоте. */

.photo-slot{
  position:relative;
  display:flex;
  align-items:center;
  justify-content:center;
  aspect-ratio:16/10;
  background:linear-gradient(140deg, var(--color-surface-brand-soft), var(--color-surface-brand-deep));
  color:var(--color-text-on-photo);
}
.photo-slot::after{
  content:"место для фото";
  position:absolute;
  bottom:var(--space-2);
  right:var(--space-4);
  font-size:var(--text-caption);
  letter-spacing:.08em;
  text-transform:uppercase;
  color:var(--color-text-on-photo);
}


/* ══ КАРТОЧКА НОВОСТИ ═════════════════════════════════════════════════════ */

.card-news{
  position:relative;
  display:flex;
  flex-direction:column;
  overflow:hidden;
  border-radius:var(--radius-card);
  background:var(--color-surface);
  box-shadow:var(--card-shadow);
  transition:transform .18s, box-shadow .18s;
}
.card-news:hover{ transform:translateY(-4px); box-shadow:var(--shadow-lg); }
.card-news__body{
  display:flex;
  flex-direction:column;
  flex:1;
  gap:var(--space-3);
  padding:var(--space-5);
}
/* Дата — приглушённая, не акцентная: это не CTA и не ссылка. */
.card-news time{
  align-self:flex-start;
  padding:var(--space-1) var(--space-3);
  border-radius:var(--radius-pill);
  background:var(--color-surface-alt);
  color:var(--color-text-muted);
  font-size:var(--text-label);
  font-weight:var(--weight-semibold);
}
.card-news h3{ font-size:var(--text-lead); font-weight:var(--weight-bold); line-height:1.4; }
.card-news a{ color:inherit; text-decoration:none; }
.card-news a:hover{ color:var(--color-accent); }

/* НАКРЫТИЕ — им и кликается вся карточка новости.

   Карточка нарисована единой кнопкой, а вела себя как абзац с одной
   ссылкой внутри: нажатие по снимку и по площади карточки не открывало
   ничего. Приём — тот же, что у карточки товара в catalog.css и у .hero
   выше по этому файлу: псевдоэлемент ЕДИНСТВЕННОЙ ссылки растянут на всю
   площадь карточки, которая служит ему содержащим блоком.

   ССЫЛКА В КАРТОЧКЕ ОДНА, И ВТОРОЙ БЫТЬ НЕ ДОЛЖНО. Обёртка <a> вокруг
   карточки дала бы вторую ссылку на ту же статью — диктор прочитал бы
   новость дважды, клавиатура прошла бы её двумя остановками. На одной
   ссылке держится и сам селектор: два накрытия на одну карточку означали
   бы два слоя друг поверх друга. Единственность проверяется прогоном
   NewsCardClickTest на отданных страницах и в обоих макетах.

   ПОЧЕМУ СЕЛЕКТОР `.card-news a`, А НЕ `.card-news__title a`, КАК У
   ТОВАРА. Разметка карточки в утверждённых макетах разная: design/news.html
   несёт .card-news__title, а блок новостей главной в design/index.html —
   просто <h3 class="clamp-2">. Селектор по заголовку работал бы на сайте и
   молча не доезжал бы до макета главной. Разметка макетов не тронута.

   ПОДНИМАТЬ НАД НАКРЫТИЕМ ЗДЕСЬ НЕЧЕГО — и этим карточка новости
   отличается от карточки товара, где кнопку «В корзину» пришлось поднять.
   Ни кнопки, ни формы, ни второй ссылки в карточке новости нет. Дата под
   накрытием остаётся намеренно: она не интерактивна и не является
   значением, которое переписывают, — в отличие от артикула и цены товара,
   поднятых ради выделения мышью. Поднять дату значило бы завести внутри
   карточки полоску, которая никуда не ведёт. */
.card-news a::after{
  content:"";
  position:absolute;
  inset:0;
}


/* ══ КОНТАКТНЫЙ БЛОК ══════════════════════════════════════════════════════ */

.contact-card{
  overflow:hidden;
  border-radius:var(--radius-card);
  background:var(--color-surface);
  box-shadow:var(--card-shadow);
}
.contact-info{ padding:var(--space-7) var(--space-6); }
@media (min-width:768px){ .contact-info{ padding:var(--space-7); } }

/* Пара «название → значение» размечена как <dl>: у справочных строк ровно
   эта структура, и она складывается в стек на mobile без потери смысла.
   Иконка живёт ВНУТРИ <dt> — спецификация допускает в div внутри dl только
   dt и dd, поэтому отдельный <span> рядом с ними был бы ошибкой валидатора. */
.crow{
  display:grid;
  grid-template-columns:1fr;
  gap:var(--space-1);
  padding:var(--space-4) 0;
  border-bottom:1px solid var(--color-hairline);
}
@media (min-width:576px){
  .crow{
    grid-template-columns:max-content 1fr;
    column-gap:var(--space-5);
    align-items:center;
  }
}
.crow:last-of-type{ border-bottom:0; }
.crow dt{
  display:flex;
  align-items:center;
  gap:var(--space-3);
  font-size:var(--text-label);
  font-weight:var(--weight-regular);
  color:var(--color-text-muted);
}
.crow dd{ overflow-wrap:anywhere; }
.crow__ic{
  display:flex;
  align-items:center;
  justify-content:center;
  flex:none;
  width:var(--tap-min);
  height:var(--tap-min);
  border-radius:var(--radius-sm);
  background:var(--color-surface-alt);
  color:var(--color-surface-brand);
}
.crow dd a{ color:var(--color-text); font-weight:var(--weight-semibold); text-decoration:none; }
.crow dd a:hover{ color:var(--color-accent); }

.map-slot{
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:center;
  gap:var(--space-2);
  min-height:var(--map-slot-min-h);
  background:
    radial-gradient(500px 260px at 60% 40%, var(--color-accent-glow-faint), transparent 65%),
    var(--color-surface-alt);
  color:var(--color-text-muted);
  font-size:var(--text-label);
}
.map-slot__pin{
  display:flex;
  align-items:center;
  justify-content:center;
  width:var(--icon-tile);
  height:var(--icon-tile);
  border-radius:var(--radius-pill);
  background:var(--color-surface);
  color:var(--color-surface-brand);
  box-shadow:var(--shadow);
}


/* ══ CTA-ПОЛОСА ═══════════════════════════════════════════════════════════ */

.cta-band{ margin:0 var(--layout-gutter); }
.cta-band__inner{
  max-width:var(--layout-container);
  margin:0 auto;
  padding:var(--space-7) var(--space-6);
  border-radius:var(--radius-card);
  text-align:center;
  color:var(--color-text-on-brand);
  background:
    radial-gradient(600px 300px at 90% 0%, var(--color-accent-glow), transparent 60%),
    linear-gradient(140deg, var(--color-surface-brand), var(--color-surface-brand-deep));
  box-shadow:var(--shadow-lg);
}
@media (min-width:768px){ .cta-band__inner{ padding:var(--space-8); } }
.cta-band__inner h2{ font-size:var(--text-heading); font-weight:var(--weight-bold); }
.cta-band__inner p{
  max-width:52ch;
  margin:var(--space-4) auto var(--space-6);
  color:var(--color-text-on-brand-lead);
}


/* ══ ПОДВАЛ ═══════════════════════════════════════════════════════════════ */

.site-footer{
  margin-top:var(--space-8);
  padding:var(--space-8) 0 var(--space-6);
  background:var(--color-surface-brand-deep);
  color:var(--color-text-on-brand-muted);
  font-size:var(--text-body);
}
.site-footer__t{
  margin-bottom:var(--space-4);
  color:var(--color-text-on-brand);
  font-size:var(--text-body);
  font-weight:var(--weight-bold);
}
.site-footer a{
  display:inline-block;
  padding:var(--space-1) 0;
  color:var(--color-text-on-brand-muted);
  text-decoration:none;
}
.site-footer a:hover{ color:var(--color-text-on-brand); }
.site-footer address{ font-style:normal; }

/* ══ ПОЛ КАСАНИЯ НА ТЕЛЕФОНЕ ═══════════════════════════════════════════════
   Контракт дизайна Фазы 1 (01-UI-SPEC.md § Touch targets) требует дословно:
   все кнопки, навигационные ссылки и поля форм — не ниже 44 пикселей на
   телефоне. Бургер и корзина это правило держали, а остальная навигация нет.
   Замер до правки на 375px: ссылки подвала 34, переключатель языка 30,
   телефон и почта в верхней полосе 22, хлебные крошки 17.

   ПОЛ СТАВИТСЯ ТОЛЬКО НА УЗКОМ ЭКРАНЕ. На настольном пальцем не целятся, а
   44 пикселя под каждой ссылкой подвала растянули бы его вдвое без пользы.

   РАСТЁТ ОБЛАСТЬ КАСАНИЯ, А НЕ ТЕКСТ. Ссылка становится строчно-блочным
   флексом с выравниванием по центру: подпись остаётся на месте, а нажимаемым
   делается весь прямоугольник. Тот же приём, что у кнопок админки. */
@media (max-width:575px){
  .site-footer a,
  .topbar a,
  .lang a,
  .breadcrumbs a{
    display:inline-flex;
    align-items:center;
    min-height:var(--tap-min);
  }
  /* Крошки стоят в строку и переносятся: вертикальный отступ у них нулевой,
     высоту даёт min-height, иначе строка крошек выросла бы вдвое. */
  .breadcrumbs a{ padding-top:0; padding-bottom:0; }
}

/* Копирайт: --color-text-on-brand-faint даёт 4.82:1 на тёмно-синем подвале.
   В утверждённом варианте здесь стоял #6E82A3 = 4.00:1 — провал WCAG AA. */
.copy{
  margin-top:var(--space-7);
  padding-top:var(--space-5);
  border-top:1px solid var(--color-hairline-on-brand);
  font-size:var(--text-label);
  color:var(--color-text-on-brand-faint);
}


/* ══ ЗНАК БЕЛОРУССКОГО РУБЛЯ ══════════════════════════════════════════════
   Знак утверждён постановлением Правления Нацбанка РБ №25 от 2026-01-27,
   в силе с 2026-02-04: кириллическая «Б», перечёркнутая горизонтальной
   чертой. Заказчик выбрал знак вместо буквенного BYN и поставил его ПОСЛЕ
   суммы через обычный пробел — «1 250,00 Б» (строки 1 и 9 журнала ревью).

   Кодовой точки Unicode у знака нет — он слишком новый, набрать его текстом
   нельзя. Поэтому он собирается из НАСТОЯЩЕЙ «Б» (U+0411 есть в
   завендоренном кириллическом подмножестве Inter — проверено по таблице
   cmap самого файла шрифта) и черты, нарисованной псевдоэлементом. Что это
   даёт против встроенной картинки: цена остаётся выделяемым и копируемым
   текстом, а черта наследует кегль, начертание и цвет — то есть остаётся
   верной на каждой ступени типографической шкалы и в мобильной раскладке,
   без второго набора размеров. Внешних байтов знак не тянет: ни нового
   шрифта, ни нового файла.

   Доступность: role="img" делает содержимое элемента листом дерева
   доступности, и экранный диктор читает не букву «Б», а имя из aria-label.
   Цена звучит как «1 250,00 белорусских рублей», а не как «1 250,00 Б». */
.byn{
  position:relative;
  display:inline-block;
  line-height:1;
  white-space:nowrap;
}
/* Геометрия выведена из ЗАМЕРА в браузерном движке, а не из метрик строки.
   Замерено на design/catalog.html в Chromium по http, кегль 16px,
   начертание 700: верх прописной «Б» стоит в 0.2725em от верха бокса,
   базовая линия — в 1.0em, высота прописной — 0.7275em. Последнее число
   совпадает с capHeight 1490/2048 самого файла шрифта: глиф рисуется как
   объявлен, сместилось положение бокса относительно него. Отсюда середина
   буквы = 0.2725 + 0.7275/2 = 0.63625em. Черта толщиной 0.1em
   позиционируется ВЕРХНИМ краем, поэтому top = 0.63625 - 0.05 = 0.586em.

   Прежнее значение top:0.45em ставило середину черты на 0.5em и было
   ошибкой. Оно выводилось из ascent/descent шрифта и полулидинга — то есть
   из СТРОЧНОГО бокса, — а положение CSS-бокса строчного элемента
   относительно базовой линии шрифта этими метриками не задаётся. Считать
   их одним и тем же нельзя: движок поставил текст на 0.13623em ниже, чем
   давала та арифметика, и черта уходила в верх чаши буквы — знак читался
   как обычная «Б», а не как денежный знак.

   Вылет влево. Левая грань стержня «Б» стоит в 0.06592em от левого края
   бокса (левый вынос 135/2048 в завендоренном файле Inter при wght 700).
   Черта обязана выходить за стержень влево, как у ₽ и ₴: именно вылет
   отличает денежный знак от буквы с чертой. Вылет взят в одну толщину
   черты, 0.1em, отсюда left = 0.06592 - 0.1 = -0.034em. Справа вылет
   прежний — 0.02em за край бокса.

   Обе доли заданы в em и масштабируются вместе с кеглем; высота прописной
   от начертания не зависит, поэтому top верен и вне 700. Значения
   посчитаны, а не подобраны: что на 0.63em черта пересекает букву, а на
   0.45em сливается с верхом её чаши, увидено браузерным проходом, а не
   этим комментарием. Строка 5.1 формы design/BROWSER-CHECK.md остаётся за
   человеком — правку он смотрит заново. */
.byn::after{
  content:"";
  position:absolute;
  top:0.586em;
  left:-0.034em;
  right:-0.02em;
  border-top:0.1em solid currentColor;
  pointer-events:none;
}
