/* Оформление сайта. Цветов и размеров тут нет — только токены из tokens.css. */

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  font-family: var(--шрифт);
  font-size: var(--кегль-обычный);
  line-height: 1.6;
  color: var(--текст);
  background: var(--фон);
}
img { max-width: 100%; height: auto; display: block; }
a { color: var(--фирменный); }
h1, h2, h3 { line-height: 1.2; margin: 0 0 var(--отступ-1); }
h1 { font-size: var(--кегль-h1); letter-spacing: -.02em; }
h2 { font-size: var(--кегль-h2); letter-spacing: -.01em; }
h3 { font-size: var(--кегль-h3); }
p  { margin: 0 0 var(--отступ-1); }

.обёртка { width: min(100% - 2rem, var(--ширина)); margin-inline: auto; }
.узко    { max-width: var(--ширина-текста); }
.приглушён { color: var(--текст-приглушён); }
.мелко   { font-size: var(--кегль-мелкий); }

/* ── шапка ───────────────────────────────────────────────────────────────── */
/* ⛔ Липнет НЕ вся шапка, а только нижняя полоса с меню и адресом страницы
   `[решение владельца 29-08-2026]`. Логотип с назначением занимают полторы
   сотни пикселей: держать их на экране постоянно значило бы отдать четверть
   высоты под то, что читают один раз. */
.шапка {
  border-bottom: 1px solid var(--граница);
  background: var(--фон);
}
.шапка__ряд {
  display: flex; align-items: center; gap: var(--отступ-2);
  min-height: 152px;   /* под логотип 118 плюс воздух */
}
.шапка__низ {
  position: sticky; top: 0; z-index: 30;
  background: var(--фон);
  border-top: 1px solid var(--граница);
  padding: .5rem 0;
}
/* ⛔ Отступ для якорей — следствие липкой полосы выше, и стоит рядом с ней,
   а не в общих правилах: увидевший `position: sticky` должен тут же увидеть,
   чем за неё заплачено.

   Без этого браузер ставит цель якоря ровно в верх окна — то есть ПОД полосу,
   и заголовок раздела не виден: человек приходит по `/soglasie/#dannye`,
   попадает в нужное место и видит середину чужого абзаца. Найдено в браузере
   `[04-09-2026]` при проверке ссылок из галочек согласия; касается всех
   якорей сайта, а не только их — `/uslugi/#smeta`, `/dokumenty/#uchreditelnye`
   уезжали так же с тех пор, как полоса стала липкой.

   ⚑ `scroll-padding-top` на корне, а не `scroll-margin-top` на заголовках:
   правило одно и действует на любой переход к якорю, в том числе будущий,
   а не только на те элементы, которые кто-то не забыл перечислить.

   ⚠ 85 px — измеренная высота полосы, одинаковая на телефоне и на экране
   `[замерено 04-09-2026]`. Плюс `--отступ-2`, чтобы заголовок не прилипал
   к полосе снизу. Полоса переменной высоты этот замер обесценит — тогда
   величину придётся считать сценарием. */
html { scroll-padding-top: calc(85px + var(--отступ-2)); }
.лого { display: flex; align-items: center; text-decoration: none; flex: none; }
/* Высота задаётся, ширина считается сама: пропорции знака не искажаются.
   Росла трижды по решению владельца: 52 → 78 `[15-08]` → 92 → 118 `[16-08]`.
   Дальше расти некуда без правки самой шапки: 118 — это высота трёх строк
   назначения, то есть логотип уже вровень с самым высоким соседом. */
.лого img { height: 118px; width: auto; }

/* Назначение над меню: род занятий на каждой странице, а не только на главной.
   Кегль вдвое против первого варианта `[владелец 16-08-2026]`: 0,875 → 1,75 rem.
   Это уже не подпись, а заявление о том, чем организация занимается, —
   и по величине оно должно быть вторым после логотипа, а не последним.
   Разрывы внутри «проектной документации» и «инженерных изысканий» закрыты
   неразрывными пробелами в самом содержании. */
.шапка__назначение {
  margin: 0 0 0 auto; font-size: 1.75rem; line-height: 1.15; letter-spacing: -.01em;
  color: var(--фирменный); font-weight: 700; text-align: right;
  /* Ширина подобрана по числу строк, а не на глаз: при 22ch выходило пять строк
     и шапка вырастала до 210 px. Здесь — три. */
  max-width: 640px;
}

/* ⛔ Меню в ОДНУ строку `[решение владельца 29-08-2026]`. Пока оно стояло
   в правой колонке рядом с логотипом, ширины не хватало и оно переносилось
   на две строки. Своя полоса во всю ширину — места хватает; `nowrap` держит
   строку одной и тогда, когда пунктов станет больше, а прокрутка вбок
   не даёт им обрезаться молча. */
/* Меню и «кто вошёл» — в одном ряду, каждое своей задачей: меню тянется
   и прокручивается внутри себя на узком экране, индикатор входа не сжимается
   и не убегает с ним — она короткая и всегда должна дочитываться целиком. */
.шапка__низ-ряд {
  display: flex; align-items: center; gap: var(--отступ-1);
}
.меню {
  display: flex; gap: var(--отступ-1); flex-wrap: nowrap;
  align-items: center; overflow-x: auto; scrollbar-width: none;
  flex: 1 1 auto; min-width: 0;
}
.меню::-webkit-scrollbar { display: none; }
.меню a, .меню__неактивен, .меню__раскрыть { white-space: nowrap; }

/* Адрес открытой страницы — в той же липкой полосе, сразу под меню. */
.шапка__низ .хлебные {
  margin: .375rem 0 0; font-size: var(--кегль-мелкий);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Полужирное намеренно `[владелец 16-08-2026]`: обычным начертанием пункты
   терялись рядом с крупной строкой назначения и логотипом. */
.меню a {
  text-decoration: none; color: var(--текст); padding: .375rem .25rem;
  border-bottom: 2px solid transparent; font-weight: 700;
}
.меню a:hover { border-bottom-color: var(--акцент); }
.меню a[aria-current="page"] { border-bottom-color: var(--фирменный); font-weight: 600; }
.шапка__тел { font-weight: 700; white-space: nowrap; text-decoration: none; color: var(--текст); }
/* Пункт заявлен, но не работает: виден и явно неактивен, а не спрятан. */
.меню__неактивен { color: var(--текст-приглушён); padding: .375rem .25rem;
  cursor: default; font-weight: 700; }
.меню__неактивен i { font-style: normal; font-size: .75rem; margin-left: .3rem;
  padding: .05rem .35rem; border-radius: 999px; background: var(--фон-мягкий);
  border: 1px solid var(--граница); }

/* ── подменю: раскрытие кликом, а не наведением ────────────────────────────
   `[решение владельца 29-08-2026]`: принцип ex-ko.ru — клик по пункту
   раскрывает список. Кнопка выглядит как обычный пункт меню, чтобы не
   выделяться устройством среди простых ссылок. */
.меню__группа { position: relative; }
.меню__раскрыть {
  display: inline-flex; align-items: center; gap: .3rem;
  border: 0; background: transparent; cursor: pointer;
  font: inherit; font-weight: 700; color: var(--текст);
  padding: .375rem .25rem; border-bottom: 2px solid transparent;
}
.меню__раскрыть:hover { border-bottom-color: var(--акцент); }
.меню__стрелка { transition: transform .15s ease; flex: none; }
.меню__раскрыть[aria-expanded="true"] .меню__стрелка { transform: rotate(180deg); }
.меню__раскрыть[aria-expanded="true"] { border-bottom-color: var(--фирменный); }

/* ⛔ **Панель `fixed` на всех ширинах, а не только на телефоне.** Полоса меню
   теперь всегда `overflow-x: auto` (одна строка вместо переноса), а такой
   контейнер обрезает абсолютно спозиционированного потомка — containing block
   у него `.меню__группа` внутри полосы. Поймано 29-08-2026: панель на десктопе
   перестала показываться сразу после того, как меню сделали однострочным.
   ⚑ `fixed` считает координаты от окна и обрезке не подлежит; `top` и `left`
   ставит `menu.js` от кнопки — у фиксированного элемента нет своего ориентира. */
.подменю {
  position: fixed; z-index: 20;
  min-width: 18rem; max-width: 26rem;
  display: flex; flex-direction: column; gap: .125rem;
  padding: .5rem; border-radius: var(--скругление-мал);
  max-height: 70vh; overflow-y: auto;
  background: var(--фон); border: 1px solid var(--граница); box-shadow: var(--тень-выше);
}
/* ⛔ **Без этой строки все подменю видны всегда, разом и внахлёст** — так
   и вышло у владельца 29-08-2026. Браузерное правило `[hidden] {display:none}`
   слабее любого селектора с классом, и `display:flex` выше его перебивал.
   Атрибут при этом стоял верно — я проверял его через JS и потому ничего
   не заметил: смотрел свойство вместо того, что видно на экране.
   ⚑ Правило: у элемента, который прячут атрибутом `hidden`, `display` в CSS
   обязан иметь парную строку `[hidden]`. */
.подменю[hidden] { display: none; }
.подменю__пункт {
  display: block; padding: .5rem .625rem; border-radius: 4px;
  text-decoration: none; color: var(--текст); font-weight: 500; line-height: 1.3;
}
.подменю__пункт:hover { background: var(--фон-мягкий); }
/* Неактивный подпункт делит класс с верхнеуровневым `.меню__неактивен`, здесь —
   только то, чем он внутри подменю отличается: своя ширина и отступ строки. */
.подменю .меню__неактивен { display: block; padding: .5rem .625rem; cursor: default; }

/* ── личный кабинет ──────────────────────────────────────────────────────── */
.сводка { display: flex; gap: var(--отступ-2); flex-wrap: wrap; align-items: stretch; }
.сводка__число b { display: block; font-size: 1.75rem; line-height: 1.1; }
.сводка__число span { font-size: var(--кегль-мелкий); color: var(--текст-приглушён); }
.сводка__тревога {
  border-left: 3px solid var(--ошибка); padding-left: var(--отступ-1);
  display: grid; align-content: center;
}
.сводка__тревога b { color: var(--акцент-тёмный); }
.сводка__тревога span { font-size: var(--кегль-мелкий); color: var(--текст-приглушён); }

/* Широкое прокручивается внутри своей рамки, а не тащит вбок всю страницу. */
.прокрутка-вбок { overflow-x: auto; margin-top: var(--отступ-1); }
table.ход { border-collapse: collapse; width: 100%; min-width: 34rem; }
table.ход th, table.ход td {
  border-bottom: 1px solid var(--граница); padding: .625rem .5rem;
  text-align: left; vertical-align: top;
}
table.ход th { font-size: var(--кегль-мелкий); color: var(--текст-приглушён); font-weight: 600; }
table.ход .ч { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
table.ход tr.ход--висит { background: var(--фон-тревога); }

/* ── кабинет: матрица «раздел × этап» ─────────────────────────────────────
   ⚑ Форма выбрана владельцем `[16-08-2026]`: не сводка, а матрица. Наглядность
   в самой заполненности — по «лесенке» дат видно, кто где встал, а сводные
   числа этого не показывают. Столбцы стороны экспертизы и стороны заказчика
   различаются цветом, поэтому «чей сейчас ход» читается без чтения.
   Даты локального заключения в отчёт не входят `[владелец 16-08-2026]`. */
.выбор-орг { display: flex; gap: var(--отступ-0-5); flex-wrap: wrap;
  margin-top: var(--отступ-2); }
.выбор-орг__кнопка {
  font: inherit; text-align: left; cursor: pointer;
  padding: .625rem 1rem; border-radius: var(--скругление-мал);
  border: 1px solid var(--граница); background: var(--фон); color: var(--текст);
  font-weight: 700;
}
.выбор-орг__кнопка span { display: block; font-weight: 400;
  font-size: var(--кегль-мелкий); color: var(--текст-приглушён); }
.выбор-орг__кнопка.выбрана {
  border-color: var(--фирменный); background: var(--фирменный-светлый);
  color: var(--фирменный-тёмный);
}
.выбор-орг__кнопка.выбрана span { color: var(--фирменный-тёмный); }

/* Расшифровка названия раздела спрятана по умолчанию `[владелец 16-08-2026]`:
   «практически все понимают, о чём речь». Она же и была главной причиной, по
   которой матрица не помещалась в экран. */
.переключатель {
  display: inline-flex; align-items: center; gap: .5rem; cursor: pointer;
  margin-top: var(--отступ-1); font-size: var(--кегль-мелкий);
  color: var(--текст-приглушён);
}
.расшифровка { display: none; }
.с-расшифровками .расшифровка { display: block; }

table.матрица { border-collapse: collapse; width: 100%; font-size: .8125rem; }
table.матрица th, table.матрица td {
  border: 1px solid var(--граница); padding: .4375rem .5rem;
  text-align: left; vertical-align: top; white-space: nowrap;
}
table.матрица th { font-weight: 600; color: var(--текст-приглушён); line-height: 1.25; }
table.матрица .д, table.матрица .ч {
  font-variant-numeric: tabular-nums; text-align: right;
}
/* Столбцы шире своей даты: заголовок в две строки длиннее любой из них.
   При выравнивании вправо дата отрывалась от заголовка `[владелец 16-08-2026]`. */
table.матрица .сторона-итог,
table.матрица .получены { text-align: center; }

/* Клетка, которой уже не быть: раздел закрыт, а круг не понадобился.
   Точки редкие и бледные — это отсутствие даты, а не содержимое. Фон столбца
   под ними остаётся, поэтому вертикаль сторон не рвётся. */
table.матрица td.неприменимо {
  background-image: radial-gradient(var(--точки) 1px, transparent 1.1px);
  background-size: 8px 8px;
  background-position: 3px 3px;
}
/* Первый столбец не уезжает при прокрутке вбок: без него на телефоне
   не понять, к какому разделу относится дата. */
table.матрица .липкий {
  position: sticky; left: 0; z-index: 1; background: var(--фон);
  white-space: normal; min-width: 5.5rem;
}
/* С расшифровками столбец шире: самая длинная — «Соответствие ПД дефектной
   ведомости и акту обследования», в 9rem она разваливалась на шесть строк. */
.с-расшифровками table.матрица .липкий { min-width: 10rem; }
table.матрица thead .липкий { background: var(--фон-мягкий); }

/* Стороны. Цвет держится бледным: датам нужно оставаться читаемыми. */
.сторона-экс  { background: var(--сторона-экс); }
.сторона-вы   { background: var(--сторона-вы); }
.сторона-итог { background: var(--сторона-итог); }
thead .сторона-экс  { background: var(--сторона-экс-шапка); color: var(--фирменный-тёмный); }
thead .сторона-вы   { background: var(--сторона-вы-шапка); color: var(--сторона-вы-текст); }
thead .сторона-итог { background: var(--сторона-итог-шапка); color: var(--успех); }
.сторона-вы-текст  { color: var(--сторона-вы-текст); }
.сторона-экс-текст { color: var(--фирменный); }

/* Полоса слева — чей ход. Ставится на липкую ячейку, поэтому видна всегда. */
table.матрица tbody tr .липкий { border-left: 4px solid transparent; }
tr.ход--вы   .липкий { border-left-color: var(--сторона-вы-граница); }
tr.ход--экс  .липкий { border-left-color: var(--фирменный); }
tr.ход--итог .липкий { border-left-color: var(--успех); }
tr.ход--нет  .липкий { border-left-color: var(--граница); }
tr.ход--нет td { color: var(--текст-приглушён); }

/* ⚑ Готовность раздела видна цветом, а не датой `[владелец 16-08-2026]`:
   «в моей таблице было визуально видно, какой раздел получил положительный
   результат, даже не обращая внимания на даты».
   ⛔ Заливать строку целиком нельзя — тем же решением владельца: «вертикальная
   структура по столбцам исчезнет, а она важна». Красится ТОЛЬКО ячейка раздела:
   готовность читается по левому краю сверху вниз, цвета сторон остаются целы. */
tr.ход--итог .липкий { background: var(--сторона-итог-липкий); }
tr.ход--итог .липкий b { color: var(--успех-тёмный); }
tr.ход--итог .липкий b::before { content: '✓ '; }
tr.ход--итог .д.сторона-итог { font-weight: 700; color: var(--успех); }

.легенда {
  display: flex; flex-wrap: wrap; gap: .5rem var(--отступ-1);
  align-items: center; margin-top: var(--отступ-2);
  padding: var(--отступ-1); border: 1px solid var(--граница);
  border-radius: var(--скругление); font-size: var(--кегль-мелкий);
}
.легенда span { display: inline-flex; align-items: center; gap: .375rem; }
.плашка { width: 1rem; height: 1rem; border-radius: 3px; border: 1px solid var(--граница); }
.плашка--экс  { background: var(--сторона-экс); }
.плашка--вы   { background: var(--сторона-вы); }
.плашка--итог { background: var(--сторона-итог); }
.плашка--пусто { background: var(--фон); }

.лента { list-style: none; margin: 0; padding: 0; display: grid; gap: .25rem;
  font-size: var(--кегль-мелкий); }
.лента li { display: grid; grid-template-columns: 5.5rem 1fr; gap: .5rem; }
.лента span { color: var(--текст-приглушён); font-variant-numeric: tabular-nums; }

/* ── контакты и карта ────────────────────────────────────────────────────── */
.реквизиты { display: grid; grid-template-columns: 7rem 1fr; gap: .5rem var(--отступ-1);
  margin: 0; }
.реквизиты dt { color: var(--текст-приглушён); font-size: var(--кегль-мелкий); }
.реквизиты dd { margin: 0; }
@media (max-width: 30rem) {
  .реквизиты { grid-template-columns: 1fr; gap: 0 0; }
  .реквизиты dd { margin-bottom: var(--отступ-0-5); }
}

/* Гнездо карты держит высоту заранее: когда придёт рамка, страница не прыгнет. */
.карта {
  display: flex; flex-direction: column; align-items: flex-start; gap: var(--отступ-1);
  min-height: 20rem; justify-content: center;
  background: var(--фон-мягкий); border-radius: var(--скругление-мал);
  padding: var(--отступ-1);
}
.карта iframe { width: 100%; height: 20rem; border: 0; border-radius: var(--скругление-мал); }
.карта__пояснение { margin: 0; max-width: 34ch; }

.вход input:disabled { background: var(--фон-мягкий); color: var(--текст-приглушён); }
.вход button:disabled { opacity: .5; cursor: not-allowed; }

/* ── кнопки ──────────────────────────────────────────────────────────────── */
.кнопка {
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  padding: .75rem 1.375rem; border-radius: var(--скругление-мал);
  font: inherit; font-weight: 600; text-decoration: none; cursor: pointer;
  border: 1px solid transparent; transition: background .15s, border-color .15s;
}
.кнопка--главная { background: var(--акцент); color: var(--на-акценте); }
.кнопка--главная:hover { background: var(--акцент-тёмный); }
.кнопка--обычная { background: var(--фон); color: var(--фирменный); border-color: var(--граница); }
.кнопка--обычная:hover { border-color: var(--фирменный); }
.кнопка--светлая { background: var(--фон-кнопки-светлой); color: var(--фирменный); }

/* Выбранный режим работы сервиса. Кнопка нажата и недоступна, пока второго
   режима нет: показать, что выбор существует, честнее, чем прятать его. */
.кнопка--выбрана {
  background: var(--фон-кнопки-светлой); color: var(--фирменный);
  border-color: var(--фирменный); cursor: default;
}
.кнопка--выбрана[disabled] { opacity: 1; }
.режимы {
  display: flex; gap: var(--отступ-1); align-items: center;
  flex-wrap: wrap; margin-top: var(--отступ-1);
}

/* ── первый экран ────────────────────────────────────────────────────────── */
.экран {
  background: linear-gradient(180deg, var(--полоса-от) 0%, var(--полоса-до) 100%);
  color: var(--текст-на-тёмном);
  padding: var(--отступ-4) 0;
}
.экран > .обёртка { position: relative; z-index: 1; }

/* Первый экран: рисунок во всю ширину, от края до края `[владелец 16-08-2026]`.
   Сдвинутый вправо он смотрелся хуже прежнего — либо на месте, либо во всю
   ширину, полумера оказалась худшим из трёх.

   ⚑ С 29-08-2026 здесь фотография города с кранами `[выбор владельца]`, а не
   план микрорайона. Она подставляется той же МАСКОЙ, что и рисунки: яркость
   исходника переведена в прозрачность прогоном `tools/prepare_fon_karusel.py`.
   ⛔ Положить её обычным слоем нельзя: исходник подготовлен под светлый фон,
   он почти белый, и на тёмно-синей полосе работал бы наоборот — небо
   высветляло бы полосу широким пятном под белым текстом, а здания, которые
   и есть сюжет, сливались бы с фоном, потому что они темнее неба.
   ⚑ Как маска она вдобавок берёт цвет из места применения, поэтому ночная
   тема не требует второго файла — в отличие от фотографии рулонов ниже. */
.экран.подложка::after {
  -webkit-mask-image: url('/static/img/fon-krany.webp?v=d4eb6b99');
          mask-image: url('/static/img/fon-krany.webp?v=d4eb6b99');
  /* `cover`, а не «во всю ширину»: у фотографии есть низ и верх, и при
     привязке к ширине на низкой полосе от города оставалась бы полоска неба. */
  -webkit-mask-size: cover; mask-size: cover;
  -webkit-mask-position: center bottom; mask-position: center bottom;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  /* Ниже, чем у рисунков: фотография покрывает всю площадь полосы, а не
     несколько линий, и при той же прозрачности спорила бы с текстом. */
  opacity: .13;
}

/* ── подложка: план микрорайона ───────────────────────────────────────────
   Рисунок задаётся МАСКОЙ, а не картинкой. Тогда цвет линий берётся из
   `currentColor` того места, где подложка стоит: на синем экране — светлые,
   на белом разделе — тёмные, и файл при этом один.
   Прозрачность низкая намеренно: подложка читается боковым зрением
   и не спорит с текстом. */
.подложка { position: relative; overflow: hidden; }
.подложка::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background-color: currentColor;
  -webkit-mask: url('/static/img/fon-mikrorajon.svg?v=6d5294ce') no-repeat right -40px center;
          mask: url('/static/img/fon-mikrorajon.svg?v=6d5294ce') no-repeat right -40px center;
  -webkit-mask-size: auto 132%;
          mask-size: auto 132%;
  opacity: .17;
}
/* ⚑ На светлом фоне линии берутся НЕ из currentColor, а фирменным синим.
   Первая версия красила их цветом текста при 9-10 % — и рисунок пропадал
   совсем: тонкие линии почти чёрного поверх почти белого при такой
   прозрачности неразличимы. Синий по светлому читается как чертёж.

   ⚠ Правило висит на ЛЮБОЙ секции, а не только на серой. Прежде оно
   касалось лишь `.секция--мягкая`, и подложка на белой секции возвращалась
   к цвету текста, то есть пропадала. Светлая секция светлая независимо
   от того, серая она или белая. */
.секция.подложка::after {
  background-color: var(--фирменный);
  opacity: .22;
  /* ⚠ Размер по ШИРИНЕ, а не по высоте полосы. От высоты рисунок на широком
     окне съёживался в правый угол и занимал меньше десятой части полосы,
     тогда как на первом экране держал ту же долю. Третий раз одна и та же
     ошибка: привязка к величине, которая меняется. `[владелец 16-08-2026]` */
  -webkit-mask-size: 100% auto; mask-size: 100% auto;
  -webkit-mask-position: center; mask-position: center;
}

/* ⚠ Разделители между секциями. Три серые секции подряд слились в одно
   полотно `[владелец 16-08-2026]`: границы между ними не было видно вовсе.
   Чередование белой и серой плюс тонкая черта — и блоки снова читаются
   по отдельности. */
.секция--мягкая { border-top: 1px solid var(--граница); border-bottom: 1px solid var(--граница); }

/* Тот же рисунок дважды читается как одна длинная картинка — второму нужен
   другой кадр. ⚠ Делается ОТДЕЛЬНЫМ ФАЙЛОМ, а не `transform: scaleX(-1)`:
   преобразование на псевдоэлементе браузер не применил, хотя правило дошло
   дословно. Что должно ехать с рисунком — живёт в рисунке. */
.подложка--зеркально::after {
  -webkit-mask-image: url('/static/img/fon-mikrorajon-zerk.svg?v=26e1cf14');
          mask-image: url('/static/img/fon-mikrorajon-zerk.svg?v=26e1cf14');
}

/* ⚠ Об уборке неиспользуемого `[владелец 29-08-2026: «убирать будем позже
   ненужное, когда везде завершим с фонами»]`.

   ⛔ **Список сжался сам, и это довод не спешить.** Вчера без применения
   числились `подложка--рулоны` (два файла, день и ночь) и `подложка--зеркально`;
   сегодня владелец отдал рулоны «Документам», и половина «мусора» оказалась
   нужной. Удали я их вчера — сегодня пришлось бы доставать из истории.

   ✅ Фон выбран ВСЕМ разделам `[30-08-2026]`. Без применения на страницах:
   `подложка--зеркально` (`fon-mikrorajon-zerk.svg`, 10 КБ) и `подложка--каркас`
   (`fon-karkas.svg`, 8 КБ).
   ⛔ Каркас **не удалять**: он остаётся умолчанием в `page.html` для страниц,
   у которых поле `фон:` не заполнено. Ни одна нынешняя страница его не
   показывает, но следующая новая покажет — это запасной, а не мусор.
   ⚠ Перед уборкой сверяться не по этой записи, а поиском `подложка--`
   по `templates/`: запись успеет устареть, как уже успела за сутки. */

/* Уровень страницы показывается рисунком, а не цветом: цвет занят фирменным.
   Глубину видно по хлебным крошкам: сколько ступеней до главной — такой и рисунок.
       1-й — план микрорайона сверху  (главная)
       2-й — каркасная модель здания  (услуги, о центре, база знаний, кабинет)
       3-й — чертёж плана             (статья, страница сервиса) */
.подложка--каркас::after {
  -webkit-mask-image: url('/static/img/fon-karkas.svg?v=000aec7b');
          mask-image: url('/static/img/fon-karkas.svg?v=000aec7b');
}
/* ⚑ Третий уровень — ФОТОГРАФИЯ, и потому устроен иначе всех остальных.
   Рисунки идут маской и берут цвет из места применения; у фотографии свой цвет
   в каждой точке, так она не умеет. Поэтому: картинка вместо маски, наложение
   «умножение» вместо прозрачности — белая бумага при умножении исчезает в фоне
   полосы, остаются только линии чертежа. Маска остаётся, но одна, для истаивания
   влево: у неё здесь единственная работа. */


/* ── шапка внутренней страницы ───────────────────────────────────────────── */
.шапка-страницы {
  background: var(--фон-мягкий);
  border-bottom: 1px solid var(--граница);
  /* ⚠ Полоса была поднята до 260 px ради рисунка — и съела полезную высоту
     страницы `[владелец 16-08-2026]`. Высота возвращена, а читаемость рисунка
     решена иначе: он уменьшен под полосу и растянут по горизонтали. */
  padding: var(--отступ-3) 0;
  min-height: 190px;
  display: grid;
  align-content: center;
}
.шапка-страницы .обёртка { position: relative; z-index: 1; }
.шапка-страницы h1 { margin-bottom: .5rem; max-width: 24ch; }
.шапка-страницы p { margin: 0; max-width: 58ch; }
.шапка-страницы .хлебные { margin: 0 0 var(--отступ-1); font-size: var(--кегль-мелкий); }
/* ⚠ Размер задан в ПИКСЕЛЯХ, а не в процентах высоты полосы.
   Проценты давали разное на разных страницах: у «Базы знаний» есть подзаголовок,
   полоса выше — и рисунок вставал крупнее и левее, чем на «Услугах».
   Пиксели дают одно и то же везде. Сдвиг влево — отступ справа. */
.шапка-страницы.подложка::after {
  background-color: var(--фирменный);
  opacity: .3;
  /* Обе стороны заданы явно — значит рисунок РАСТЯНУТ по горизонтали в полтора
     раза против своих пропорций `[решение владельца 16-08-2026]`. Для подложки
     это не искажение, а панорамный кадр: в низкой полосе широкое читается
     лучше высокого. Высота 420 против прежних 578 — уменьшено под полосу. */
  -webkit-mask-size: 1230px 420px; mask-size: 1230px 420px;
  -webkit-mask-position: right 350px bottom -40px;
          mask-position: right 350px bottom -40px;
}

/* ── фотографические подложки `[выбор владельца 29-08-2026]` ───────────────
   Готовятся одним прогоном `tools/prepare_fon.py`: яркость исходника переведена
   в прозрачность, поэтому они ведут себя как рисунки — берут цвет из места
   применения и не дают резкого края. Обоснование целиком — в шапке прогона.

   ⛔ **Фон выбирается по СМЫСЛУ страницы, а не по её глубине** `[решение
   владельца 29-08-2026: «прежний порядок „первый уровень — микрорайон, второй —
   каркас, третий — рулоны“ меняем, т. к. у нас теперь уровень проставлен
   в адресе страницы под меню, и более правильным становится выбор фона
   по корреляции со смыслом страницы»]`.
   ⚑ Прежний порядок не был плох — он был осмыслен, пока глубину не показывало
   ничто другое. В тот же день под меню появилась прилипающая строка адреса
   и забрала себе эту работу; картинка, продолжавшая показывать уровень, стала
   вторым голосом о том же самом, а о разделе не говорил никто.
   ⛔ Отсюда и второе: **фон следует за разделом, а не за страницей** — одна
   картинка на всех страницах раздела. Каркас остаётся там, где фон разделу
   ещё не выбран. Разбор целиком — docs/specs/oformlenie-sajta.md.

   ⛔ **Блок стоит ЗДЕСЬ, а не выше по файлу.** У `.шапка-страницы.подложка::after`
   вес (0,2,0) и растяжка 1230×420 px под рисованные уровни; одноклассовые
   правила легче и проигрывают ему, а двухклассовые равны по весу — и тогда
   решает порядок. Первая версия стояла выше, и фотография кабинета молча
   растянулась в 1230×420 вместо своих пропорций: правило применилось, картинка
   поехала, а глазом на мелком снимке это выглядело приемлемо. Найдено замером
   `getComputedStyle(el, '::after').maskSize`. Тот же капкан, что описан выше
   у рулонов, и он сработал вторично.

   ⚑ `cover` вместо «во всю ширину»: у фотографии есть верх и низ, и при
   привязке к ширине на низкой полосе от сюжета оставалась бы полоска фона. */
.подложка--макет::after,
.шапка-страницы.подложка--макет::after {
  -webkit-mask-image: url('/static/img/fon-maket.webp?v=3e6c27ca');
          mask-image: url('/static/img/fon-maket.webp?v=3e6c27ca');
  -webkit-mask-size: cover; mask-size: cover;
  -webkit-mask-position: center; mask-position: center;
}
/* ⚠ Полки приглушены сильнее прочих `[владелец 30-08-2026: «для раздела „База
   знаний“ фон не подходит — можно оставить тот же рисунок, но перепад между
   светлым и тёмным слишком сильный и отвлекает внимание от чтения»]`.
   ⚑ Причина в самой картинке, а не в настройке. Остальные подложки —
   фотографии: у них полутона идут сплошняком, и глаз читает их как дымку.
   Полки нарисованы вектором: у каждой книги ровная заливка и резкий край,
   то есть перепад там, где у фотографии плавный переход. При одной и той же
   прозрачности фотография отходит на задний план, а рисунок лезет вперёд.
   Лечится прозрачностью: она сжимает весь размах к нулю разом. */
.подложка--полки::after,
.шапка-страницы.подложка--полки::after {
  -webkit-mask-image: url('/static/img/fon-polki.webp?v=c229028d');
          mask-image: url('/static/img/fon-polki.webp?v=c229028d');
  -webkit-mask-size: cover; mask-size: cover;
  -webkit-mask-position: center; mask-position: center;
}
.секция.подложка--полки::after { opacity: .10; }
.шапка-страницы.подложка--полки::after { opacity: .13; }

/* ── подложки, стоящие КУСКОМ справа от текста ─────────────────────────────
   Начато с кабинета `[владелец 29-08-2026: «фоновый рисунок вставить только
   в правой части от текста, но края нужно плавно соединить цветом»]`, и тем же
   порядком поставлены совещание и офис `[выбор владельца 30-08-2026]`.

   ⚠ У последних двух исходники КВАДРАТНЫЕ, а полоса заголовка низкая и широкая.
   Растянутые во всю ширину, они теряют сюжет: от совещания остаются затылки
   без доски, от офиса — ряд мониторов без зала. В пропорции и справа они
   читаются, а слева остаётся чистое место под текст.

   ⚑ Растушёвка левого края вписана в саму прозрачность картинки
   (`prepare_fon.py`, 45 % ширины), а не наложена градиентом в CSS: у
   `mask-composite` в разных браузерах разные имена значений, а альфа везде одна.
   Это то же решение, что у фотографии рулонов, только там в картинку впечатывали
   ЦВЕТ полосы — и оттого понадобился отдельный файл на ночь.
   ⛔ **Размер задаётся по-разному, и это не небрежность.** У кабинета исходник
   горизонтальный (1249×702), и высота полосы задаёт ему разумную ширину: 132 %
   высоты — около 600 px. У совещания и офиса исходники КВАДРАТНЫЕ, и та же
   формула даёт всего ~250 px: картинка съёживается в узкую виньетку у края,
   а растушёвке в 45 % от неё негде развернуться. Проверено глазом 30-08-2026.
   Поэтому квадратным размер задаётся долей ШИРИНЫ полосы; по высоте они
   обрезаются серединой, где и лежит сюжет — доска у совещания, столы у офиса.
   ⚑ Общее правило отсюда: **привязывать размер к той стороне, которая
   у картинки главная.** Одна формула на разные пропорции — это одна формула,
   верная для одной из них. */
.подложка--кабинет::after,
.шапка-страницы.подложка--кабинет::after,
.подложка--макет-стол::after,
.шапка-страницы.подложка--макет-стол::after,
.подложка--совещание::after,
.шапка-страницы.подложка--совещание::after,
.подложка--офис::after,
.шапка-страницы.подложка--офис::after {
  -webkit-mask-position: right center; mask-position: right center;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
}
/* Оба горизонтальные — размер по высоте полосы (см. довод выше). */
.подложка--кабинет::after,
.шапка-страницы.подложка--кабинет::after,
.подложка--макет-стол::after,
.шапка-страницы.подложка--макет-стол::after {
  -webkit-mask-size: auto 132%; mask-size: auto 132%;
}
.подложка--макет-стол::after,
.шапка-страницы.подложка--макет-стол::after {
  -webkit-mask-image: url('/static/img/fon-maket-stol.webp?v=9b171a6a');
          mask-image: url('/static/img/fon-maket-stol.webp?v=9b171a6a');
}
.подложка--совещание::after,
.шапка-страницы.подложка--совещание::after,
.подложка--офис::after,
.шапка-страницы.подложка--офис::after {
  -webkit-mask-size: 38% auto; mask-size: 38% auto;
}
.подложка--совещание::after,
.шапка-страницы.подложка--совещание::after {
  -webkit-mask-image: url('/static/img/fon-soveshchanie.webp?v=49a51af1');
          mask-image: url('/static/img/fon-soveshchanie.webp?v=49a51af1');
}
.подложка--офис::after,
.шапка-страницы.подложка--офис::after {
  -webkit-mask-image: url('/static/img/fon-ofis.webp?v=e3e3ab42');
          mask-image: url('/static/img/fon-ofis.webp?v=e3e3ab42');
}
/* ⚠ На узком экране куски убираются совсем: текст занимает всю ширину,
   и «справа от текста» там просто нет места. */
@media (max-width: 900px) {
  .шапка-страницы.подложка--кабинет::after,
  .шапка-страницы.подложка--макет-стол::after,
  .шапка-страницы.подложка--совещание::after,
  .шапка-страницы.подложка--офис::after { display: none; }
}

/* Рабочее место — только СПРАВА от текста `[владелец 29-08-2026: «фоновый
   рисунок вставить только в правой части от текста, но края нужно плавно
   соединить цветом»]`.
   ⚑ Растушёвка левого края вписана в саму прозрачность картинки
   (`prepare_fon.py`, 45 % ширины), а не наложена градиентом в CSS: у
   `mask-composite` в разных браузерах разные имена значений, а альфа везде одна.
   Это то же решение, что у фотографии рулонов, только там в картинку впечатывали
   ЦВЕТ полосы — и оттого понадобился отдельный файл на ночь.
   ⚑ Высота 132 %, а не 100 %: при точной высоте полосы картинка выходит узкой
   полоской у правого края, и растушёвке негде развернуться. */
.подложка--кабинет::after,
.шапка-страницы.подложка--кабинет::after {
  -webkit-mask-image: url('/static/img/fon-rabochee-mesto.webp?v=3c8f36ea');
          mask-image: url('/static/img/fon-rabochee-mesto.webp?v=3c8f36ea');
}

/* ⚠ Селектор с двумя классами намеренно. `.шапка-страницы.подложка::after` задаёт
   синюю заливку и прозрачность для РИСОВАННЫХ уровней, и он весомее одиночного
   `.подложка--рулоны::after`. Из-за этого фотография ложилась поверх синей
   заливки, а слева от неё заливка оставалась — вот та самая «резкая граница».
   Искал её в картинке, а она была в порядке правил. Шрам `[16-08-2026]`. */
.шапка-страницы.подложка--рулоны::after {
  background-color: transparent;
  background-image: url('/static/img/fon-rulony.jpg?v=ec929287');
  background-repeat: no-repeat;
  background-size: 1000px auto;
  /* ⚠ Привязка к НИЗУ, а не к верху. От верха картинка не доставала до низа
     полосы на длинных заголовках — у «Пожарной безопасности» заголовок в четыре
     строки, полоса выше, и снизу выходил ровный обрез. От низа высота полосы
     ничего не ломает: картинка 728 px, любая полоса короче. */
  /* Уходит за правый край: иначе там, где картинка кончается, встаёт ровная
     вертикальная граница — её владелец и видел. */
  background-position: right -40px bottom -166px;
  opacity: 1;
  /* ⚑ Ни маски, ни наложения. Всё, что делало переход, вшито в саму картинку
     (`tools/prepare_foto_rulony.py`): фон полосы впечатан в «бумагу», переход
     слева уходит в тот же цвет. Границе взяться неоткуда — фон изображения
     и фон полосы одно и то же число.
     Наложение «умножение» отсюда убрано намеренно: бумага после обработки
     не строго белая, и умножение оставляло еле заметный прямоугольник. */
  mix-blend-mode: normal;
  -webkit-mask-image: none; mask-image: none;
}
/* ── карусель первого экрана ───────────────────────────────────────────────
   `[задание владельца 29-08-2026]` Три режима смены кадра, переключаются одной
   строкой в `site.json` → `карусель.смена`. Это ОДИН механизм с разными
   переходами, а не три куска кода: разметка, сценарий и состояния общие,
   различаются только правила ниже.

   Устройство состояний. Кадр бывает в трёх положениях:
       покоится   — базовое правило: невидим, без перехода;
       текущий    — видим;
       уходит     — виден и анимируется в небытие, класс снимается по таймеру.
   ⚑ У покоящегося `transition: none` намеренно: когда с ушедшего кадра снимают
   класс, он возвращается в исходное положение МГНОВЕННО и незаметно. Иначе он
   поехал бы обратно на глазах — попятился бы вместо того, чтобы исчезнуть.

   ⛔ Кадры лежат в СЕТКЕ одной клеткой, а не абсолютом. Абсолютные кадры выпали
   бы из потока, и высота полосы схлопнулась бы до нуля, а при смене кадров
   прыгала бы под каждый текст. В одной клетке сетки высота равна самому
   высокому кадру и не меняется вовсе.

   ⚑ Скрытие через `visibility`, а не только прозрачностью: невидимый, но
   «видимый» для браузера кадр держал бы свои ссылки в обходе по Tab — человек
   с клавиатуры проваливался бы в кнопки кадров, которых не видит. */
/* Раскладка: стрелка — кадры — стрелка, точки во второй строке.
   ⚑ Боковые колонки ФИКСИРОВАННОЙ ширины, и место под них держится всегда,
   даже когда стрелки спрятаны (без сценария). Иначе появление стрелок
   сдвигало бы текст вбок уже после того, как человек начал читать.
   ⚠ Цена решения названа честно: текст первого экрана начинается на ширину
   стрелки правее, чем логотип над ним и числа под ним. Другого способа
   поставить стрелку слева нет — она либо двигает текст, либо ложится на него. */
.карусель { position: relative; }

/* ⚑ Две колонки: большой кадр слева, пара карточек справа `[задание владельца
   31-08-2026: «самое дорогое место — первый экран, а площадь используется лишь
   наполовину»]`. Ширина правой колонки задана в `ch`, а не долей: карточка
   с текстом читается по числу знаков в строке, и от доли она то растягивалась
   бы в ленту, то сжималась в столбик.
   ⚠ На узком экране правой колонки нет вовсе `[владелец: «для телефона
   поведение сайта не меняем — там нет свободных площадей»]`. */
.карусель__ряд { display: grid; gap: var(--отступ-2); }
/* ⚑ Колонки РАВНЫЕ: справа такая же карточка, а не уменьшенная. Разница
   между каруселями выражена частотой показа, а не размером — уменьшенная
   правая карточка сказала бы, что она и по сути мельче. */
@media (min-width: 980px) {
  .карусель__ряд { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .карусель__ряд--одна { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 979px) {
  .карусель__ряд > .карусель__колонка:nth-child(2) { display: none; }
}

.карусель__кадры { display: grid; }

/* Стрелки и точки — одной строкой под каруселью `[владелец 31-08-2026]`.
   ⚑ По краям стрелки съедали ширину у самого дорогого места экрана и сдвигали
   текст на 44 px правее логотипа. Внизу они не отнимают ничего, а связь
   «стрелка — указатель» стала прямой: они рядом. */
.карусель__низ {
  display: flex; align-items: center; gap: var(--отступ-0-5);
  margin-top: var(--отступ-2);
}
.карусель__стрелка {
  /* `color: inherit` — по тому же шраму, что и у точек: кнопка не наследует
     цвет текста, у неё своё браузерное умолчание. */
  color: inherit;
  display: flex; align-items: center; justify-content: center;
  width: 2rem; height: 2rem; flex: none;
  padding: 0; border: 0; border-radius: 50%;
  background: transparent; opacity: .6; cursor: pointer;
  transition: opacity .2s ease, background-color .2s ease;
}
.карусель__стрелка[hidden] { display: none; }
.карусель__стрелка:hover { opacity: 1; background: var(--черта-на-тёмном); }
.карусель__стрелка:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }
.карусель__кадр {
  grid-area: 1 / 1;
  opacity: 0;
  visibility: hidden;
  transition: none;
}
.карусель__кадр--текущий { opacity: 1; visibility: visible; z-index: 2; }
.карусель__кадр--уходит  { visibility: visible; z-index: 1; }
.карусель__заголовок {
  font-size: var(--кегль-h1); line-height: 1.15;
  margin: 0 0 var(--отступ-1); max-width: 24ch;
}

/* Перечень внутри кадра: каждый пункт с новой строки `[владелец 31-08-2026:
   «указанные сервисы будут гораздо лучше читаться, если каждый сервис будет
   с новой строки»]`.
   ⚑ Прежде четыре сервиса шли через запятую в одну фразу, и найти в ней
   нужный можно было только прочитав её целиком. Перечень читается взглядом:
   строка = сервис.
   ⚠ Кегль здесь обычный, а не крупный, как у подписи: четыре строки крупным
   поднимают высоту всей полосы первого экрана — кадры лежат в одной ячейке
   сетки, и её высоту задаёт самый высокий. */
.карусель__перечень {
  margin: 0 0 var(--отступ-1); padding: 0; list-style: none;
  display: grid; gap: .375rem; max-width: 44ch;
}
.карусель__перечень li {
  position: relative; padding-left: 1.125rem;
  font-size: var(--кегль-обычный); line-height: 1.45; opacity: .92;
}
/* Точка рисуется краской текста: полоса меняет фон вместе с темой,
   а фирменный цвет на синем читался бы хуже белого. */
.карусель__перечень li::before {
  content: ''; position: absolute; left: 0; top: .55em;
  width: 6px; height: 6px; border-radius: 50%;
  background: currentColor; opacity: .6;
}

/* Слайд: новый приходит справа, старый уезжает влево.
   Прозрачность у уходящего трогается только в самом конце — иначе он растворяется
   на полпути, и движение читается как исчезновение, а не как уход. */
.карусель[data-смена="слайд"] .карусель__кадр { transform: translateX(100%); }
.карусель[data-смена="слайд"] .карусель__кадр--текущий {
  transform: translateX(0);
  transition: transform .55s cubic-bezier(.22,.61,.36,1), opacity .25s ease;
}
.карусель[data-смена="слайд"] .карусель__кадр--уходит {
  transform: translateX(-100%);
  transition: transform .55s cubic-bezier(.22,.61,.36,1), opacity .15s linear .4s;
}

/* Наезд: старый ОСТАЁТСЯ НА МЕСТЕ, новый надвигается справа поверх него
   `[дословно от владельца 29-08-2026: «новый текст наезжает справа, а старый
   не уезжает влево, а остаётся на месте, и новый текст наезжает на него сверху»]`.

   ⚠ Оговорка. Буквальное «наезжает сверху» значило бы непрозрачный
   прямоугольник поверх старого текста — а полоса первого экрана залита
   градиентом и покрыта рисунком-подложкой, и такой прямоугольник был бы
   виден как заплата. Поэтому перекрытие сделано временем, а не краской:
   новый набирает полную непрозрачность к середине пути, старый гаснет на
   месте с задержкой. Движение и порядок слоёв те же, заплаты нет. */
.карусель[data-смена="наезд"] .карусель__кадр { transform: translateX(55%); }
.карусель[data-смена="наезд"] .карусель__кадр--текущий {
  transform: translateX(0);
  transition: transform .6s cubic-bezier(.22,.61,.36,1), opacity .28s ease-out;
}
.карусель[data-смена="наезд"] .карусель__кадр--уходит {
  transform: translateX(0);
  transition: opacity .34s ease-in .2s;
}

/* Проявление: старый гаснет на месте, следом проявляется новый
   `[владелец 29-08-2026: «один текст без движения исчезает, а другой появляется»]`.
   ⚑ Не встречный перелив: у нового задержка. При полном наложении посреди смены
   стоят два полупрозрачных текста друг на друге — читается как рябь. Здесь
   сначала пустое место, потом текст, как и сказано. */
.карусель[data-смена="проявление"] .карусель__кадр { transform: none; }
.карусель[data-смена="проявление"] .карусель__кадр--текущий {
  transition: opacity .4s ease .3s;
}
.карусель[data-смена="проявление"] .карусель__кадр--уходит {
  transition: opacity .34s ease;
}

/* Точки. ⚠ `hidden` объявлен ЯВНО и после `display: flex` — иначе класс
   перебивает атрибут и спрятанное показывается. Шрам `[29-08-2026]`: на этом
   же правиле все подменю в шапке открылись разом. */
/* ⚑ Колонка держит кадры и своё управление вместе `[владелец 31-08-2026:
   «каждый индикатор должен быть под своей карточкой»]`. Управление прижато
   к низу колонки: у карточек разная длина текста, и без этого точки одной
   висели бы посреди высоты другой. */
.карусель__колонка { display: grid; grid-template-rows: 1fr auto; }
.карусель__точки { display: flex; gap: .5rem; align-items: center; }
.карусель__точки[hidden] { display: none; }
.карусель__точки[hidden] { display: none; }
.карусель__точка {
  /* ⚠ `color: inherit` обязателен и стоит первым. Точка — это `<button>`, а
     кнопка НЕ наследует цвет текста: у неё своё умолчание (`buttontext`,
     чёрный). Заливка `currentColor` брала его, и на синей полосе, где всё
     остальное белое, точки выходили чёрными — проверено глазом 29-08-2026. */
  color: inherit;
  width: 34px; height: 5px; padding: 0; border: 0; border-radius: 3px;
  background: currentColor; opacity: .35; cursor: pointer;
  transition: opacity .2s ease, width .2s ease;
}
.карусель__точка:hover { opacity: .6; }
.карусель__точка[aria-current="true"] { opacity: 1; width: 52px; }

/* Цвет отметки текущего кадра `[просьба владельца 29-08-2026]`. Выбирается
   в `site.json` → `карусель.цвет_указателя`; значения именуют ЦВЕТА САЙТА
   из tokens.css, а не произвольные числа — иначе смена палитры прошла бы
   мимо карусели.
   ⚑ Красится только текущая отметка. Незанятые кадры остаются приглушённо
   белыми: если покрасить все, отметка перестанет выделяться, а она и есть
   единственная работа этой полоски. */
.карусель[data-указатель="красный"] .карусель__точка[aria-current="true"] {
  background: var(--акцент);
}
.карусель[data-указатель="фирменный"] .карусель__точка[aria-current="true"] {
  background: var(--фирменный);
}
.карусель__точка:focus-visible { outline: 2px solid currentColor; outline-offset: 3px; }

/* ⚑ Кому движение мешает — тому его нет вовсе: кадры сменяются мгновенно,
   а сценарий вдобавок не листает сам. Точки остаются: листать руками можно. */
@media (max-width: 600px) {
  .карусель__стрелка { width: 1.75rem; height: 1.75rem; }
  .карусель__стрелка svg { width: 18px; height: 18px; }
}

@media (prefers-reduced-motion: reduce) {
  .карусель__кадр,
  .карусель__кадр--текущий,
  .карусель__кадр--уходит { transition-duration: .01ms !important; transform: none !important; }
}

.экран h1 { max-width: 20ch; }
.экран__подпись { font-size: var(--кегль-крупный); opacity: .92; max-width: 56ch; }
.экран__кнопки { display: flex; gap: var(--отступ-1); flex-wrap: wrap; margin-top: var(--отступ-2); }
.экран__числа { display: flex; gap: var(--отступ-3); flex-wrap: wrap; margin-top: var(--отступ-3); }
.число b { display: block; font-size: 2rem; line-height: 1.1; }
.число span { font-size: var(--кегль-мелкий); opacity: .85; }

/* ── секции и карточки ───────────────────────────────────────────────────── */
.секция { padding: var(--отступ-4) 0; }
.секция--мягкая { background: var(--фон-мягкий); }
.секция__шапка { margin-bottom: var(--отступ-2); }
.секция__шапка p { max-width: 62ch; }

.сетка { display: grid; gap: var(--отступ-1); }
.сетка--3 { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.сетка--2 { grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); }

.карточка {
  background: var(--фон); border: 1px solid var(--граница);
  border-radius: var(--скругление); padding: var(--отступ-2);
  display: flex; flex-direction: column; gap: .625rem;
  box-shadow: var(--тень);
}
.карточка h3 { margin: 0; }
.карточка p { margin: 0; color: var(--текст-приглушён); }
.карточка__низ { margin-top: auto; padding-top: var(--отступ-1); }

/* Состав услуги: не абзац, а перечень — так видно, что входит, не читая. */
.состав { margin: .25rem 0 0; padding: 0; list-style: none; display: grid; gap: .375rem; }
.состав li {
  position: relative; padding-left: 1.125rem;
  font-size: var(--кегль-мелкий); color: var(--текст-приглушён); line-height: 1.45;
}
.состав li::before {
  content: ''; position: absolute; left: 0; top: .5em;
  width: 6px; height: 6px; border-radius: 50%; background: var(--фирменный);
}

.метка {
  display: inline-block; font-size: var(--кегль-мелкий); font-weight: 600;
  padding: .125rem .5rem; border-radius: 999px;
  background: var(--фирменный-светлый); color: var(--фирменный-тёмный);
  align-self: flex-start;
}
.метка--скоро { background: var(--фон-метки); color: var(--текст-приглушён); }
.метка--срок  { background: var(--фон-тревога-мягкий); color: var(--акцент-тёмный); }

/* ── сервис: форма и ответ ───────────────────────────────────────────────── */
/* ⚠ `minmax(0, 1fr)`, а не просто сетка `[шрам 30-08-2026]`. У ячейки сетки
   наименьшая ширина по умолчанию — ширина её содержимого, и одна широкая
   таблица растягивала ВЕСЬ блок сервиса за край окна: 616 точек при окне 457.
   Прокрутка у таблицы при этом не помогала — растягивалась не таблица,
   а колонка сетки вокруг неё.
   ⚑ Правило: **у сетки и флекса наименьшая ширина ячейки не ноль.** Если
   внутри есть что-то широкое с собственной прокруткой, ячейке нужно прямо
   разрешить быть у́же содержимого. */
.сервис { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--отступ-2); }
.поле { display: grid; gap: .375rem; }
.поле label { font-weight: 600; font-size: var(--кегль-мелкий); }
.поле input {
  font: inherit; padding: .75rem .875rem; border: 1px solid var(--граница);
  border-radius: var(--скругление-мал); background: var(--фон);
}
.поле input:focus { outline: 2px solid var(--фирменный); outline-offset: 1px; }
.строка-формы { display: flex; gap: var(--отступ-1); align-items: end; flex-wrap: wrap; }
.строка-формы .поле { flex: 1 1 16rem; }

.ответ { border: 1px solid var(--граница); border-radius: var(--скругление); overflow: hidden; }
.ответ__шапка { padding: var(--отступ-1) var(--отступ-2); background: var(--фон-мягкий); border-bottom: 1px solid var(--граница); }
.ответ__тело { padding: var(--отступ-2); display: grid; gap: var(--отступ-1); }
.строка-ответа { display: grid; grid-template-columns: 14rem 1fr; gap: var(--отступ-1); align-items: start; }
.строка-ответа dt { color: var(--текст-приглушён); }
.строка-ответа dd { margin: 0; font-weight: 600; }
.признак { display: inline-flex; align-items: center; gap: .375rem; font-weight: 600; }
.признак--да  { color: var(--успех); }
.признак--нет { color: var(--ошибка); }
.признак--вопрос { color: var(--внимание); }

.оговорка {
  border-left: 3px solid var(--внимание); background: var(--фон-внимание);
  padding: var(--отступ-1) var(--отступ-2); border-radius: 0 var(--скругление-мал) var(--скругление-мал) 0;
}
.оговорка--черновик { border-left-color: var(--фирменный); background: var(--фирменный-светлый); }

/* ── статьи ──────────────────────────────────────────────────────────────── */
/* Расстояние между статьями — вдвое меньше прежнего `[владелец 01-09-2026]`.
   ⚑ Ужимаются ОБА слагаемых: и зазор сетки, и поля строки. Просвет между
   двумя названиями складывается из трёх величин (низ верхней строки + зазор +
   верх нижней), и уменьшить одну из них значило бы срезать треть, а не
   половину. ⚠ `gap` внутри `.статья-строка` — другое: это просвет между
   названием и подписью ВНУТРИ строки, он к расстоянию между статьями
   отношения не имеет и остаётся прежним. */
.список-статей { display: grid; gap: var(--отступ-0-5); }
/* ⛔ «ЕГРЗ в цифрах» из уплотнения ИСКЛЮЧЕНА `[владелец 01-09-2026: «а до
   „ЕГРЗ в цифрах“ оставить прежнее»]`. Она не статья: это страница
   с диаграммами, обновляемая первого числа, и стоит первой строкой блока
   на главной. Просветы вокруг неё держат прежние 48 пикселей — сумму
   из поля строки, зазора сетки и поля соседа; между статьями та же сумма
   стала 24. ⚑ Отсюда видно глазом, где кончается вещь одного рода
   и начинается список другого — без разделительной черты и подзаголовка. */
.статья-строка--витрина {
  /* ⚑ Поля строки прежние, а margin добирает то, что срезал уплотнённый зазор
     сетки и уменьшенное верхнее поле СЛЕДУЮЩЕЙ строки. Значение подобрано
     не на глаз: замерено от текста до текста на выложенном черновике
     (прежние 50 px) и здесь — после правки должно выйти столько же. */
  padding: var(--отступ-1) 0;
  margin-bottom: calc(var(--отступ-1) + var(--отступ-0-5));
}
.статья-строка {
  display: flex; gap: var(--отступ-1); align-items: baseline; flex-wrap: wrap;
  padding: var(--отступ-0-5) 0; border-bottom: 1px solid var(--граница);
}
.статья-строка a { font-weight: 600; text-decoration: none; font-size: var(--кегль-крупный); }
.статья-строка a:hover { text-decoration: underline; }
.текст { max-width: var(--ширина-текста); }
/* Подзаголовок внутри длинного раздела `[01-09-2026]`. У h1–h3 в основе нет
   ВЕРХНЕГО отступа — и это верно там, где заголовок открывает блок. Здесь он
   стоит посреди текста, и без отступа сверху прижимался бы к концу прежнего
   абзаца: подзаголовок читался бы продолжением предыдущей мысли, а не началом
   новой. Первому подзаголовку в блоке отступ не нужен — над ним ничего нет. */
.текст h3 { margin-top: var(--отступ-2); }
.текст > h3:first-child { margin-top: 0; }
.текст table { border-collapse: collapse; width: 100%; }
.текст th, .текст td { border: 1px solid var(--граница); padding: .5rem .75rem; text-align: left; }
.текст th { background: var(--фон-мягкий); }
.текст code { font-family: var(--шрифт-моно); background: var(--фон-мягкий); padding: .1rem .3rem; border-radius: 4px; }

/* ── анализ элементов PDF ──────────────────────────────────────────────────
   Приём файла и таблицы разбора. Всё считается в браузере, поэтому здесь нет
   ни одного состояния «жду ответа сервера» — только «читаю» и «разбираю». */
.пдф-приём {
  border: 2px dashed var(--граница); border-radius: var(--скругление);
  padding: var(--отступ-2); text-align: center; background: var(--фон-мягкий);
  transition: border-color .15s ease, background-color .15s ease;
}
.пдф-приём--ждёт { border-color: var(--фирменный); background: var(--фирменный-светлый); }
.пдф-приём__текст {
  display: flex; gap: var(--отступ-1); align-items: center;
  justify-content: center; flex-wrap: wrap; margin: 0 0 .5rem;
}
.пдф-числа {
  display: flex; gap: var(--отступ-3); flex-wrap: wrap;
  margin: var(--отступ-2) 0;
}
.пдф-числа .число b { color: var(--фирменный); }
.пдф-раздел { margin-top: var(--отступ-2); }
.пдф-раздел h3 { margin: 0 0 .5rem; }
/* ⚠ Высота ограничена намеренно: у проектной документации сотни страниц,
   и полная таблица увела бы низ страницы за горизонт. Прокрутка внутри
   оставляет выгрузку на виду. */
.пдф-прокрутка { max-height: 60vh; overflow-y: auto; }
/* ── просмотр страницы: лист и перечень рядом ─────────────────────────── */
.пдф-выбор {
  display: flex; gap: var(--отступ-1); align-items: center;
  flex-wrap: wrap; margin: 0 0 .5rem; font-size: var(--кегль-мелкий);
}
.пдф-выбор select {
  font: inherit; padding: .375rem .5rem; max-width: 100%;
  border: 1px solid var(--граница); border-radius: var(--скругление-мал);
  background: var(--фон); color: var(--текст);
}
.пдф-легенда { display: flex; gap: .375rem; align-items: center; flex-wrap: wrap; }
.пдф-метка {
  display: inline-block; width: 12px; height: 12px; border-radius: 2px;
  vertical-align: -1px; margin-right: .25rem;
}
.пдф-метка--изобр { border: 2px solid var(--диаг-6); }
.пдф-метка--беда  { border: 2px solid var(--акцент); }

/* ⚠ Две колонки только там, где для листа хватает места. На узком экране лист
   и перечень встают друг под другом: лист, сжатый до половины телефона,
   перестаёт быть листом. */
.пдф-просмотр { display: grid; gap: var(--отступ-1); }
@media (min-width: 900px) {
  .пдф-просмотр { grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); }
}
.пдф-лист {
  position: relative; border: 1px solid var(--граница);
  border-radius: var(--скругление-мал); overflow: hidden; background: var(--фон);
  line-height: 0;
}
.пдф-лист canvas { width: 100%; height: auto; display: block; }
/* ⚑ Рамки — отдельный SVG поверх холста, в его же системе координат
   (`viewBox` = размер холста). Тогда они едут вместе с листом при любом
   размере показа, и пересчитывать их при изменении ширины не нужно. */
.пдф-лист svg {
  position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none;
}
.пдф-лист rect { fill: none; stroke-width: 2; }
.пдф-лист rect.изобр { stroke: var(--диаг-6); }
.пдф-лист rect.беда  { stroke: var(--акцент); }
/* Подсветка по наведению на строку перечня: связь между листом и описанием. */
.пдф-лист rect.видно { stroke-width: 4; fill: currentColor; fill-opacity: .12; }
.пдф-кусок { font-family: var(--шрифт-моно); word-break: break-all; }

.пдф-скан td { background: var(--фон-внимание); }
/* Строка с неправильными символами метится сильнее скана: скан — свойство
   документа, а нечитаемый текст — беда, которую надо чинить. */
.пдф-плохо td { background: var(--фон-тревога); }
.пдф-мало { color: var(--акцент); font-weight: 600; }
.число--тревога b { color: var(--акцент); }

/* ── документы: список и карточки ──────────────────────────────────────────
   Два представления одного перечня `[владелец 30-08-2026]`: список отвечает
   «что есть», карточки — «что это». Оба из одного источника, см. шаблон. */
.документы__список { margin: 0 0 var(--отступ-2); padding-left: 1.25rem; }
.документы__список li { margin: .25rem 0; }

.документы__карточки {
  display: grid; gap: var(--отступ-1);
  grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
}
.документ {
  display: grid;
  /* Превью слева, описание справа `[дословно от владельца: «слева виден
     документ, а справа его краткое описание»]`. Ширина колонки постоянная:
     у документов разные пропорции (лист А4 и широкое свидетельство), и от
     ширины по содержимому текст прыгал бы от карточки к карточке. */
  grid-template-columns: 132px 1fr;
  gap: var(--отступ-1);
  background: var(--фон); border: 1px solid var(--граница);
  border-radius: var(--скругление); padding: var(--отступ-1);
  box-shadow: var(--тень);
}
.документ__вид {
  display: block; align-self: start;
  border: 1px solid var(--граница); border-radius: var(--скругление-мал);
  overflow: hidden; background: var(--фон-мягкий);
  /* ⚑ Постоянная высота окошка при `object-fit: cover` и привязке к верху:
     показывается «шапка» документа — там герб, название и номер, то есть
     ровно то, по чему его узнают. Целиком лист в 132 точки всё равно
     нечитаем, а обрезанный по низу выглядит как страница, а не как марка. */
  height: 168px;
}
.документ__вид img {
  width: 100%; height: 100%; display: block;
  object-fit: cover; object-position: top center;
}
.документ__вид:hover { border-color: var(--фирменный); }
.документ__текст h3 { margin: 0 0 .375rem; font-size: var(--кегль-обычный); }
.документ__текст h3 a { text-decoration: none; }
.документ__текст p { margin: 0 0 .375rem; font-size: var(--кегль-мелкий); }

@media (max-width: 480px) {
  .документ { grid-template-columns: 96px 1fr; }
  .документ__вид { height: 128px; }
}

/* ── подвал ──────────────────────────────────────────────────────────────── */
/* ⚑ Подвал залит той же синей полосой, что и первый экран `[владелец
   29-08-2026: «цвет этой части заменим на синий как фон у карусели»]`.
   Тот же градиент, а не похожий: значения берутся из тех же двух токенов,
   и при смене палитры верх и низ страницы поедут вместе.
   ⛔ Граница сверху убрана: она разделяла серое с белым, а синее с белым
   разделяется само. */
.подвал {
  background: linear-gradient(180deg, var(--полоса-от) 0%, var(--полоса-до) 100%);
  color: var(--текст-на-тёмном);
  padding: var(--отступ-3) 0 var(--отступ-2); margin-top: var(--отступ-4);
}
/* ⚠ Приглушённый текст внутри подвала — свой. Общий `.приглушён` — тёмно-серый,
   он рассчитан на светлый фон; на синей полосе строка «Москва» стала почти
   неразличима. Замечено глазом на снимке 29-08-2026, вместе с переводом
   подвала на синее. */
.подвал .приглушён { color: var(--на-тёмном-приглушён); }

.подвал__знак { display: inline-block; margin-bottom: var(--отступ-2); }
.подвал__знак img { height: 76px; width: auto; display: block; }
@media (max-width: 760px) { .подвал__знак img { height: 56px; } }

.подвал__сетка { display: grid; gap: var(--отступ-2); grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.подвал h4 { margin: 0 0 .5rem; font-size: var(--кегль-обычный); }
.подвал ul { list-style: none; margin: 0; padding: 0; display: grid; gap: .375rem; }
/* ⚠ `inherit`, а не «белый»: цвет один раз назначен полосе выше, и ссылка
   обязана брать его оттуда, а не заводить второе место, где то же решение
   записано ещё раз. */
.подвал a { color: inherit; text-decoration: none; }
.подвал a:hover { text-decoration: underline; }
.подвал__низ {
  margin-top: var(--отступ-2); padding-top: var(--отступ-1);
  border-top: 1px solid var(--черта-на-тёмном);
  color: var(--на-тёмном-приглушён); font-size: var(--кегль-мелкий);
}

/* Знак «Дом на острове» — СПРАВА от последней строки подвала и круглый
   `[владелец 31-08-2026: «высотой в 4 высоты цифр», «сделаем логотип круглым
   и разместим не под, а справа от указанной надписи»]`.
   ⚑ Высота задана в `cap` — это и есть высота прописной буквы и цифры
   в текущем шрифте. Сказано «в четыре высоты цифр», и в стиле написано ровно
   это, а не пересчитанные пиксели: изменится кегль подвала — знак останется
   в том же отношении к строке, рядом с которой стоит.
   ⚠ Строка про `2.8em` — запасная, для браузеров без `cap` (Safari до 16.4).
   0,7 em — отношение высоты цифры к кеглю у наших шрифтов; при 14 px обе
   строки дают одно и то же, около 39 точек. Порядок важен: младший браузер
   не понимает вторую строку и берёт первую.
   ⚑ Знак стоит в строке (`inline-block`), а не рядом с ней в раскладке:
   тогда на узком экране он переносится вместе с текстом и не отрывается
   от него в отдельный столбец.
   ⚠ Круг делается скруглением, а не вырезается в файле: исходник квадратный
   1024×1024 и снят по центру, прозрачность в WebP хранится без потерь
   и весила бы дороже самого рисунка. */
.подвал__остров {
  display: inline-block; vertical-align: middle;
  margin-left: var(--отступ-0-5);
  width: auto; height: 2.8em; height: 4cap;
  border-radius: 50%;
}

/* ── телефон ─────────────────────────────────────────────────────────────────
   Не сжатый настольный, а другой порядок: вертикаль на телефоне дороже всего,
   и всё, что можно, отдаётся содержанию. */
@media (max-width: 760px) {
  :root {
    --кегль-h1: 1.75rem; --кегль-h2: 1.375rem;
    --отступ-4: 2.25rem; --отступ-3: 1.75rem; --отступ-2: 1.25rem;
  }

  .шапка__ряд { flex-wrap: wrap; gap: .625rem; min-height: 0; padding: .625rem 0; }
  .лого img { height: 60px; }
  /* На телефоне назначение уходит под логотип и выравнивается по левому краю:
     справа его прижимать не к чему, там нет второй колонки. */
  .шапка__назначение { order: 3; width: 100%; margin-left: 0;
                       text-align: left; max-width: none; font-size: 1.125rem; }

  /* Полоса меню липнет и на телефоне тоже: адрес страницы владелец просил
     держать на виду, а он живёт здесь же. Логотип с назначением при этом
     по-прежнему уезжают вверх — липнет только полоса. */
  .шапка__низ { padding: .375rem 0; }
  .меню {
    gap: 1.125rem; padding-bottom: .25rem;
    /* край подсказывает, что полоса продолжается */
    -webkit-mask-image: linear-gradient(90deg, #000 88%, transparent 100%);
            mask-image: linear-gradient(90deg, #000 88%, transparent 100%);
  }

  /* ⛔ **Пока подменю открыто, маска снимается.** Маска действует на всё
     поддерево, включая `position: fixed` панель: она стояла на своём месте
     по расчёту, но не рисовалась и не ловила нажатия — маска гасит всё, что
     вне полосы. Полосу в этот момент всё равно не листают, так что подсказка
     о продолжении не нужна. Класс ставит `menu.js`. */
  .меню--раскрыто {
    -webkit-mask-image: none; mask-image: none;
  }

  /* На телефоне панель во всю ширину экрана: `left`/`right` задаются здесь,
     и `menu.js` их не трогает — ставит только `top`. */
  .подменю {
    left: .75rem; right: .75rem; /* top ставит menu.js */
    max-width: none; max-height: 60vh;
  }

  /* Телефон — не строка мелким шрифтом, а нажимаемая кнопка. */
  .шапка__тел {
    margin-left: auto; background: var(--акцент); color: var(--на-акценте);
    padding: .5rem .875rem; border-radius: var(--скругление-мал);
    font-size: var(--кегль-мелкий);
  }

  /* Подложка убрана: на узком экране она всё равно уходит под текст
     и только съедает разборчивость. */
  .подложка::after { display: none; }
  .экран { padding: var(--отступ-3) 0 var(--отступ-4); }
  .экран h1 { max-width: none; }
  .экран__подпись { font-size: var(--кегль-обычный); }
  .экран__кнопки { flex-direction: column; align-items: stretch; }
  .экран__кнопки .кнопка { width: 100%; padding: .875rem 1rem; }

  /* Числа — в две колонки: три в ряд не помещаются, а столбиком занимают экран. */
  .экран__числа {
    display: grid; grid-template-columns: 1fr 1fr; gap: var(--отступ-1) var(--отступ-2);
    margin-top: var(--отступ-2);
  }
  .число b { font-size: 1.375rem; }

  .карточка { padding: var(--отступ-2) var(--отступ-1); }
  .строка-ответа { grid-template-columns: 1fr; gap: .125rem; }
  .сводка { gap: var(--отступ-1); }
  .лента li { grid-template-columns: 4.75rem 1fr; }
}

/* ── статистика посещений (служебная страница /statistika/) ────────────────
   Спецификация — docs/specs/statistika-na-sajte.md

   ⚑ Дописано в конец файла намеренно и своими именами классов. Шрам
   `[16-08-2026]`: полдня ушло на резкую границу подложки, а причиной оказался
   порядок правил, а не картинка. С тех пор новое не вставляется в середину
   к похожему по смыслу и не переиспользует чужие классы: `.вход` уже занят
   формой проверки по ИНН.

   ⚑ Ни одного цвета числом — только токены. Владельцу нынешняя палитра не
   нравится («стили будут другие»), и смена должна оставаться правкой одного
   файла tokens.css. */

.стат { padding-top: var(--отступ-2); padding-bottom: var(--отступ-4); }

.стат-вход {
  display: flex; flex-wrap: wrap; align-items: end; gap: var(--отступ-1);
  margin: var(--отступ-2) 0 var(--отступ-1);
  padding: var(--отступ-1) var(--отступ-2) var(--отступ-2);
  background: var(--фон-мягкий); border: 1px solid var(--граница);
  border-radius: var(--скругление);
}
.стат-вход label { display: block; font-size: var(--кегль-мелкий); font-weight: 600; }
.стат-вход input[type="password"], .стат-вход select {
  font: inherit; padding: .625rem .75rem; margin-top: .25rem;
  border: 1px solid var(--граница); border-radius: var(--скругление-мал);
  background: var(--фон); color: var(--текст); min-width: 12rem;
}
.стат-вход select { min-width: 9rem; }
.стат-вход button {
  font: inherit; font-weight: 600; cursor: pointer;
  padding: .625rem 1.25rem; border-radius: var(--скругление-мал);
  border: 1px solid transparent; background: var(--фирменный); color: var(--на-фирменном);
}
.стат-вход button:hover { background: var(--фирменный-тёмный); }
.стат-вход button:disabled { opacity: .5; cursor: not-allowed; }
.стат-вход .кнопка--тихая {
  background: var(--фон); color: var(--текст-приглушён); border-color: var(--граница);
}
.стат-вход .кнопка--тихая:hover { background: var(--фон); border-color: var(--фирменный); }
.стат-вход .галка {
  display: flex; align-items: center; gap: .4rem; font-weight: 400;
  font-size: var(--кегль-обычный); padding-bottom: .625rem;
}
/* Пароль принят — поле уводится с глаз, но остаётся доступным: период
   переключают часто, а вводить пароль снова не нужно. */
.стат-вход--свёрнут input[type="password"], .стат-вход--свёрнут label[for="пароль"] { display: none; }

.сообщение {
  margin: var(--отступ-1) 0; padding: .75rem var(--отступ-1);
  border-radius: var(--скругление-мал); background: var(--фон-мягкий);
  border-left: 3px solid var(--граница);
}
.сообщение--ошибка { border-left-color: var(--ошибка); background: var(--фирменный-светлый); }
.сообщение--предупреждение { border-left-color: var(--внимание); }

.стат-раздел { margin: var(--отступ-3) 0 0; }
.стат-раздел h2 {
  font-size: var(--кегль-h2); margin: 0 0 var(--отступ-0-5);
  padding-bottom: var(--отступ-0-5); border-bottom: 2px solid var(--фирменный-светлый);
}
.стат-раздел > p { margin: 0 0 var(--отступ-1); }

/* Оговорки идут при числах, а не в конце страницы: число без того, из чего
   оно получено, нечем проверить `[правило проекта]`. */
.оговорки {
  margin: var(--отступ-1) 0 0; padding: var(--отступ-1) var(--отступ-1) var(--отступ-1) var(--отступ-2);
  list-style: disc; background: var(--фон-мягкий); border-radius: var(--скругление-мал);
  font-size: var(--кегль-мелкий); color: var(--текст-приглушён);
}
.оговорки li + li { margin-top: .375rem; }

.плитки {
  display: grid; gap: var(--отступ-1); margin: var(--отступ-1) 0;
  grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr));
}
.плитка {
  background: var(--фон); border: 1px solid var(--граница);
  border-radius: var(--скругление); padding: var(--отступ-1);
  display: flex; flex-direction: column; gap: .25rem;
}
.плитка b { font-size: var(--кегль-h2); line-height: 1.1; color: var(--фирменный); }
.плитка span { font-size: var(--кегль-мелкий); color: var(--текст-приглушён); }

/* Вывод замера текстов согласия `[06-09-2026]`. Стоит ПЕРЕД таблицей и, пока
   решений мало, окрашен как предупреждение: на малых числах один текст
   непременно «выигрывает», и строка «75%» читается как результат раньше, чем
   станет им. Оформление здесь несёт смысл, а не украшает. */
.стат-вывод {
  margin: 0 0 var(--отступ-1); padding: var(--отступ-1);
  border-left: 3px solid var(--фирменный); background: var(--фон-мягкий);
  border-radius: var(--скругление-мал); font-size: var(--кегль-мелкий);
}
.стат-вывод--рано { border-left-color: var(--внимание); }

/* Полоса вместо графика: доля читается глазом, а библиотеки для рисования
   на сайте нет намеренно — зависимость дороже полоски. */
.полоса {
  display: grid; grid-template-columns: 11rem 1fr 8rem; align-items: center;
  gap: var(--отступ-1); padding: .1875rem 0;
}
.полоса__подпись {
  font-family: var(--шрифт-моно); font-size: var(--кегль-мелкий);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.полоса__жёлоб {
  background: var(--фон-мягкий); border-radius: 999px; height: .875rem;
  overflow: hidden;
}
.полоса__жёлоб i { display: block; height: 100%; background: var(--фирменный); border-radius: 999px; }
.полоса__число { font-size: var(--кегль-мелкий); color: var(--текст-приглушён); }

/* ⚠ Прокрутка у самой таблицы, а не у страницы: в таблице визитов цепочка
   страниц длинная, и без этого горизонтальную полосу получал бы весь сайт. */
.таблица-прокрутка { overflow-x: auto; margin: var(--отступ-1) 0; }
.таблица { border-collapse: collapse; width: 100%; font-size: var(--кегль-мелкий); }
.таблица th, .таблица td {
  text-align: left; padding: .5rem .625rem; border-bottom: 1px solid var(--граница);
  vertical-align: top;
}
.таблица th {
  position: sticky; top: 0; background: var(--фон); font-weight: 600;
  border-bottom: 2px solid var(--фирменный-светлый); white-space: nowrap;
}
.таблица tbody tr:hover { background: var(--фон-мягкий); }
.таблица .вправо { text-align: right; white-space: nowrap; }
.таблица .моно { font-family: var(--шрифт-моно); }
.таблица .не-рвать { white-space: nowrap; }

@media (max-width: 760px) {
  .полоса { grid-template-columns: 7rem 1fr; }
  /* Число уходит под полосу, а не жмётся третьей колонкой в 4 знака. */
  .полоса__число { grid-column: 2; margin-top: -.25rem; }
  .стат-вход { padding: var(--отступ-1); gap: var(--отступ-0-5); }
  .стат-вход input[type="password"], .стат-вход select { min-width: 0; width: 100%; }
  .стат-вход label, .стат-вход > * { flex: 1 1 100%; }
}

/* Суточный профиль: 24 столбика в ряд. Полосами это занимало целый экран,
   почти весь — нулями ночных часов, а форма суток при этом не читалась. */
.сутки {
  display: grid; grid-template-columns: repeat(24, 1fr);
  gap: 2px; align-items: end; margin: var(--отступ-1) 0;
}
.сутки__час { display: flex; flex-direction: column; align-items: center; gap: .125rem; }
.сутки__час b {
  font-size: var(--кегль-мелкий); font-weight: 600; color: var(--фирменный);
  min-height: 1.1em; line-height: 1;
}
.сутки__стакан {
  display: flex; align-items: flex-end; width: 100%; height: 5rem;
  background: var(--фон-мягкий); border-radius: var(--скругление-мал);
  overflow: hidden;
}
.сутки__стакан i {
  display: block; width: 100%; background: var(--фирменный);
  border-radius: var(--скругление-мал) var(--скругление-мал) 0 0;
}
.сутки__час--пусто .сутки__стакан i { background: var(--граница); }
.сутки__подпись {
  font-family: var(--шрифт-моно); font-size: .6875rem; color: var(--текст-приглушён);
  min-height: 1em;
}

/* ── ночной режим: то, что не решается одной сменой токенов ─────────────────
   `[просьба владельца 17-08-2026]` Сами цвета — в tokens.css, здесь только
   случаи, где тёмная тема требует иного устройства, а не иного цвета. */

.шапка__право { display: flex; align-items: center; gap: var(--отступ-1); }

/* Кто вошёл — теперь ДВА состояния, оба видны всегда `[решение владельца
   03-09-2026]`. Гостю: «Вход» и «Регистрация» — раздельные ссылки, каждая
   ведёт сразу на свою форму, а не на общую страницу входа с довыбором.
   Вошедшему: имя и «Выйти» — как и раньше. Приглушённое, некрупное: это
   не главное на странице, а справка о состоянии — но справка, которая
   обязана быть под рукой и не пропадать до входа. */
.кто-вошёл {
  display: flex; align-items: center; gap: .6rem; flex: 0 0 auto;
  font-size: var(--кегль-мелкий); white-space: nowrap;
}
/* ⛔ Подчёркнуто ПОСТОЯННО, а не только при наведении `[замечание владельца:
   «вход/регистрация не пункт меню, выделить заметнее — подчёркивание»]`.
   Пункты меню рядом жирные и БЕЗ подчёркивания (см. `.меню a` выше) —
   ровно наоборот. На телефоне наведения не бывает вовсе, и «только при
   наведении» там означало бы «никогда». */
.кто-вошёл a {
  color: var(--фирменный); text-decoration: underline;
  text-underline-offset: .15em;
}
.кто-вошёл a:hover { text-decoration-thickness: 2px; }
.кто-вошёл__черта { color: var(--текст-приглушён); }
/* Та же справка в кабинете, но развёрнутой строкой: здесь у неё есть место
   и есть надобность объяснить, а не только обозначить. */
.кабинет-кто {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--отступ-1); flex-wrap: wrap;
  margin-bottom: var(--отступ-2); padding: .6rem .9rem;
  border: 1px solid var(--граница); border-radius: var(--скругление);
  background: var(--фон-мягкий);
  font-size: var(--кегль-мелкий); color: var(--текст-приглушён);
}
.кабинет-кто b { color: var(--текст); }
.кабинет-кто__выйти { flex: 0 0 auto; }
.кто-вошёл__имя {
  font-size: var(--кегль-мелкий); color: var(--текст-приглушён);
  max-width: 12rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.кто-вошёл__выйти {
  font: inherit; font-size: var(--кегль-мелкий); cursor: pointer;
  padding: .2rem .6rem; border-radius: 999px;
  border: 1px solid var(--граница);
  background: var(--фон-мягкий); color: var(--фирменный);
}
.кто-вошёл__выйти:hover { background: var(--фон); }
/* На узком экране имя прячем, кнопку оставляем: выйти нужно и с телефона,
   а место там дороже, чем повтор имени, которое человек и так знает.
   Ссылки гостя («Вход» / «Регистрация») короткие и остаются всегда —
   прятать в них нечего. */
@media (max-width: 640px) {
  .кто-вошёл__имя { display: none; }
}

.тумблер {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.5rem; height: 2.5rem; padding: 0; cursor: pointer;
  background: var(--фон-мягкий); color: var(--фирменный);
  border: 1px solid var(--граница); border-radius: 999px;
  transition: background .15s, border-color .15s;
}
.тумблер:hover { border-color: var(--фирменный); }
/* Показывается рисунок того, ЧТО ВКЛЮЧИТСЯ по нажатию: днём — луна. */
.тумблер__ночь { display: block; }
.тумблер__день { display: none; }
[data-тема="ночь"] .тумблер__ночь { display: none; }
[data-тема="ночь"] .тумблер__день { display: block; }

/* Знак: синий у него тёмный, и ночью здания слились бы с фоном. Взята вторая
   копия, где синее перекрашено в голубой `[выбор владельца 17-08-2026]`; красный
   в обеих одинаков. Первым решением была белая плашка под знаком — отвергнута
   владельцем: выглядела заплаткой на тёмной шапке. */
.лого__ночь { display: none; }
[data-тема="ночь"] .лого__день { display: none; }
[data-тема="ночь"] .лого__ночь { display: block; }

/* ⚠ Фотография рулонов — единственная картинка, в которую фон полосы
   ВПЕЧАТАН (см. tools/prepare_foto_rulony.py и шрам 16-08). В ночном режиме
   светлый впечатанный фон дал бы ровно ту резкую границу, ради избавления от
   которой его туда и впечатали. Поэтому у ночи свой файл, собранный тем же
   скриптом с тёмным фоном. */
/* ⚠ Селектор повторяет двойной класс `.шапка-страницы.подложка--рулоны`
   намеренно: одиночный `.подложка--рулоны` легче по весу, и правило ночи просто
   не применилось бы — картинка осталась бы дневной. Тот же капкан, что описан
   выше по файлу, и он сработал бы вторично. */
[data-тема="ночь"] .шапка-страницы.подложка--рулоны::after {
  background-image: url('/static/img/fon-rulony-noch.jpg?v=290be260');
}

/* Карта Яндекса приходит своим светлым прямоугольником: её оформление не наше.
   Приглушаем, чтобы она не била по глазам единственным белым пятном. */
[data-тема="ночь"] .карта iframe { filter: brightness(.82) contrast(1.05); }

@media (max-width: 760px) {
  .шапка__право { gap: var(--отступ-0-5); }
}

/* ⚠ Автозаполнение браузера рисует поле своим фоном — почти белым, и в ночном
   режиме форма получает белый прямоугольник. Сами стили при этом верны: фон
   поля тёмный, просто браузер кладёт свой поверх. Обычная тень внутрь его
   перекрывает — другого способа у автозаполнения нет.
   Найдено глазами на своей же странице статистики `[17-08-2026]`: поле было
   белым, а вычисленный стиль показывал тёмный. */
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--текст);
  -webkit-box-shadow: 0 0 0 1000px var(--фон) inset;
          box-shadow: 0 0 0 1000px var(--фон) inset;
  caret-color: var(--текст);
}

/* ── календарь замечаний в кабинете `[замысел владельца 17-08-2026]` ────────
   Два месяца рядом: основной и предыдущий приглушённый. Предыдущий нужен
   первым числам месяца, когда свежих замечаний ещё нет, а висящие с прошлого
   никуда не делись. */
.кал-блок {
  margin-top: var(--отступ-2); padding: var(--отступ-2);
  background: var(--фон-мягкий); border: 1px solid var(--граница);
  border-radius: var(--скругление);
}
.кал-шапка {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: var(--отступ-1); margin-bottom: var(--отступ-1);
}
.кал-шапка h3 { margin: 0; font-size: var(--кегль-h3); }
.кал-управа { display: flex; align-items: center; gap: .5rem; }
.кал-управа select {
  font: inherit; padding: .375rem .5rem; border-radius: var(--скругление-мал);
  border: 1px solid var(--граница); background: var(--фон); color: var(--текст);
}
.кал-шаг {
  font: inherit; cursor: pointer; width: 2rem; height: 2rem; line-height: 1;
  border: 1px solid var(--граница); border-radius: var(--скругление-мал);
  background: var(--фон); color: var(--текст);
}
.кал-шаг:hover { border-color: var(--фирменный); }

/* ⚑ Клетки на треть меньше прежних `[владелец 18-08-2026]`: календарь стоит
   над отчётом по объекту, и его клетки были заметно крупнее клеток отчёта —
   два соседних поля читались как разные по важности, а на экран вместе
   не помещались. */
.кал-тело { display: flex; flex-wrap: wrap; gap: var(--отступ-2); align-items: flex-start; }
/* ⚠ min-width держит два месяца в ряд. Без него соседняя колонка подписей
   сжимала эту до одного месяца, и календарь становился вдвое выше — ровно то,
   от чего уходили. */
.кал-поле { display: flex; flex-wrap: wrap; gap: var(--отступ-1); flex: 0 1 auto; min-width: 27rem; }
.кал-сбоку { flex: 1 1 15rem; min-width: 13rem; }
.кал { flex: 0 1 13rem; min-width: 12.5rem; }
/* Предыдущий месяц приглушён целиком: он вспомогательный, и это должно быть
   видно сразу, без чтения заголовка `[владелец]`. */
.кал--прошлый { opacity: .62; }
.кал__месяц {
  font-weight: 600; margin-bottom: var(--отступ-0-5); text-transform: capitalize;
}
.кал__сетка { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.кал__дн {
  font-size: .6875rem; color: var(--текст-приглушён);
  text-align: center; padding-bottom: .125rem;
}
.кал__дн--вых { color: var(--акцент); }
.кал__день {
  position: relative; display: flex; align-items: center; justify-content: center;
  aspect-ratio: 1 / 1; border-radius: 4px;
  background: var(--фон); font-size: .75rem;
}
.кал__день--пусто { background: transparent; }
.кал__день--вых { background: var(--кал-выходной); }
/* Замечания перекрывают выходной: суббота с висящим замечанием — это прежде
   всего висящее замечание. */
.кал__день--замечания {
  background: var(--кал-замечания);
  box-shadow: inset 0 0 0 1px var(--кал-замечания-край);
  font-weight: 700; cursor: help;
}
.кал__день--замечания i {
  position: absolute; top: 0; right: 2px; font-style: normal;
  font-size: .5625rem; line-height: 1.2; color: var(--кал-замечания-край);
}
.кал__день--сегодня { outline: 2px solid var(--кал-сегодня); outline-offset: -2px; }

.кал-подпись { margin: 0; }
.кал-легенда {
  display: flex; flex-wrap: wrap; align-items: center; gap: .375rem var(--отступ-1);
  margin: var(--отступ-0-5) 0 0; color: var(--текст-приглушён);
}
.кал-обр {
  display: inline-block; width: .875rem; height: .875rem; margin-right: .25rem;
  border-radius: 3px; vertical-align: -2px; background: var(--фон);
}
.кал-обр--замечания { background: var(--кал-замечания); box-shadow: inset 0 0 0 1px var(--кал-замечания-край); }
.кал-обр--вых { background: var(--кал-выходной); }
.кал-обр--сегодня { outline: 2px solid var(--кал-сегодня); outline-offset: -2px; }

@media (max-width: 760px) {
  .кал-блок { padding: var(--отступ-1); }
  /* На телефоне столбцы не помещаются: подписи возвращаются под сетки.
     ⚠ min-width сбрасывается обязательно: он держит два месяца в ряд на
     широком экране, а на узком тем же числом выпихивал страницу за край
     и давал прокрутку вбок. Поймано замером `[18-08-2026]`. */
  .кал-тело { flex-direction: column; gap: var(--отступ-1); }
  .кал-поле { min-width: 0; width: 100%; }
  .кал { flex: 1 1 100%; min-width: 0; }
  .кал__день { font-size: var(--кегль-мелкий); }
}

/* Важная дата на календаре: пунктирная рамка вместо заливки — заливка спорила бы
   с замечаниями, а это разное по смыслу. Замечания — забота организации,
   важные даты — общие для всех. */
.кал__день--важная {
  box-shadow: inset 0 0 0 2px var(--кал-сегодня);
  font-weight: 700; cursor: help;
}
.кал-важное {
  margin: var(--отступ-0-5) 0 0; padding: .5rem .75rem;
  background: var(--фон-внимание); border-left: 3px solid var(--внимание);
  border-radius: var(--скругление-мал); color: var(--текст);
}

/* ── диаграммы витрины ЕГРЗ ───────────────────────────────────────────────
   ⚑ Рисуется инлайновый SVG, а не картинка: подписи в нём — текст, и цвета
   берутся отсюда. Задай их в скрипте — палитра сайта и палитра диаграмм
   разошлись бы на первой правке. */
.диаг { margin: var(--отступ-1) 0 var(--отступ-3); }
.диаг__svg { width: 100%; height: auto; display: block; }
.диаг__подпись { font: 500 12px var(--шрифт); fill: var(--текст-приглушён); }
/* Подписи экспертиз: имена длинные (медиана 86 знаков), поэтому мельче и в две
   строки. Полное имя — в <title>, по наведению. */
.диаг__подпись--мелкая { font-size: 9.5px; }
.диаг__сноска  { font: 500 10px var(--шрифт); }
.диаг__вцвете  { font: 600 12px var(--шрифт); }
.диаг__сетка   { stroke: var(--граница); stroke-width: 1; }

/* Две тепловые карты рядом — так их и просили: государственная и негосударственная.
   На узком экране встают друг под друга, иначе клетки станут нечитаемыми. */
.диаг--пара { display: grid; grid-template-columns: 1fr 1fr; gap: var(--отступ-2); }
.диаг__половина h3 { font-size: var(--кегль-обычный); margin: 0 0 var(--отступ-0-5); }
@media (max-width: 900px) { .диаг--пара { grid-template-columns: 1fr; } }

/* Числа под диаграммой: по картинке нельзя ни сверить, ни процитировать. */
.диаг details { margin-top: var(--отступ-0-5); }
.диаг summary { cursor: pointer; color: var(--текст-приглушён);
                font-size: var(--кегль-мелкий); }
.таблица-диаграммы { width: 100%; border-collapse: collapse; margin-top: var(--отступ-0-5);
                     font-size: var(--кегль-мелкий); display: block; overflow-x: auto; }
.таблица-диаграммы th, .таблица-диаграммы td {
  border: 1px solid var(--граница); padding: .25rem .5rem; text-align: right;
  white-space: nowrap; }
.таблица-диаграммы thead th, .таблица-диаграммы tbody th {
  background: var(--фон-мягкий); text-align: left; }

/* Список организаций-совпадений при поиске по названию: кнопки в столбик,
   потому что названия длинные и в строку не встают. */
.список-выбора { display: grid; gap: .375rem; margin: var(--отступ-0-5) 0; }
.список-выбора .кнопка { text-align: left; justify-content: flex-start;
                         font-weight: 500; }

/* ── всплывающее окно: помощь и списки ────────────────────────────────────
   Одно окно на оба случая: требования к нему владелец назвал одни и те же —
   прокрутка внутри, закрытие по ESC и крестиком. */
.окно {
  width: min(48rem, 92vw); max-height: 82vh; padding: 0;
  border: 1px solid var(--граница); border-radius: var(--скругление);
  background: var(--фон); color: var(--текст); box-shadow: var(--тень-выше);
  overflow: hidden;
}
.окно::backdrop { background: rgba(16, 20, 30, .55); }
.окно__шапка {
  display: flex; align-items: center; justify-content: space-between; gap: var(--отступ-1);
  padding: var(--отступ-1) var(--отступ-2);
  background: var(--фон-мягкий); border-bottom: 1px solid var(--граница);
  position: sticky; top: 0;
}
.окно__имя { font-size: var(--кегль-крупный); line-height: 1.3; }
.окно__закрыть {
  border: 0; background: transparent; color: var(--текст-приглушён);
  font-size: 1.75rem; line-height: 1; cursor: pointer; padding: 0 .25rem;
}
.окно__закрыть:hover { color: var(--текст); }
/* Прокручивается ТЕЛО, а не всё окно: шапка с крестиком обязана оставаться
   на виду — иначе на длинном списке закрывать нечем, кроме ESC. */
.окно__тело { padding: var(--отступ-2); overflow-y: auto; max-height: calc(82vh - 4rem); }
.окно__тело h3 { font-size: var(--кегль-обычный); margin: var(--отступ-1) 0 .25rem; }
.окно__тело ul { margin: .25rem 0 var(--отступ-1); padding-left: 1.25rem; }
.окно__тело li { margin-bottom: .375rem; }

.меню__помощь {
  border: 0; background: transparent; cursor: pointer; padding: 0;
  font: inherit; color: inherit; opacity: .85;
}
.меню__помощь:hover { opacity: 1; text-decoration: underline; }

/* Список объектов в окне */
.объекты { display: grid; gap: .5rem; }
.объекты__строка { border-bottom: 1px solid var(--граница); padding-bottom: .5rem; }
.объекты__шапка { color: var(--текст-приглушён); font-size: var(--кегль-мелкий); }

/* Подпись экспертизы — кнопка: по ней открывается список объектов. Подчёркивание
   пунктиром, потому что сплошное в SVG читается как часть диаграммы. */
.диаг__подпись--щёлкать { cursor: pointer; }
.диаг__подпись--щёлкать:hover, .диаг__подпись--щёлкать:focus {
  fill: var(--фирменный); text-decoration: underline dotted; outline: none;
}

/* ── кнопка «Задать вопрос» и чат ────────────────────────────────────────
   ⚑ Кнопка приклеена к низу справа. Низ экрана у нас свободен: сверху
   прилипшая полоса меню (z-index 30), подменю 20 — кнопке дано 25, чтобы
   она была НАД содержимым, но ПОД раскрытым подменю. Иначе выпавший список
   разделов ложился бы под неё, и пункт в правом нижнем углу становился
   нежатым. */
/* ⚑ Кнопка СЛЕВА `[решение владельца 02-09-2026, образец ex-ko.ru]`: «так её
   лучше видно». У образца тоже левый угол — я в прошлый раз замерил её позицию
   на широком экране и принял отступ справа за привязку, хотя в их правиле
   стоит `left`. Замер положения — не то же, что чтение правила.
   ⚠ Слева важнее ещё и потому, что правый нижний угол на телефонах занимают
   системные жесты и кнопки чужих виджетов. */
.вопрос-кнопка {
  position: fixed; left: var(--отступ-1); bottom: var(--отступ-1); z-index: 25;
  padding: .7rem 1.15rem; border: 0; border-radius: 999px; cursor: pointer;
  background: var(--акцент); color: var(--на-акценте); font: 600 1rem/1 inherit;
  animation: вопрос-пульс 1.5s linear infinite;
}

/* ── полоса согласия ────────────────────────────────────────────────────────
   ⛔ Висит НЕПОДВИЖНО, как кнопка «Задать вопрос» `[требование владельца
   04-09-2026: «полоса должна висеть в одном положении как и кнопка»]`.
   Отсюда `position: fixed`, а не блок в конце страницы: у прокручиваемой
   полосы просьба уезжает вверх и человек её больше не видит — а не увидев,
   он не отказывается, он просто не отвечает.

   ⚑ Обе прижаты к низу и обе `fixed`, поэтому полоса накрыла бы кнопку.
   Кнопку поднимает класс на теле (ниже), а не отрицательный отступ у полосы:
   двигаться должно то, что мешает, а не то, что просит.

   ⚠ z-index 26 — выше кнопки (25), ниже окна вопроса (40). Полоса важнее
   кнопки, пока не отвечена, но раскрытый чат перекрывает её: там человек
   занят делом, ради которого пришёл. */
/* ⛔ Плавающая КАРТОЧКА в углу, а не сплошная полоса во весь низ экрана
   `[замечание владельца 04-09-2026: «просто прямоугольную область на дне
   отсечением пространства, широкая и некрасивая»]`. Разобрано на образце
   sibstroyekspert.pro (`.cookie-notice__inner`): белая карточка со
   скруглением и МЯГКОЙ ТЕНЬЮ большого растяжения — тень и даёт то
   «затемнение по краю», что владелец описал: никакого отдельного слоя
   затемнения там нет, это обычный box-shadow с большим blur.

   ⚑ `--тень-выше` — уже заведённый токен приподнятой карточки, свой для
   дня и ночи. Взят готовый, а не изобретён новый: у прежней полосы тень
   была вписана числами и не менялась с темой — это тоже читалось грубо. */
/* ⛔ ШИРОКАЯ карточка ПО ЦЕНТРУ низа, а не маленькая в углу
   `[поправка владельца 04-09-2026]`: разобрано на sibstroyekspert.pro ещё
   раз, на настоящей ширине компьютерного экрана (1600px, не суженная
   эмуляция) — их видимая полоса центрирована (зазоры слева и справа
   почти равны, ~222 и ~238px из 1600), с потолком ширины 1140px. Угловая
   вертикальная вкладка «Задать вопрос» у них — СОВСЕМ ДРУГОЙ элемент,
   не совмещённый с полосой согласия. Прошлая версия ошибочно попала на
   их же адаптивную раскладку под более узкий экран, где полоса действительно
   уходит в угол, — и была принята за целевую.

   ⚑ Центрирование — `left: 50%; translateX(-50%)`, а не `margin: 0 auto`
   на fixed-элементе: `position: fixed` не участвует в потоке, авто-отступы
   для него не считаются, а точка привязки `left/right/top/bottom` — единственный
   рабочий способ. */
/* ⛔ Один ряд ВСЕГДА, без попытки переключать раскладку по ширине
   `[владелец 04-09-2026, после пяти неудачных заходов через
   flex-wrap/flex-grow/@container в тот же день]`: текст слева, кнопки
   справа, и точка. Каждая попытка «переносить кнопки вниз, когда тесно»
   натыкалась на новый нюанс раскладки (медиа-запрос по экрану вместо
   карточки, третий элемент в общем потоке, гипотетическая непереносимая
   ширина абзаца при `flex-basis: auto`) — простое устройство без ветвлений
   не может разойтись само с собой. */
.полоса-согласия {
  position: fixed; left: 50%; bottom: var(--отступ-1);
  transform: translateX(-50%);
  z-index: 26;
  width: min(69rem, calc(100vw - 2 * var(--отступ-1)));
  display: flex; align-items: center; gap: var(--отступ-2);
  padding: var(--отступ-2); padding-right: calc(var(--отступ-2) + 1.75rem);
  background: var(--фон);
  border: 1px solid var(--граница);
  border-radius: var(--скругление);
  box-shadow: var(--тень-выше);
}
/* ⚠ Здесь стоял комментарий «текст и кнопки ВСЕГДА друг под другом» — он
   устарел `[исправлено 07-09-2026]`. Так было до 05-09; потом владелец
   решил иначе: «давай сделаем все же их справа и увеличим ширину полосы в
   полтора раза». Код с тех пор держит один ряд, а комментарий остался от
   прежнего поколения и утверждал обратное коду. История прежних заходов —
   в `docs/CHANGELOG.md` за 04-09-2026, здесь ей не место.

   Как устроено сейчас: на широком экране один ряд — текст слева, кнопки
   справа; на узком (ниже) — столбиком. */
.полоса-согласия__текст { flex: 1 1 auto; min-width: 0; }
.полоса-согласия__текст p { margin: 0; font-size: var(--кегль-мелкий); }
.полоса-согласия__текст p + p { margin-top: .4rem; }
/* Напоминание о сроке — единственное, что здесь выделено: человек уже
   соглашался, и это объясняет, почему его спрашивают снова. */
.полоса-согласия__срок { color: var(--текст); }
.полоса-согласия__просьба { color: var(--текст-приглушён); }
.полоса-согласия__кнопки { display: flex; gap: var(--отступ-1); flex: 0 0 auto; }

/* ⛔ Узкий экран — столбиком. И это НЕ шестой заход на отвергнутый условный
   перенос `[замер на телефоне 07-09-2026]`.

   ⚑ Почему прежние заходы срывались, а этот нет. Ширина карточки —
   `min(69rem, 100vw - 2 * отступ)`. Две половины этого `min` расходятся
   ТОЛЬКО когда экран шире ~1136px: там карточка упёрта в 69rem и уже экрана,
   поэтому вопрос «широко ли» про экран и про карточку имел РАЗНЫЕ ответы —
   на этом всё и ломалось. Ниже 1136px карточка равна экрану минус отступы,
   то есть они связаны намертво. Порог здесь 48rem — глубоко в той области,
   где расхождения нет по построению, и промахнуться правилу негде.

   ⚑ Почему 48rem, а не на глаз. Ряду нужно 393px независимо от экрана:
   кнопки 293 плюс зазор и поля карточки. Значит текст получает хотя бы
   половину карточки только начиная примерно с 790px. Замер на 645px:
   у текста 38%, у кнопок 48% — работает, но перекошено. 48rem (768px) —
   ближайшая круглая граница ниже той, где ряд становится соразмерным,
   и заодно накрывает планшет в книжной ориентации.

   ⛔ Что было замерено на телефоне (375×812) до этой правки: **ширина текста
   0 пикселей**. Кнопки занимают 293px, плюс отступы и место под крестик —
   это уже больше карточки в 343px; `min-width: 0` честно позволяет тексту
   сжаться в нуль, и он осыпается по букве на 314px в высоту. Полоса съедала
   44% экрана телефона. Владелец описал это как «текст прижат к левой границе,
   занимая лишь четверть площади, а кнопки по середине высоты» — кнопки
   и правда стояли посередине: `align-items: center` центрировал их против
   трёхсотпиксельного столбца букв.

   ⚑ Кнопки по своей ширине, а боковые поля урезаны `[замерено 07-09-2026]`.
   Сперва стояло «поровну» (`flex: 1 1 0`) ради одинакового размера — и на
   телефоне «Не разрешать» переносилось в две строки, разнося обе кнопки на
   77px в высоту. Причина в числах: на половину ряда приходится 128px, а этой
   надписи с обычными полями нужен 151. Урезанные поля дают 103 и 127 — обе
   в одну строку, и вместе с зазором это 246 из 273 доступных, то есть с
   запасом, а не впритык.

   ⚠ Ширины стали разными, и это НЕ послабление к отказу. Обещание — равная
   ТРУДНОСТЬ: одно нажатие, рядом, одного роста, обе видны без прокрутки.
   Надпись «Не разрешать» длиннее слова «Разрешить», и место под неё шире
   ровно на эту разницу; если что, шире оказалась кнопка отказа, а не
   согласия. Разница в заметности (цвет у «да») остаётся намеренно —
   она говорит, какое действие обычное, и давлением не является. */
@media (max-width: 48rem) {
  .полоса-согласия {
    flex-direction: column;
    align-items: stretch;
    gap: var(--отступ-1);
  }
  .полоса-согласия__кнопки .кнопка { padding-left: .625rem; padding-right: .625rem; }
}
/* ⛔ Крестик — ВНЕ общего flex-потока текста и кнопок `[найдено при
   отладке 04-09-2026]`. Он был третьим flex-элементом в общем ряду, и с ним
   решение «переносить кнопки на свою строку или нет» переставало совпадать
   с простым расчётом по ширине текста и кнопок: браузер вправе перенести
   ЛЮБОЙ из трёх элементов, а не обязательно средний, и в паре случаев
   переносил кнопки, даже когда для них двоих с текстом места хватало —
   потому что считал уже с оглядкой на третий элемент дальше по потоку.
   Крестик к переносу текста и кнопок отношения не имеет: он всегда в углу
   карточки, независимо от того, уместились ли они в один ряд или в два.
   Абсолютное позиционирование внутри позиционированной `.полоса-согласия`
   (она `position: fixed`, значит уже сама — контекст для потомков) убирает
   его из расчёта ширины совсем. Справа в базовом правиле карточки добавлен
   запасной `padding-right`, чтобы текст не заезжал под крестик. */
.полоса-согласия__закрыть {
  position: absolute; top: var(--отступ-1); right: var(--отступ-1);
  background: none; border: 0; cursor: pointer;
  color: var(--текст-приглушён); font-size: 1.5rem; line-height: 1;
  padding: 0 .25rem;
}
.полоса-согласия__закрыть:hover { color: var(--текст); }
/* ⚑ Обе кнопки — `flex: 1 1 0` ДРУГ ОТНОСИТЕЛЬНО ДРУГА, поэтому они всегда
   поровну, независимо от того, сколько всего места досталось их общему
   ряду. Растягивать сам ряд `.полоса-согласия__кнопки` на всю ширину
   карточки при переносе — отдельная забота, которую здесь решать не стал:
   исходная жалоба была про «Не разрешать» УЕЗЖАЮЩУЮ ЗА КРАЙ (переполнение),
   а не про то, что ряд не во всю ширину. Пока обе кнопки равны друг другу
   и в границах карточки — выбор одинаково лёгок; растягивать ряд можно
   отдельным шагом, если понадобится именно это. */

/* Кнопка вопроса уходит выше полосы, пока та висит.

   ⛔ Подъём берётся из ИЗМЕРЕННОЙ высоты полосы (`soglasie.js` кладёт её в
   `--полоса-согласия-высота`), а не задан числом. Числом было — и кнопка
   осталась внутри полосы: высота плавает от одной строки до трёх, смотря по
   ширине экрана и по тому, показано ли напоминание о сроке `[найдено в
   браузере 04-09-2026]`. Тот же урок, что с якорями: замеренная величина
   верна только для того случая, в котором её замерили.

   ⚠ Запасное значение в `var()` — на случай, если сценарий не успел измерить.
   Оно заведомо велико: лучше кнопка выше нужного, чем под полосой. */
.с-полосой-согласия .вопрос-кнопка {
  /* Карточка теперь ПО ЦЕНТРУ, а кнопка вопроса — в своём углу слева
     `[поправка владельца 04-09-2026]`: на обычном десктопе они физически
     не пересекаются по горизонтали и подъём не обязателен. Но карточка сама
     сужается формулой `width: min(46rem, 100vw − 2×отступ)` и на узком
     экране занимает почти всю ширину, включая тот же угол — там подъём
     снова нужен. Правило оставлено безусловным: на широком экране кнопка
     просто повиснет чуть выше, чем строго необходимо, а это не ошибка,
     а лишние 3 см воздуха, которые никому не мешают.

     Отступ снизу у карточки — тот же --отступ-1, что и раньше; формула
     подъёма не менялась, она зависит только от высоты карточки и отступа,
     не от того, где карточка стоит по горизонтали. */
  bottom: calc(var(--отступ-1) * 2 + var(--полоса-согласия-высота, 16rem));
}

/* Расходящееся кольцо — тем же приёмом, что у образца: тень без размытия,
   у которой растёт РАСТЯЖЕНИЕ, а цвет гаснет. Кольцо ничего не занимает
   в потоке и не сдвигает соседей: тень не участвует в раскладке.

   ⛔ Цвет — АКЦЕНТ (красный), а не фирменный синий `[замер 02-09-2026]`.
   Сперва и кнопка, и кольцо были синими — и на синих полосах сайта (первый
   экран, подвал) пропадали почти совсем: синее на синем. Просили ровно
   об обратном. Красный — тот же цвет, которым на сайте отмечены кнопки
   действия, и он читается и на белом, и на синем.
   ⚑ Прозрачность берётся из токена через `color-mix`, а не вписывается
   числами: иначе красный жил бы в двух местах и разошёлся бы при первой
   же правке палитры. В ночной теме `--акцент` другой, и кольцо поедет
   за ним само. */
@keyframes вопрос-пульс {
  0%   { box-shadow: 0 0 0 0    color-mix(in srgb, var(--акцент) 70%, transparent); }
  70%  { box-shadow: 0 0 0 15px color-mix(in srgb, var(--акцент) 0%, transparent); }
  100% { box-shadow: 0 0 0 0    color-mix(in srgb, var(--акцент) 0%, transparent); }
}

/* ⛔ У того, кто просил не двигать на экране лишнего, кольцо не пульсирует.
   Бесконечное движение — первое, что мешает при укачивании и при расстройствах
   внимания, и системная настройка заведена ровно про это. Кнопка не пропадает
   и не теряет заметности: вместо пульса ей даётся постоянное кольцо. */
@media (prefers-reduced-motion: reduce) {
  .вопрос-кнопка {
    animation: none;
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--акцент) 35%, transparent),
                var(--тень);
  }
}
.вопрос-кнопка:hover { filter: brightness(1.07); }
.вопрос-кнопка:focus-visible { outline: 3px solid var(--фирменный); outline-offset: 3px; }

.вопрос-окно {
  /* Затемнение — то же значение, что у `.окно::backdrop`. Второй оттенок
     той же маски читался бы как другая вещь и разошёлся бы при первой правке. */
  position: fixed; inset: 0; z-index: 40; background: rgba(16, 20, 30, .55);
  display: flex; align-items: flex-end; justify-content: center;
}
.вопрос-окно[hidden] { display: none; }
/* ⛔ Окно — КОНТЕЙНЕР для своей раскладки `[шрам 02-09-2026]`. Правила
   «для компьютера» я сначала писал через `@media`, то есть по ширине ЭКРАНА.
   Стоило сузить окно вдвое — и на широком экране в узкое окно применились
   широкие правила: текст сжался в колонку в два слова, кнопка отняла у него
   половину, появилась прокрутка вбок.
   ⚑ Ширину окна человек меняет сам, растягивая за угол; раскладка обязана
   следовать за ОКНОМ, а не за экраном, иначе она врёт при каждом растягивании. */
.вопрос-окно__короб {
  container-type: inline-size;
  background: var(--фон); width: min(100%, 44rem); max-height: 92vh;
  border-radius: var(--скругление) var(--скругление) 0 0;
  display: flex; flex-direction: column; overflow: hidden;
}
@media (min-width: 760px) {
  .вопрос-окно { align-items: center; }
  .вопрос-окно__короб {
    /* ⛔ На компьютере окно ШИРОКОЕ по умолчанию `[решение владельца
       02-09-2026: «ширину даже по умолчанию взять в 80–85 % ширины экрана»]`.
       Сорок четыре em были рассчитаны на чтение текста в одну колонку,
       а здесь переписка: сообщения у́же ленты, и подложке нужно место,
       иначе её не видно — а ради неё всё и затевалось. */
    /* ⛔ Узкое и ВЫСОКОЕ `[решение владельца 02-09-2026: «вдвое уже и втрое
       выше»]`. Переписку читают колонкой: широкое окно растягивает строку
       так, что глаз теряет начало следующей, а низкое показывает две записи
       и заставляет прокручивать после каждого ответа.
       ⚠ Высота задана ЖЁСТКО (`height`), а не пределом (`max-height`):
       предел позволял окну съёживаться до содержимого, и на двух записях
       оно было втрое ниже экрана — ровно то, что владелец и увидел. */
    width: min(96vw, max(30rem, 42vw));
    height: 86vh;
    border-radius: var(--скругление); max-height: 86vh;
    /* ⚑ Окно тянется за угол `[замысел владельца 02-09-2026]`. Средство
       браузерное: `resize` рисует ухватку в правом нижнем углу сам, своей
       мышью не надо — и она сразу работает и с клавиатуры, и на планшете.
       ⛔ Обязателен `overflow: auto` на том же узле: без него `resize`
       не действует вовсе — это требование самого свойства, а не наша
       прихоть. Прокрутка при этом не появляется: внутри всё в своих
       рамках, и коробу прокручивать нечего.
       ⚠ Только на широком экране. На телефоне окно и так во всю ширину,
       тянуть его некуда, а ухватка в углу перекрыла бы поле ввода. */
    resize: both; overflow: auto;
    min-width: 22rem; min-height: 18rem;
    max-width: 96vw;
  }
}
.вопрос-окно__шапка {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--отступ-1); padding: var(--отступ-1);
  border-bottom: 1px solid var(--граница);
}
.вопрос-окно__шапка h2 { margin: 0; font-size: var(--кегль-h3); }
/* Поле поиска забирает свободное место между заголовком и крестиком.
   ⚠ На узком экране оно уходит на свою строку целиком: втиснутое рядом
   с заголовком, оно становится в два слова шириной и бесполезно. */
.вопрос-поиск {
  flex: 1 1 8rem; min-width: 0; font: inherit;
  padding: .35rem .6rem; border: 1px solid var(--граница);
  border-radius: var(--скругление-мал);
  background: var(--фон); color: var(--текст);
}
/* ⛔ Порог узкой шапки считается по ОКНУ, а не по экрану `[шрам 03-09-2026]`:
   окно перетаскивается за угол, и шапка обязана перестраиваться вместе с ним.
   ⚑ Заголовок сделан сжимаемым, а промежутки — вдвое меньше. Без этого
   на телефоне шапка ложилась в ТРИ строки (заголовок и «↑», потом «↓» и «×»,
   потом поиск) и съедала девяносто пикселей из семисот — при том что владелец
   как раз просил убрать пустые пространства. */
@container (max-width: 32rem) {
  .вопрос-окно__шапка { flex-wrap: wrap; gap: var(--отступ-0-5); }
  .вопрос-окно__шапка h2 { flex: 1 1 6rem; min-width: 0; font-size: var(--кегль-крупный); }
  .вопрос-поиск { order: 3; flex-basis: 100%; }
}
.вопрос-окно__закрыть {
  border: 0; background: none; font-size: 1.75rem; line-height: 1;
  cursor: pointer; color: var(--текст-приглушён); padding: 0 .25rem;
}
/* Кружок с «?» — тот же приём, что у остальных мелких кнопок шапки
   (стрелки поиска): узнаваемый знак вместо слова экономит место рядом
   с заголовком, а `title`/`aria-label` называют её словами для остальных. */
.вопрос-окно__помощь {
  flex: 0 0 auto; width: 1.75rem; height: 1.75rem;
  border: 1px solid var(--граница); border-radius: 50%; background: var(--фон);
  color: var(--текст-приглушён); font: 700 .9rem/1 inherit; cursor: pointer;
}
.вопрос-окно__помощь:hover { background: var(--фон-мягкий); color: var(--фирменный); }

/* ⛔ Прокручивается ЛЕНТА, а не всё окно: поле для вопроса должно оставаться
   на виду, пока человек читает чужие. Иначе, дочитав до конца, он не найдёт,
   куда писать, — а именно за этим и пришёл. */
/* ⛔ Боковые поля вдвое шире и РАСТУТ вместе с окном `[решение владельца
   02-09-2026: «отступы с боков увеличить вдвое и делать шире, если окно
   расширяем — так будет органичнее»]`. Постоянные поля на растянутом окне
   выглядят прижатыми к краям: содержимое расползается, а рамка остаётся
   прежней. `clamp` держит нижнюю и верхнюю границы, а между ними поле
   считается долей ширины — то есть само следует за растягиванием.
   ⚠ Сверху и снизу поля НЕ растут: там место дорого, а прибавка ничего
   не даёт — вертикаль в окне и так короткая. */
/* ⛔ Лента — ПОДЛОЖКА, сообщения на ней светлые `[подход владельца
   02-09-2026, образец — телеграм]`. Пока фон ленты был того же цвета, что
   и записи, глазу не за что было зацепиться: белое на белом не образует
   «мест», где лежит сообщение. Тёмная подложка делает эту работу сама,
   до всякого чтения.
   ⚑ Отсюда же и книжный узор становится осмысленным: он лежит НА подложке,
   а не под текстом. */
/* ⛔ Окно прокрутки и список — РАЗНЫЕ узлы `[найдено при проверке
   03-09-2026: «фон заканчивается чуть раньше, чем размещается последний
   ответ»]`. `.вопрос-лента` — короб с прокруткой, его высота равна высоте
   ОКНА. Подложка, повешенная на нём самом, обрывалась бы на границе окна —
   что и произошло: узор кончался там, где кончалась первая «страница»,
   а список к этому моменту был уже длиннее. Подложка живёт на
   `.вопрос-лента__список` ниже — блоке без собственной прокрутки, чья
   высота равна высоте СОДЕРЖИМОГО и растёт вместе с ним. */
.вопрос-лента {
  flex: 1 1 auto; overflow-y: auto;
  background: var(--фон-мягкий);
}
/* ⛔ Отступ — НА СПИСКЕ, а не на окне прокрутки `[найдено при проверке
   03-09-2026: «сообщения прижимаются к верхнему, нижнему и боковым краям
   контейнера с фоном, должны быть отделены полосой фона»]`. Подложка
   (`::before` ниже) — это ровно рамка списка: `inset:0` заливает её ДО
   самого края. Отступ раньше стоял на окне прокрутки — на ДРУГОМ узле, чем
   подложка, — и рамки вокруг записей не оставалось: список начинался
   вплотную к краю окна, а запись — вплотную к краю списка. Отступ и
   подложка обязаны жить на одном узле, иначе один не создаёт рамку другому.
   ⚑ `box-sizing: border-box` обязателен вместе с `min-height: 100%` ниже:
   без него отступ добавился бы СВЕРХ ста процентов высоты окна, и короткий
   список ушёл бы в прокрутку на пустом месте. */
.вопрос-лента__список {
  display: grid; gap: var(--отступ-0-5);
  align-content: start;
  position: relative; isolation: isolate;
  box-sizing: border-box;
  padding: var(--отступ-1) clamp(var(--отступ-1), 4%, var(--отступ-3));
  /* Список короче окна (мало записей) — подложка всё равно заполняет
     окно целиком, а не обрывается сразу под последней записью: пусть
     список растянется хотя бы на высоту окна. Список длиннее окна —
     `min-height` не мешает расти дальше, и подложка растёт вместе с ним. */
  min-height: 100%;
}

/* ⛔ Вопрос — на БЕЛОМ, а не на книжном фоне `[решение владельца]`. Читать
   поверх рисунка труднее, чем кажется: узор спорит с буквами именно там,
   где текст важнее всего. Книжный фон остаётся видимым в промежутках между
   записями — то есть там, где он украшает, а не мешает.
   ⚑ Отсюда же смысл плотных блоков: чем меньше воздуха ВНУТРИ, тем больше
   фона МЕЖДУ — и рисунок работает, не мешая чтению. */
/* ⚠ Сообщение У́ЖЕ ленты — иначе подложки не видно нигде, кроме зазоров
   `[требование владельца: фон должен занимать 25–30 % площади]`. На узком
   экране предел снимается: там дорога каждая строка, и подложка ради
   красоты съедала бы текст. */
.вопрос-лента .вопрос {
  background: var(--фон);
  border: 1px solid var(--граница);
  border-radius: var(--скругление);
  padding: .4rem .6rem;
  box-shadow: var(--тень);
}
/* ⛔ Порог — РОВНО минимальная ширина окна `[найдено при проверке 03-09-2026:
   «сообщения прижаты к стенкам контейнера с фоном, не погружены в среду
   фона»]`. Окно чата не бывает у́же 30rem (см. `max(30rem, 42vw)` у
   `.вопрос-окно__короб`), а это правило включалось только с 34rem. Между
   30rem и 34rem окно уже открыто «по-настольному», а запись всё ещё тянется
   на всю ширину подложки — мёртвая зона в 64 пикселя, где подложки не видно
   нигде, кроме зазоров между записями. Порог опущен до фактического пола
   окна: мёртвой зоны больше нет ни при каком открытии. */
@container (min-width: 30rem) {
  .вопрос-лента .вопрос { max-width: 78%; }
  /* Ответ эксперта чуть сдвинут вправо: в переписке отвечающий и спрашивающий
     стоят по разные стороны, и сдвиг говорит это без единого слова. */
  .вопрос-лента .вопрос--от-эксперта { margin-left: auto; }
}

/* ── книжный фон ленты `[замысел владельца 02-09-2026]` ────────────────────
   Рисунок ЗАМОЩАЕТСЯ, а не растягивается: «заполнить этим рисунком всё поле
   чата m*n повторений». Ширина куска задана в пикселях (`260px auto`),
   поэтому на любом окне рисунок остаётся мелким — при растягивании
   он стал бы тем крупнее, чем шире окно, то есть ровно наоборот просьбе.

   ⛔ Взят `illustrated-bookshelf`, а НЕ `__bookshelf-silhouette` из задания
   `[замер 02-09-2026]`: на силуэте и на `bookshelf-row` стоит водяной знак
   стоковой службы («dreamstime» поперёк середины). Он виден и означает, что
   файл — пробник без прав. Третья картинка чистая, и владелец сам назвал её
   среди пригодных.

   ⛔ Рисунок кладётся ФОНОМ, а не маской — в отличие от прочих подложек
   проекта `[замер 02-09-2026]`. Маска берёт форму из альфа-канала, а у этой
   картинки альфы нет вовсе: она обычная, непрозрачная. Маской из неё
   не видно ничего — проверено в браузере, файл отдавался (200, 21 КБ),
   а на экране было пусто. Приём проекта верен для силуэтов с прозрачностью;
   здесь другой исходник — значит и приём другой.

   ⚠ Отсюда следствие: цвет НЕ идёт за темой сам, и ночную прозрачность
   приходится задавать отдельно. Картинка светлая: на тёмном фоне при той же
   прозрачности она светилась бы вдвое заметнее текста.

   ⚠ Кусок не бесшовный: книги по краям обрезаны, и при замощении стык
   различим, если приглядываться. При такой прозрачности это читается
   как узор, а не как ошибка; ровный шов потребовал бы перерисовки. */
.вопрос-лента__список::before {
  content: ''; position: absolute; inset: 0; z-index: -1;
  background-image: url('/static/img/fon-chat-polki.webp?v=01f7ec5b');
  background-repeat: repeat;
  /* ⚑ Кусок вдвое у́же `[решение владельца 02-09-2026: «книги вдвое меньше,
     добавляем 2m и 2n»]` — то есть повторений вчетверо больше: вдвое
     по горизонтали и вдвое по вертикали, ведь высота задана `auto`
     и следует за шириной. Мелкий рисунок и читается как фактура, а не как
     картинка, которую пытаются рассмотреть. */
  background-size: 130px auto;
  /* ⚑ Фон СУЩЕСТВЕННО заметнее `[решение владельца 02-09-2026]`. Раньше он
     держался бледным по необходимости: текст лежал прямо на нём, и узор
     спорил с буквами. Теперь записи на своём белом фоне, читать поверх
     рисунка не приходится — и сдерживать его больше незачем.
     ⚠ Ночью доля меньше: светлый рисунок на тёмном ярче при той же
     прозрачности, и одинаковое число дало бы днём узор, а ночью решётку. */
  opacity: .38;
  pointer-events: none;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-тема="день"]) .вопрос-лента__список::before { opacity: .18; }
}
:root[data-тема="ночь"] .вопрос-лента__список::before { opacity: .18; }
/* ⚠ Разделительной черты больше нет: записи отделены собственным фоном
   и промежутком, а черта поверх этого была третьим способом сказать то же. */
.вопрос { border-bottom: 0; }
.вопрос__кто { margin: 0 0 .15rem; }
.вопрос__текст { margin: 0; }
/* ⛔ Жирный ТОЛЬКО когда ответ в той же карточке `[решение владельца
   03-09-2026]`. Класс ставится в JS ровно при этом условии (`строкаЛенты`
   в vopros.js) — здесь только начертание, решение уже принято там. */
.вопрос__текст--с-ответом { font-weight: 700; }
.вопрос__ждёт { margin: .2rem 0 0; font-style: italic; }
/* Ответ центра отбит полосой слева — это не просто «ещё абзац», а другая
   сторона разговора, и видно это должно быть до чтения. */
/* ⛔ Ответ отличается от вопроса ФОНОМ, а не только полосой слева
   `[решение владельца 02-09-2026: «фон должен заметнее различаться
   в вопросах и в ответах… давай попробуем слабый оттенок синего из нашей
   гаммы»]`. Прежде ответ был на сером `--фон-мягкий` — он задуман как
   «чуть иначе, чем обычно», и в ленте, где половина записей ответы,
   этой разницы не хватало: полоса слева видна, только если приглядеться
   к краю, а глаз читает плоскость.
   ⚑ `--фирменный-светлый` — тот самый слабый синий: днём светло-голубой,
   ночью приглушённый тёмно-синий. Он идёт за темой сам, и второй цвет
   для ночи заводить не надо. */
/* ⛔ Ответ теперь СВЕТЛЫЙ, как и вопрос `[решение владельца 02-09-2026]`.
   Голубой фон ответа спорил с подложкой и почти сливался с нею; а главное —
   различать вопрос и ответ фоном самого сообщения незачем, когда все
   сообщения должны читаться как «места на подложке». Различие переносится
   внутрь: цитата вопроса заливается голубым.
   ⚑ Полоса слева остаётся: она говорит «это ответ» и на узком экране,
   где сдвига вправо нет. */
.вопрос__ответ {
  margin: .375rem 0 0; padding: .375rem .5rem .375rem var(--отступ-0-5);
  border-left: 3px solid var(--фирменный); background: transparent;
  border-radius: 0;
}
.вопрос__ответ p { margin: 0 0 .25rem; }
.вопрос__ответ p:last-child { margin: 0; }

.вопрос-окно__подвал {
  border-top: 1px solid var(--граница); padding: var(--отступ-1);
  background: var(--фон-мягкий); max-height: 60vh; overflow-y: auto;
}
.вопрос-форма { display: grid; gap: var(--отступ-0-5); }
.вопрос-форма .поле { display: grid; gap: .25rem; }
.вопрос-форма .поле span { font-size: var(--кегль-мелкий); color: var(--текст-приглушён); }
.вопрос-форма input, .вопрос-форма textarea {
  font: inherit; padding: .5rem .625rem; border: 1px solid var(--граница);
  border-radius: var(--скругление-мал); background: var(--фон); color: var(--текст);
  width: 100%;
}
.вопрос-форма textarea { min-height: 5.5rem; resize: vertical; }
.вопрос-форма .галочка {
  display: flex; gap: .5rem; align-items: flex-start;
  font-size: var(--кегль-мелкий); line-height: 1.4;
}
.вопрос-форма .галочка input { width: auto; margin-top: .15rem; flex: 0 0 auto; }
.вопрос-ряд { display: flex; gap: var(--отступ-0-5); flex-wrap: wrap; }
.вопрос-сообщение { margin: .25rem 0 0; font-size: var(--кегль-мелкий); }
.вопрос-сообщение--худо { color: var(--ошибка); }
/* Гнездо капчи: своя высота, чтобы форма не подпрыгивала, когда виджет
   догрузится. Без неё кнопка «Зарегистрироваться» уезжает вниз в момент,
   когда человек до неё дотягивается. */
.вопрос-капча { min-height: 102px; }

/* ⚑ «Забыли пароль?» — кнопка, притворяющаяся ссылкой. Кнопка, потому что
   действие происходит на месте и никуда не ведёт; вид ссылки, потому что
   рядом стоит настоящая кнопка «Войти», и две одинаковые кнопки заставляли
   бы выбирать между равными по виду, но неравными по смыслу. */
.вопрос-ссылка {
  justify-self: start; padding: 0; border: 0; background: none;
  color: var(--фирменный); font: inherit; font-size: var(--кегль-мелкий);
  text-decoration: underline; cursor: pointer;
}
.вопрос-ссылка:hover { text-decoration: none; }
/* Восстановление отделено чертой: это отдельное дело внутри формы входа,
   и без границы поле почты читается как третье поле того же входа. */
.вопрос-восстановление {
  display: grid; gap: var(--отступ-0-5);
  padding-top: var(--отступ-0-5);
  border-top: 1px solid var(--граница);
}

/* ── страница разбора вопросов ───────────────────────────────────────────
   Служебная, под паролем. Оформление намеренно плотнее сайта: здесь работают,
   а не читают — на экран должно помещаться больше записей за раз. */
.разбор { padding-block: var(--отступ-2); }
.разбор-полоса {
  display: flex; gap: var(--отступ-0-5); flex-wrap: wrap; align-items: center;
  margin-top: var(--отступ-0-5);
}
.разбор-вопрос, .разбор-человек {
  border: 1px solid var(--граница); border-radius: var(--скругление-мал);
  padding: var(--отступ-1); margin-top: var(--отступ-1);
}
/* ⚑ Снятая запись видна СРАЗУ, а не по надписи: она приглушена и отчёркнута.
   Иначе, разбирая полсотни, легко ответить на снятую и не понять, почему
   ответа нет в ленте. */
.разбор-вопрос--снят { opacity: .55; border-left: 4px solid var(--ошибка); }
.разбор-вопрос__текст { margin: .25rem 0 var(--отступ-0-5); }
.разбор-поле {
  width: 100%; min-height: 4.5rem; font: inherit; resize: vertical;
  padding: .5rem .625rem; border: 1px solid var(--граница);
  border-radius: var(--скругление-мал); background: var(--фон); color: var(--текст);
}
.разбор-кто, .разбор-аттестации {
  font: inherit; padding: .35rem .5rem; border: 1px solid var(--граница);
  border-radius: var(--скругление-мал); background: var(--фон); color: var(--текст);
}
.разбор-аттестации { flex: 1 1 14rem; min-width: 0; }
.разбор-аттестации:disabled { opacity: .5; }
.разбор-подпись { flex-basis: 100%; }

/* ── цитирование в чате ──────────────────────────────────────────────────
   ⚑ Кнопка «Ответить» КРУПНАЯ на телефоне `[поправка владельца 02-09-2026:
   «на телефоне кнопка может быть маленькой»]`. Сорок четыре пикселя — обычная
   мера попадания пальцем; мельче человек мажет и бросает. На широком экране
   она может быть скромнее: там целятся мышью. */
/* ⚠ Кнопка ужата `[решение владельца 02-09-2026: «не оставлять больших
   пустых пространств»]`. Сорок четыре пикселя — мера попадания пальцем,
   и на телефоне она остаётся; но там, где целятся мышью, столько высоты
   в каждой записи съедало ленту. Ниже по файлу правило для широкого экрана
   делает её скромнее — здесь уменьшены только поля вокруг. */
.вопрос-ответить {
  margin-top: .25rem; padding: .45rem .8rem; min-height: 44px;
  border: 1px solid var(--граница); border-radius: 999px;
  background: var(--фон); color: var(--фирменный);
  font: 600 var(--кегль-мелкий)/1 inherit; cursor: pointer;
}
.вопрос-ответить:hover { background: var(--фон-мягкий); }
@container (min-width: 30rem) {
  .вопрос-ответить { min-height: 0; padding: .3rem .7rem; margin: 0; }

  /* ⛔ На компьютере «Ответить» стоит СПРАВА от сообщения `[решение владельца
     02-09-2026]`. Под текстом она добавляла каждой записи целую строку —
     а именно высота записей и съедала подложку. Справа она занимает место,
     которое всё равно пустует, и записи становятся ниже и ближе друг к другу.
     ⚠ На телефоне остаётся под текстом: там ширины нет, и колонка под кнопку
     отняла бы её у текста. */
  .вопрос-лента .вопрос,
  .вопрос-лента .вопрос__ответ {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: start;
    column-gap: var(--отступ-0-5);
  }
  .вопрос-лента .вопрос > *:not(.вопрос-действия),
  .вопрос-лента .вопрос__ответ > *:not(.вопрос-действия) {
    grid-column: 1;
  }
  /* Блок кнопок прижат к верху своей записи: так он рядом с началом текста,
     к которому относится, а не уезжает к низу длинного сообщения.
     ⚑ Раньше сюда попадала сама кнопка «Ответить» — теперь блок
     `.вопрос-действия`, в котором она стоит вместе с «Спасибо», когда
     та есть `[03-09-2026]`. Правило то же, адресат другой. */
  .вопрос-лента .вопрос > .вопрос-действия,
  .вопрос-лента .вопрос__ответ > .вопрос-действия {
    grid-column: 2; grid-row: 1 / span 2; align-self: start;
  }
  /* ⚠ Ответ внутри вопроса — своя сетка, поэтому он должен занять обе
     колонки родителя, иначе встанет в узкую первую. */
  .вопрос-лента .вопрос > .вопрос__ответ { grid-column: 1 / -1; }
}

/* Блок кнопок под записью: «Ответить» и «Спасибо», когда она есть, —
   ОДНА НАД ДРУГОЙ всегда, а не в ряд `[уточнение владельца 03-09-2026:
   «можно расположить не только рядом, но и просто одну над другой»]`.
   Так они не спорят за ширину на телефоне и не гадают, поместятся ли
   обе в строку — одно и то же правило годится и там, и на широком
   экране, где блок целиком встаёт в правую колонку сеткой (`@container`
   выше). */
.вопрос-действия {
  display: flex; flex-direction: column; align-items: stretch;
  gap: var(--отступ-0-5);
}

/* «Спасибо» — того же роста, что «Ответить», но приглушённее по цвету:
   это не приглашение к диалогу, а лёгкая реакция, и не должна тянуть
   внимание на себя сильнее самой кнопки ответа. */
.вопрос-спасибо {
  margin-top: .25rem; padding: .45rem .8rem; min-height: 44px;
  border: 1px solid var(--граница); border-radius: 999px;
  background: var(--фон); color: var(--текст-приглушён);
  font: 600 var(--кегль-мелкий)/1 inherit; cursor: pointer;
}
.вопрос-спасибо:hover { background: var(--фон-мягкий); }
.вопрос-спасибо:disabled { opacity: .6; cursor: default; }
/* Отмеченная — уже нажимал в этом браузере: фирменный цвет вместо
   приглушённого, та же логика, что у активной вкладки или текущего пункта. */
.вопрос-спасибо--отмечена {
  color: var(--фирменный); border-color: var(--фирменный);
  background: color-mix(in srgb, var(--фирменный) 8%, var(--фон));
}
@container (min-width: 30rem) {
  .вопрос-спасибо { min-height: 0; padding: .3rem .7rem; margin: 0; }
}

/* Цитата: и в ленте, и над полем ввода — одинаково, чтобы человек узнавал
   её как одну вещь. Отбита полосой слева, как и ответ центра. */
.вопрос-цитата {
  position: relative;
  margin: .3rem 0; padding: .3rem .5rem;
  border-left: 3px solid var(--граница); background: var(--фон-мягкий);
  border-radius: 0 var(--скругление-мал) var(--скругление-мал) 0;
  font-size: var(--кегль-мелкий);
}
.вопрос-цитата p { margin: 0 0 .15rem; }
.вопрос-цитата p:last-child { margin: 0; }
.вопрос-цитата--вводим { border-left-color: var(--фирменный); padding-right: 2rem; }
.вопрос-цитата__снять {
  position: absolute; top: .15rem; right: .25rem;
  border: 0; background: none; cursor: pointer;
  font-size: 1.25rem; line-height: 1; color: var(--текст-приглушён);
}
/* Обязательная галочка помечена так же, как обязательное поле: звёздочкой
   в цвете действия. Один знак на всю форму — иначе человек ищет два правила. */
.галочка--нужна b { color: var(--акцент); font-weight: 700; }
/* Найденное в чате. ⚠ Свой цвет, а не браузерный жёлтый: на тёмной теме
   родной mark даёт чёрное на жёлтом посреди светлого текста — рябит. */
/* ⛔ Подсветка и текущее совпадение — ОДНОГО семейства, разной силы
   `[замечание владельца 02-09-2026: «первый фон хорошо виден, последующие
   практически не различимы ни в основном режиме, ни в ночном»]`.
   Прежде обычные красились в `--фирменный-светлый` — а он задуман подложкой
   под целые полосы, и как метка на строке текста почти не читается,
   особенно ночью, где он и вовсе тёмно-синий.
   ⚑ Теперь обычное — тот же акцент, разбавленный до четверти, текущее —
   сплошной. Одно семейство даёт ясную градацию «найдено / вот оно»,
   и оба поедут за темой сами: `--акцент` в ночи другой.
   ⚑ Обводка держит метку различимой и на цветной подложке чата, где одной
   заливки мало. */
.вопрос-лента mark {
  background: color-mix(in srgb, var(--акцент) 22%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--акцент) 45%, transparent);
  color: var(--текст);
  border-radius: 3px; padding: 0 .1em;
}
.вопрос-счёт { margin: 0 0 .25rem; }
/* Стрелки перехода по совпадениям. ⚠ Крупные под палец: они стоят в шапке
   рядом с крестиком закрытия, и промах по ним закрывает окно — а это потеря
   набранного вопроса, самая дорогая ошибка в этом месте. */
.вопрос-стрелка {
  border: 1px solid var(--граница); background: var(--фон); color: var(--текст);
  border-radius: var(--скругление-мал); cursor: pointer;
  min-width: 34px; min-height: 34px; font-size: 1rem; line-height: 1;
}
.вопрос-стрелка:hover { background: var(--фон-мягкий); }
.вопрос-счёт-совпадений { min-width: 3.5rem; text-align: right; }
/* Текущее совпадение отличается от прочих: иначе переход виден только
   по прокрутке, а на коротком списке она не двигается вовсе. */
.вопрос-лента mark.вопрос-совпало--текущее {
  background: var(--акцент); color: var(--на-акценте);
}
/* Запись эксперта в ленте: та же полоса слева, что у ответа центра, — чтобы
   ответ был узнаваем как ответ независимо от того, откуда он пришёл:
   из админки или из чата. */
/* Запись эксперта в ленте — тот же синий, что у ответа центра: ответ
   узнаётся как ответ независимо от того, откуда пришёл. */
.вопрос-лента .вопрос--от-эксперта {
  border-left: 3px solid var(--фирменный);
  background: var(--фон);
}

/* ⛔ Цитата ВНУТРИ ответа возвращается к фону вопроса `[та же мысль
   владельца: «под одной боковой синей линией и вопрос, и ответ, и именно
   фон позволит чётко их разделить»]`. Синее на синем слилось бы, и в одном
   блоке стало бы не видно, где чужой вопрос, а где наш ответ. */
/* ⛔ Цитата вопроса внутри ответа — ГОЛУБАЯ `[решение владельца: «цвет
   вопросов внутри рамок ответов можно залить голубым»]`. Теперь голубой
   работает там, где он и нужен: не различает сообщения между собой,
   а показывает внутри одного блока, где чужой вопрос, а где наш ответ. */
.вопрос-цитата {
  background: var(--фирменный-светлый);
  border-left-color: var(--фирменный);
}
