/* ЕДИНАЯ шапка порталов Neptune (core/static/header.css) — ЕДИНСТВЕННЫЙ источник.
   Отдаётся роутом /header.css обоих отделов; HTML строит core.ui.build_header.
   Разметку вставляет сервер через плейсхолдер <!--HEADER-->. Цвета берутся из :root страницы. */
/* overflow НЕ hidden: выпадающий список модулей обязан выходить за низ шапки, иначе
   он обрезается по её краю и виден один первый пункт. Клипать нечего — и волна
   (.wave, absolute внутри), и сетка (::before, inset:0) лежат в границах шапки. */
/* Полоса прокрутки резервируется ВСЕГДА. Без этого короткая страница шире длинной на
   ширину полосы (замерено: 1700 против 1685), а шапка центрируется по ширине окна — и
   при переходе «Готовые КП» → «Подбор» весь блок прыгал влево на 7,5 px. Заодно уходит
   дробное смещение: на нецелом left текст рендерится другим сглаживанием и выглядит
   то жирнее, то тоньше. Правило документное, а не «шапочное», но лечит именно её:
   header.css грузят все страницы портала, и геометрия обязана быть общей. */
/* ── ПАЛИТРА ПОРТАЛА ────────────────────────────────────────────────────────────
   ЕДИНСТВЕННОЕ место, где у портала заданы цвета. До 10.09.2026 их не было нигде:
   двадцать четыре файла объявляли У СЕБЯ один и тот же набор (--ink, --muted, --line,
   --card, --teal, --bg1, --bg2, --deep1, --deep2, --ok, --amber) — и он успел
   разъехаться. В одном только семействе почти-белых голубых накопилось СОРОК оттенков
   в полосе светлоты 94–99 %: #f6fafc, #f7fbfc, #f2f8fb, #f3fafc, #f5fafc… — разница
   между ними меньше, чем ошибка калибровки монитора, а поддерживать надо каждый.

   🔑 **Токены СМЫСЛОВЫЕ, а не «светлый/тёмный».** `--card` это «поверхность карточки»,
   а не «белый»: в светлой теме она светлее фона, и в тёмной ТОЖЕ светлее фона. Тёмная
   тема — не инверсия светлой (инверсия кладёт карточку под фон и ломает всю глубину),
   а второй набор значений для тех же ролей.

   ⚠️ **Цвет текста НА цветной кнопке остаётся #fff в обеих темах** и токеном не
   становится: подставь туда `--card`, и белые буквы на бирюзовой кнопке в тёмной теме
   станут тёмными на бирюзовом. Роль у него другая — «текст поверх акцента», а не
   «поверхность».

   ⚠️ Имена латиницей — не по недосмотру. Они уже стоят в двадцати четырёх файлах и в
   сотнях `var(…)`; переименование в русские ничего не улучшает и стоит одного
   пропущенного места на файл. Та же граница, что у `data-label` и у имени параметра
   пути Starlette.

   Как выбирались значения светлой темы: это САМЫЕ ЧАСТЫЕ из уже стоявших (#eef4f7 —
   50 раз, #d7e3ea — 28, #5c7a8b — 38, #0c2a3c — 35), то есть светлая тема осталась
   собой; сдвинулись только редкие соседи на 1–2 % светлоты. */
:root{
  color-scheme:light dark;

  --card:#ffffff;      /* поверхность карточки, таблицы, поля ввода */
  --card2:#f6fafc;     /* строка при наведении, вложенная подложка */
  --bg1:#eef4f7;       /* фон страницы */
  --bg2:#e0ecf1;       /* выделенная плашка, шапка таблицы */
  --line:#d7e3ea;      /* обычная рамка */
  --line2:#e8eff3;     /* тонкая рамка, разделитель строк */
  --line3:#cfe6f2;     /* заметная рамка: активное, выбранное */
  --ink:#0c2a3c;       /* основной текст */
  --muted:#4d6a79;     /* пояснения, мета-строки. Было #5c7a8b: на --bg1/--bg2 давал 4,1 и
                          4,3 при норме 4,5 — серые переключатели и даты читались плохо. */
  --muted2:#7d8f99;    /* ещё тише: подписи, отключённое */
  --onDark:#eaf6fb;    /* текст поверх тёмного фирменного — светлый в ОБЕИХ темах */
  --onDark2:#cfe7f2;   /* второй по силе ПОВЕРХ тёмного: пункты меню, подписи на лендинге.
                          Отдельный токен, потому что «приглушённый» на тёмном и на светлом
                          — разные цвета: --muted (#5c7a8b) на шапке даёт контраст 2,5. */
  --strong:#0b3a54;    /* сильный текст: заголовки, названия, ссылки списков */
  --strong2:#0e6d8f;   /* второй по силе: подзаголовки, метки */
  --onAccent:#ffffff;  /* текст ПОВЕРХ заливки: кнопка, плашка состояния, бейдж */

  --deep1:#0b3a54;     /* фирменный тёмный: шапка, лендинг */
  --deep2:#0e6d8f;
  --teal:#0a7fa0;      /* акцент: ссылка, кнопка. Было #0e93b8: белый текст кнопки на нём и
                          сама ссылка на белом давали 3,57 при норме 4,5 (прогон 11.09.2026). */
  --teal-d:#0b7794;    /* акцент при наведении */

  --ok:#0f7a4f;   --ok-bg:#eaf7f1;    --ok-line:#bfe6d5;    --ok-ink:#0f5f3c;
  --amber:#e0a800; --amber-bg:#fff8e6; --amber-line:#f0dfa8; --amber-ink:#7a5c00;
  /* Буквы ПОВЕРХ жёлтой заливки (счётчик задач). Тёмные в обеих темах и потому без
     тёмного значения: --amber-ink в тёмной теме — светлый текст на ТЁМНОЙ подцветке,
     и на жёлтом бейдже цифра «6» сливалась с фоном полностью (жёлтое на жёлтом). */
  --onAmber:#3a2c00;
  --err:#c0392b;  --err-bg:#fdeceb;   --err-line:#f5c6c2;   --err-ink:#8a1f1f;

  /* Приглушённые заливки: полоса простоя на /status закрашена ими СПЛОШЬ, и обычные
     --ok/--amber/--err там кричат. Отдельные токены, а не «чуть светлее»: в тёмной
     теме приглушать надо в другую сторону. */
  --ok-soft:#57b389; --amber-soft:#e5b44e; --err-soft:#d97b7b;

  /* Мягкое пятно вверху страницы. Не `--card2`, хотя в светлой теме значение то же:
     у поверхности карточки и у отсвета на фоне разные соседи. В тёмной теме --card2
     лежит на десять процентов светлоты выше фона, и пятно из отсвета стало серой
     мутью во весь верх экрана. */
  --блик:#f6fafc;

  --violet:#4a4fb0; --violet-bg:#eef0fb;   /* метки «Прайсы» и «Оборудование» — единственный
                                              цвет портала вне пяти семейств */
  --shadow:0 14px 44px rgba(12,42,60,.10),0 2px 8px rgba(12,42,60,.05);
}

/* Тёмная тема — по настройке устройства. Переключателя в портале нет намеренно: своим
   переключателем пришлось бы хранить выбор, показывать его в интерфейсе и объяснять,
   почему на телефоне и на компьютере по-разному. Настройка системы уже есть у всех. */
@media (prefers-color-scheme: dark){
  :root{
    --card:#152c39;    /* карточка СВЕТЛЕЕ фона — глубина та же, что в светлой теме */
    --card2:#1a3442;
    --bg1:#0e1f2a;
    --bg2:#1e3d4d;
    --line:#274657;
    --line2:#1d3543;
    --line3:#37627a;
    --ink:#e4eff5;
    --muted:#9ab2c0;
    --muted2:#8299a6;
    /* --onDark не переопределяется: он и так «светлый поверх тёмного». */

    --deep1:#0a2733;
    --deep2:#0e5573;
    /* 🔑 Сильный текст РАСХОДИТСЯ с фирменным тёмным именно здесь. В светлой теме это
       один и тот же #0b3a54 — и до тёмной темы разницы не было видно. Оставь их одним
       токеном, и заголовок «Сметы» станет тёмно-синим на тёмно-синей карточке. */
    --strong:#f2f9fc;
    --strong2:#7fd3ee;
    /* В тёмной теме заливки СВЕТЛЕЮТ, значит буквы по ним обязаны потемнеть. Белый
       текст на #38bcdd дал контраст 2,2 при норме 4,5 — замерено на живых страницах. */
    --onAccent:#06222d;
    --teal:#38bcdd;    /* на тёмном фоне светлый бирюзовый: #0e93b8 не добирает контраста */
    --teal-d:#63d2ef;

    /* У состояний в тёмной теме меняются местами роли: заливка становится тёмной
       подцветкой, а «чернильный» вариант — светлым текстом поверх неё. */
    --ok:#3fc98d;    --ok-bg:#123328;    --ok-line:#20573f;    --ok-ink:#8fe3bd;
    --amber:#e8b62c; --amber-bg:#33290d; --amber-line:#5c4a15; --amber-ink:#f0d488;
    --err:#ef6a5c;   --err-bg:#3a1e1c;   --err-line:#63302c;   --err-ink:#f6a9a0;

    --ok-soft:#2f7f5c; --amber-soft:#9a7a1e; --err-soft:#964a4a;
    --блик:#132734;
    --violet:#a9a6f0; --violet-bg:#241f3d;

    /* Тень на тёмном фоне работает только чёрная: полупрозрачный синий на #0e1f2a
       не виден вовсе, и карточка теряет край. */
    --shadow:0 14px 44px rgba(0,0,0,.45),0 2px 10px rgba(0,0,0,.30);
  }
}

/* Возврат «Назад» из кэша переходов: на один-два кадра без переходов и анимаций.
   Браузер восстанавливает страницу вместе с «наведением» и «нажатием», в которых её
   оставили, а сняв их, давал переходам CSS доиграть обратно — кнопки «отжимались» на
   глазах. Класс ставит и снимает core/static/pwa.js по `pageshow` с `persisted`.
   ⚠️ `!important` здесь по делу: переходы заданы у двух десятков кнопок в стилях
   модулей, которые идут ПОСЛЕ header.css, и без него правило проиграло бы каждому. */
:root.восстановлено *, :root.восстановлено *::before, :root.восстановлено *::after{
  transition:none !important; animation:none !important}

/* Фон страницы в тёмной теме. Правило нужно потому, что часть страниц портала
   («Проверяющий», журналы, доработки) фона у body НЕ ЗАДАЁТ вовсе: в светлой теме их
   белый холст совпадал с задуманным, и разницы никто не видел. В тёмной холст берётся
   у браузера — нейтрально-серый #121212, — и такая страница выпадала из портала
   серым пятном между синей шапкой и синими карточками.
   ⚠️ Только для тёмной темы: поставь это правило безусловно, и белые страницы разом
   позеленеют в #eef4f7 — правка темы стала бы правкой светлого портала.
   Страницы со СВОИМ фоном (лендинг, вход) перебивают его как раньше: их правила идут
   после header.css, а специфичность у медиазапроса та же. */
@media (prefers-color-scheme: dark){
  body{background:var(--bg1); color:var(--ink)}
}


html{scrollbar-gutter:stable}

/* Шрифт по умолчанию — у страницы, которая свой не задала. Каждая страница модуля
   объявляет `body{font-family:var(--sans)}` сама, и редактор КП про это забыл: весь
   текст, включая подсказки тура, шёл шрифтом с засечками (поймано роликами 03.10.2026).
   Свои правила страниц идут после header.css и перебивают это как раньше. */
body{font-family:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif}

/* ── Типографика форм ПОРТАЛА (не шапки) ──────────────────────────────────────
   Один размер полей и кнопок на все модули. Причина: у каждой страницы поля стояли
   `font:inherit`, то есть наследовали базовый кегль body (15 px), а подписи, таблицы и
   плашки вокруг них — 12.5–14. Форма из-за этого выглядела крупнее и тяжелее всего
   остального, будто её увеличили по ошибке («в формах как будто крупнее чем нужно» —
   владелец, 04.09.2026).

   Живёт ЗДЕСЬ, а не в CSS каждого модуля: header.css грузят все страницы портала, и это
   единственное общее место. Копии шкалы по модулям разъехались бы ровно так же, как
   успели разъехаться копии стиля кнопки «?» до переезда сюда.

   Переменные, а не жёсткие значения: модуль, которому нужен свой кегль (крупная кнопка
   на лендинге, мелкий фильтр), переопределяет `--кегль-поля` у себя, а не заводит
   собственную шкалу. Явный `font-size` в правилах модуля по-прежнему сильнее — здесь
   задаётся ДЕФОЛТ, а не запрет. */
:root{
  --кегль-поля:13.5px;      /* input/select/textarea/кнопки */
  --кегль-подписи:12.5px;   /* пояснения под заголовками, мета-строки */
  --кегль-меток:10.5px;     /* КАПСОМ над полем */
}
input,select,textarea,button{font-size:var(--кегль-поля)}
/* Цвета полей — ПОРТАЛА, а не браузера. С `color-scheme: light dark` браузер сам красит
   поля в тёмной теме — но в СВОЙ нейтрально-серый (#3b3b3b), и рядом с сине-зелёными
   карточками портала это выглядит чужой вставкой. В светлой теме правило ничего не
   меняет: белый фон и почти-чёрный текст у полей и так были.
   ⚠️ Только текстовые поля: у флажка, переключателя и ползунка `background` отнимает
   рисунок самого элемента, и вместо галочки остаётся пустой квадрат. */
input:not([type=checkbox]):not([type=radio]):not([type=range]):not([type=color]):not([type=file]),
select,textarea{background:var(--card); color:var(--ink)}
input::placeholder,textarea::placeholder{color:var(--muted2)}
/* Плейсхолдер той же величины, что и вводимый текст: разница даже в полпункта читается
   как «поле подпрыгнуло», когда начинаешь печатать. */
input::placeholder,textarea::placeholder{font-size:inherit}

/* ══ КОМПОНЕНТЫ ПОРТАЛА ═══════════════════════════════════════════════════════════
   Карточка, кнопка и ширина колонки — ОДНИ на весь портал.

   Зачем. `.card` был объявлен 27 раз в двадцати файлах, `.btn` — 11, `.wrap` — 29, и
   почти всегда почти одинаково: разница сводилась к скруглению (14 против 18), полям
   (16/18 против 22) и верхнему отступу. То есть одна и та же вещь рисовалась по-разному
   в зависимости от того, с какой страницы скопировали, и разъезжалась дальше при каждой
   правке — ровно так же, как разъехались шапка главной и шапка модулей (12.09.2026).

   Как пользоваться. Модуль НЕ повторяет базу, а дописывает СВОЁ: `.card{overflow:hidden}`
   у журнала, `.card{display:grid}` у «Готовых КП». Стили модуля грузятся после
   header.css, поэтому любое его правило сильнее — здесь дефолт, а не запрет.
   ⚠️ Одно исключение из «не повторять» — ШИРИНА: `.wrap` задаёт только поля и
   центрирование, а `max-width` остаётся за страницей: у ленты «Что нового» колонка для
   чтения, у оплат — таблица во весь экран (см. «Вёрстка страниц» в CLAUDE.md).
   Список того, что нельзя переопределять целиком, стережёт core/tests/test_стили.py. */
.card{background:var(--card); border:1px solid var(--line); border-radius:16px;
  box-shadow:var(--shadow); padding:18px 20px; margin-top:16px}
/* Кнопка. `.btn` — нейтральная (на поверхности карточки), `.btn.акцент` — действие
   страницы (собрать, сохранить, отправить). Раньше одно и то же имя `.btn` означало
   у «Готовых КП» и «Журнала» бирюзовую кнопку, а у «Проверяющего», «Доработок» и
   «Лидов» — нейтральную: увидеть это можно было, только открыв обе страницы рядом. */
.btn{background:var(--card); color:var(--strong); border:1px solid var(--line);
  padding:9px 15px; border-radius:9px; font:inherit; font-size:var(--кегль-поля);
  font-weight:600; cursor:pointer; text-decoration:none; display:inline-flex;
  align-items:center; gap:8px; transition:.15s}
.btn:hover{background:var(--card2); border-color:var(--line3)}
/* ⚠️ Своё `display` перебивает [hidden] — без этой строки кнопка, спрятанная атрибутом,
   остаётся на экране. Так «Отменить правку» висела в форме встречи, где править нечего,
   и обещала отмену того, чего человек не начинал. Та же грабля, что у «как часто». */
.btn[hidden]{display:none}
.btn:disabled, .btn[aria-disabled="true"]{opacity:.55; cursor:default}
.btn.акцент{background:var(--teal); color:var(--onAccent); border-color:transparent;
  padding:9px 16px}
.btn.акцент:hover{background:var(--teal-d); border-color:transparent}
/* Колонка страницы: поля и центрирование — общие, ширина — своя у каждой страницы. */
.wrap{margin:0 auto; padding:0 24px 72px}
/* Окно подтверждения — вместо системного confirm(): тот белый в тёмной теме, со своим
   шрифтом и кнопками (владелец, 11.09.2026 и 24.09.2026). На <dialog>: фокус внутри, Esc
   и затемнение под ним браузер делает сам. Разметка: dialog.окно > form[method=dialog] >
   .окно-верх (.окно-знак + h3), .окно-текст, .окно-кнопки (.окно-отмена, .окно-да). */
dialog.окно{width:min(460px, calc(100vw - 32px)); padding:0; border:1px solid var(--line);
  border-radius:18px; background:var(--card); color:var(--ink);
  box-shadow:0 30px 80px -24px rgba(4,24,36,.6)}
dialog.окно::backdrop{background:rgba(6,22,32,.55); -webkit-backdrop-filter:blur(3px); backdrop-filter:blur(3px)}
dialog.окно[open]{animation:окно-появление .3s cubic-bezier(.22,.8,.26,1)}
dialog.окно[open]::backdrop{animation:фон-появление .3s ease}
@keyframes окно-появление{from{opacity:0; transform:translateY(10px) scale(.98)}}
@keyframes фон-появление{from{opacity:0}}
.окно form{margin:0; padding:24px 24px 20px; display:flex; flex-direction:column; gap:14px}
.окно-верх{display:flex; align-items:center; gap:14px}
.окно-знак{width:44px; height:44px; flex:none; border-radius:13px; display:grid; place-items:center;
  background:color-mix(in srgb, var(--teal) 15%, var(--bg1)); color:var(--teal-d)}
.окно h3{margin:0; font-size:18px; line-height:1.3; color:var(--strong)}
.окно-текст{margin:0; font-size:14px; line-height:1.5; color:var(--ink)}
.окно-кнопки{display:flex; flex-wrap:wrap; justify-content:flex-end; gap:10px; margin-top:6px}
.окно-кнопки button{font:inherit; font-size:14px; font-weight:600; padding:9px 18px;
  border-radius:10px; cursor:pointer; transition:background-color .2s, border-color .2s, color .2s}
.окно-отмена{border:1px solid var(--line); background:transparent; color:var(--muted)}
.окно-отмена:hover{border-color:var(--strong2); color:var(--strong2)}
.окно-да{border:1px solid var(--teal); background:var(--teal); color:var(--onAccent)}
.окно-да:hover{background:var(--teal-d); border-color:var(--teal-d)}
dialog.окно.окно-широкое{width:min(580px, calc(100vw - 32px))}
.окно-поле{font:inherit; font-size:14px; width:100%; box-sizing:border-box; padding:9px 11px;
  border:1px solid var(--line); border-radius:10px; background:var(--bg1); color:var(--ink); resize:vertical}
.окно-поле:focus{outline:none; border-color:var(--teal)}
.окно-время{display:flex; align-items:center; gap:12px; font-size:14px; color:var(--muted)}
.окно-время input{font:inherit; font-size:15px; padding:7px 10px; border:1px solid var(--line);
  border-radius:10px; background:var(--bg1); color:var(--strong)}
.окно-время input:focus{outline:none; border-color:var(--teal)}
@media (prefers-reduced-motion:reduce){
  dialog.окно[open], dialog.окно[open]::backdrop{animation:none}
}
/* Окно «Загрузить документ» (core/static/upload.js) — начинка того же каркаса. */
.окно-загрузки{width:min(520px, calc(100vw - 32px))}
.зг-файлы{display:flex; flex-direction:column; align-items:center; gap:4px; padding:18px 14px;
  border:1.5px dashed var(--line3); border-radius:12px; background:var(--bg1); text-align:center;
  cursor:pointer; font-size:14px; color:var(--ink); transition:border-color .15s, background .15s}
.зг-файлы:hover, .зг-файлы.над{border-color:var(--teal); background:color-mix(in srgb, var(--teal) 8%, var(--bg1))}
.зг-файлы.есть{border-style:solid; border-color:var(--teal)}
.зг-файлы input{position:absolute; width:1px; height:1px; opacity:0}
.зг-файлы small{font-size:12px; color:var(--muted)}
.зг-поле{display:flex; flex-direction:column; gap:4px; position:relative}
.зг-поле span{font-size:12.5px; font-weight:600; color:var(--muted)}
.зг-поле i{font-style:normal; font-weight:400}
.зг-поле input, .зг-поле select, .зг-поле textarea{font:inherit; font-size:var(--кегль-поля);
  padding:9px 11px; border:1px solid var(--line3); border-radius:10px; background:var(--card2);
  color:var(--ink); width:100%; box-sizing:border-box}
.зг-выпад{position:absolute; z-index:3; left:0; right:0; top:100%; margin-top:4px; max-height:220px;
  overflow-y:auto; background:var(--card); border:1px solid var(--line3); border-radius:10px;
  box-shadow:0 10px 30px rgba(0,0,0,.25)}
.зг-выпад div{padding:8px 11px; cursor:pointer; font-size:13.5px}
.зг-выпад div:hover{background:var(--bg1)}
.зг-итог{margin:0; font-size:13.5px; padding:9px 12px; border-radius:10px}
.зг-итог.готово{background:var(--ok-bg); color:var(--ok)}
.зг-итог.готово a{color:inherit; font-weight:600}
.зг-итог.ошибка{background:var(--err-bg); color:var(--err)}
/* Комментарии к задаче (core/static/task_comments.js) — карточка планёрки и «Задачи».
   Здесь, а не в стилях модулей: блок один на две страницы, и вторая копия стилей
   разъехалась бы с первой. Свёрнут по умолчанию — список задач не раздувается. */
details.комм{margin-top:8px; font-size:13.5px}
details.комм > summary{cursor:pointer; color:var(--teal); font-weight:600; font-size:12.5px;
  list-style:none; display:inline-flex; align-items:center; gap:6px}
details.комм > summary::-webkit-details-marker{display:none}
details.комм > summary::before{content:"▸"; transition:transform .15s}
details.комм[open] > summary::before{transform:rotate(90deg)}
.комм-список{list-style:none; margin:8px 0 0; padding:0; display:flex; flex-direction:column; gap:6px}
.комм-реплика{padding:7px 10px; border-radius:10px; background:var(--bg1); border:1px solid var(--line2)}
.комм-кто{font-size:12px; color:var(--muted)}
.комм-кто b{color:var(--strong); font-weight:600}
.комм-текст{margin-top:2px; white-space:pre-wrap; overflow-wrap:anywhere; line-height:1.45}
.комм-пусто{margin:6px 0 0; color:var(--muted); font-size:12.5px}
.комм-пусто[hidden], .комм-беда[hidden]{display:none}
/* Форма — столбиком: поле во всю ширину блока, кнопка под ним. В строку «поле + кнопка»
   в узкой колонке «Задач» полю оставалось ~270px на две строки — «огрызок» (08.10.2026). */
.комм-форма{display:flex; flex-direction:column; align-items:flex-start; gap:8px; margin-top:8px}
.комм-форма textarea{align-self:stretch; min-width:0; min-height:84px; font:inherit;
  font-size:var(--кегль-поля); line-height:1.45; padding:9px 12px; border:1px solid var(--line3);
  border-radius:10px; background:var(--card2); color:var(--ink); resize:vertical;
  box-sizing:border-box}
.комм-форма textarea:focus{outline:none; border-color:var(--teal)}
.комм-беда{margin:6px 0 0; color:var(--err); font-size:12.5px}
/* Вопрос (галка «Жду ответа»): янтарная кайма, пока ждёт, — его ищут глазами в переписке,
   придя по значку из шапки; отвеченный — обычной репликой с тихой пометкой. */
.комм-реплика.вопрос{border-color:var(--amber-line); background:var(--amber-bg)}
.комм-вопрос{margin-left:8px; padding:0 7px; border-radius:99px; font-size:11px;
  font-weight:600; background:var(--amber); color:var(--onAmber)}
.комм-вопрос.отвечен{background:none; color:var(--muted); font-weight:500; padding:0}
.комм-жду{display:inline-flex; align-items:center; gap:6px; font-size:13px; color:var(--ink);
  cursor:pointer}
.комм-жду[hidden]{display:none}
/* Этап открытой задачи — пилюлей («Задачи» и карточка планёрки, 08.10.2026). Своей
   задаче та же пилюля — выпадающий список. «На проверке» — сплошным янтарём: это
   «сделал, проверь», и строка должна бросаться в глаза; «в работе» — бирюзой. Цвет — фоном
   (`background-color`), а не шорткатом: шорткат стёр бы стрелку списка. */
.этап-задачи{display:inline-block; padding:1px 9px; border-radius:99px; font:inherit;
  font-size:12px; font-weight:600; line-height:20px; white-space:nowrap; vertical-align:middle;
  border:1px solid var(--line); background-color:var(--card2); color:var(--muted)}
select.этап-задачи{appearance:none; -webkit-appearance:none; cursor:pointer; height:auto;
  width:auto; padding-right:22px; background-repeat:no-repeat; background-size:4px 4px;
  background-image:linear-gradient(45deg, transparent 50%, currentColor 50%),
                   linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position:calc(100% - 12px) 55%, calc(100% - 8px) 55%}
select.этап-задачи:disabled{opacity:.6; cursor:default}
select.этап-задачи:focus-visible{outline:2px solid var(--teal); outline-offset:1px}
select.этап-задачи option{color:var(--ink); background-color:var(--card); font-weight:400}
.этап-задачи[data-этап="active"]{color:var(--teal);
  border-color:color-mix(in srgb, var(--teal) 45%, transparent);
  background-color:color-mix(in srgb, var(--teal) 12%, transparent)}
.этап-задачи[data-этап="review"]{color:#2e2300; border-color:var(--amber);
  background-color:var(--amber)}
/* Пусто — один вид на все списки портала. */
.пусто, .empty{color:var(--muted)}

/* Типографику шапка задаёт СЕБЕ САМА и ничего не наследует со страницы. Раньше
   line-height приходил из body, а он у страниц разный: где 1.5 (подбор, опросный лист,
   прайсы, договоры), где не задан вовсе (готовые КП, журнал, проверяющий) — и меню
   получалось то 39 px высотой, то 35, вместе с ним прыгала и вся шапка. Шрифт и
   сглаживание фиксируем по той же причине: стека `--sans` в отделах два разных. */
header.top{position:relative; overflow:visible; color:var(--onDark);
  font-family:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
  /* Межстрочный — в ПИКСЕЛЯХ: при множителе высота меню выходит дробной (36,9 px),
     и нижний край шапки вместе с волной садится на полпикселя. */
  font-size:14px; line-height:19px; -webkit-font-smoothing:antialiased;
  background:linear-gradient(135deg,var(--deep1),var(--deep2)); padding:26px 0 48px}
header.top::before{content:""; position:absolute; inset:0; opacity:.11;
  background-image:linear-gradient(rgba(255,255,255,.5) 1px,transparent 1px),
    linear-gradient(90deg,rgba(255,255,255,.5) 1px,transparent 1px);
  background-size:30px 30px; mask-image:linear-gradient(180deg,#000 25%,transparent 92%)}
/* Волна под шапкой закрашена цветом ФОНА СТРАНИЦЫ — она и есть переход от шапки к ней.
   Правило нужно потому, что fill стоит атрибутом в разметке (core.ui._WAVE_SVG), а атрибут
   темы не знает: presentation-атрибут слабее любого правила CSS, чем мы и пользуемся. */
.wave path{fill:var(--bg1)}
/* фиксированная ширина шапки — одинакова на всех страницах, не зависит от ширины контента */
/* Две строки: 1) логотип слева + пользователь/выход справа; 2) навигация под ними (справа). */
/* 1040 было под старую ширину страниц-форм. Страницы с тех пор стали шире (прайсы 1240,
   договоры 1680), а меню отдела доросло до девяти пунктов и в 1040 не помещалось —
   «Статистика» уезжала на вторую строку. */
.hwrap{position:relative; z-index:2; max-width:1320px; margin:0 auto; padding:0 20px;
  /* Колоночный зазор 12, а не 20: он стоит только между значками шапки и между
     последним значком и именем. На главной блок кнопок свой и собран плотно, в модулях
     четвёрка значков расползалась — «надо плотно как на главной» (владелец, 12.09.2026).
     Логотип от значков отделяет `margin-left:auto`, пункты меню — свой `gap:4px`.
     ⚠️ До ИМЕНИ отступ больше зазора (12 против 10) — как на главной: у значка задач
     бейдж выступает вправо на пять пикселей, и при одном общем зазоре имя почти
     касается его (владелец, 11.09.2026). */
  display:flex; align-items:center; gap:12px 10px; flex-wrap:wrap}
.wave{position:absolute; left:0; right:0; bottom:-1px; width:100%; height:46px; z-index:1; display:block}
.logo{display:flex; align-items:center; gap:14px; text-decoration:none; color:inherit; order:1}
.mark{width:44px; height:44px; flex:0 0 44px; filter:drop-shadow(0 4px 10px rgba(0,0,0,.25))}
.brand{font-weight:800; letter-spacing:.06em; font-size:20px; line-height:1.1}
.brand small{display:block; font-weight:500; letter-spacing:.2em; font-size:10.5px; opacity:.8; text-transform:uppercase; margin-top:2px}
.menu{display:flex; gap:4px; flex-wrap:wrap; order:3; flex-basis:100%; justify-content:flex-end}
.menu a{color:var(--onDark2); text-decoration:none; font-weight:600; font-size:14px; padding:8px 12px; border-radius:10px; transition:.15s; white-space:nowrap}
.menu a:hover{background:rgba(255,255,255,.12); color:#fff}
.menu a.active{background:rgba(255,255,255,.18); color:#fff}
/* «Все модули» — выход из модуля НАРУЖУ, к списку. Отделён рамкой и стоит первым: это
   не соседний раздел модуля, а шаг на уровень выше, и путать их нельзя. Соседние модули
   лежат ВНУТРИ него: списком в ряд они раздували шапку стройки до двух строк и мешались
   со страницами самого отдела. */
/* Селекторы от `header.top`: страницы модулей стилизуют ГОЛЫЕ details/summary под свои
   раскрывающиеся блоки (у прайсов — светлый фон, своя стрелка, отступ сверху), и без
   этой специфичности переключатель модулей выглядел там полем ввода. Заодно гасим всё,
   что может прилететь со страницы: фон, отступы и чужой маркер. */
/* Прижат к ЛЕВОМУ краю (margin-right:auto), а не плывёт вместе с пунктами отдела:
   пунктов у модулей разное число — семь у стройки, один у прайсов, — и при
   выравнивании по правому краю кнопка каждый раз оказывалась в новом месте. */
header.top .modsw{position:relative; margin:0 auto 0 0; border:0; background:none}
header.top .modsw>summary{list-style:none; cursor:pointer; display:inline-flex; align-items:center;
  gap:7px; color:var(--onDark); font-weight:600; font-size:14px; padding:8px 13px; border-radius:10px;
  border:1px solid rgba(255,255,255,.28); background:none; white-space:nowrap; transition:.15s}
header.top .modsw>summary::-webkit-details-marker{display:none}
header.top .modsw>summary::before{content:none}
header.top .modsw>summary::after{content:""; width:6px; height:6px; margin-left:1px; flex:none;
  border-right:2px solid currentColor; border-bottom:2px solid currentColor; background:none;
  transform:rotate(45deg) translateY(-2px); transition:transform .15s}
header.top .modsw[open]>summary::after{transform:rotate(-135deg) translateY(-1px)}
header.top .modsw>summary:hover{background:rgba(255,255,255,.18); border-color:rgba(255,255,255,.5)}
header.top .modsw[open]>summary{background:rgba(255,255,255,.2); border-color:rgba(255,255,255,.55)}
header.top .modmenu{position:absolute; z-index:60; top:calc(100% + 6px); left:0; min-width:236px;
  background:var(--card); border-radius:12px; padding:6px; display:flex; flex-direction:column; gap:2px;
  box-shadow:0 18px 40px rgba(6,28,42,.34), 0 2px 6px rgba(6,28,42,.2)}
header.top .modmenu a{color:var(--strong); padding:9px 12px; border-radius:9px; font-size:14px;
  font-weight:600; text-decoration:none; white-space:nowrap;
  display:flex; align-items:center; gap:9px}
/* Значок приглушён, а подпись нет: список читают по названиям, картинка — якорь для
   глаза, а не главное. У текущего модуля значок берёт его цвет. */
header.top .modmenu a>svg{flex:0 0 auto; color:var(--muted2)}
header.top .modmenu a.тек>svg{color:var(--teal-d)}
header.top .modmenu a:hover{background:var(--bg1)}
header.top .modmenu a.тек{color:var(--teal-d); background:var(--bg1)}
/* Подпись раздела списка: группы модулей (core.ui.ГРУППЫ_МОДУЛЕЙ) и «Портал». Подписи,
   а не вложенные списки: это один перечень, разбитый для глаза. */
header.top .modmenu .modmenu-раздел{font-size:10.5px; font-weight:700; letter-spacing:.12em;
  text-transform:uppercase; color:var(--muted); padding:10px 12px 4px; margin-top:2px;
  border-top:1px solid var(--line)}
/* Первая группа идёт сразу за «Портал — все модули», у которого своя черта снизу. */
header.top .modmenu a.modmenu-home + .modmenu-раздел{border-top:0; margin-top:0}
/* «Портал — все модули» — не сосед по списку, а уровень выше: отделяем чертой. */
header.top .modmenu a.modmenu-home{display:flex; align-items:center; gap:8px; color:var(--teal-d);
  border-bottom:1px solid var(--line); border-radius:9px 9px 0 0; margin-bottom:2px; padding-bottom:11px}
.menu a .cnt{display:inline-block; margin-left:7px; min-width:16px; padding:1px 6px; border-radius:999px; background:var(--err); color:var(--onAccent); font-size:11px; font-weight:700; line-height:1.35; text-align:center; vertical-align:middle}
.menu a.active .cnt{background:var(--card); color:var(--strong)}
/* .ok — зелёный: не «горит, разберись», а «твоя правка готова» */
.menu a .cnt.ok{background:var(--ok)}
.menu a.active .cnt.ok{background:var(--card); color:var(--ok-ink)}

/* Плашка «ваша доработка выполнена» — под шапкой, рендерится сервером в _страница.
   Бейдж в меню легко не заметить, а письмо приходит только если почта настроена. */
.onbar{display:flex; align-items:center; gap:10px; flex-wrap:wrap;
  max-width:960px; margin:12px auto 0; padding:9px 14px;
  background:var(--ok-bg); border:1px solid var(--ok-line); border-radius:10px;
  color:var(--ok-ink); font-size:13.5px; line-height:1.4}
.onbar .ic{display:inline-flex; align-items:center; justify-content:center;
  width:18px; height:18px; flex:0 0 18px; border-radius:50%;
  background:var(--ok); color:var(--onAccent); font-size:11px; font-weight:700}
.onbar a{margin-left:auto; color:var(--ok-ink); font-weight:600; white-space:nowrap}
/* Личность вошедшего + выход (справа в шапке; показывается при включённой авторизации) */
.userbox{display:flex; align-items:center; gap:10px; white-space:nowrap; order:2; margin-left:auto}
/* Имя — ссылка на свою карточку (/profile), но по-прежнему просто текстом, без плашки:
   с фоном оно читалось как кнопка и спорило по весу с «Выйти» рядом (владелец: «на
   главной нравится больше»). Что имя нажимается, подсказывают курсор и подчёркивание
   при наведении. */
/* Имя — ОБЫЧНОГО начертания. Полужирным оно спорило по весу с «Выйти» рядом и
   выглядело сдвинутым относительно ряда значков (владелец, 12.09.2026); на главной
   имя всегда было обычным, и разница между шапками была видна именно на нём. */
.userbox .who{color:var(--onDark); font-weight:400; font-size:13.5px; opacity:.85;
  max-width:260px; overflow:hidden; text-overflow:ellipsis;
  text-decoration:none; transition:.15s}
.userbox a.who:hover{opacity:1; color:#fff;
  text-decoration:underline; text-underline-offset:3px}
.userbox .logout{color:var(--onDark); text-decoration:none; font-weight:600; font-size:13.5px;
  padding:6px 13px; border-radius:9px; border:1px solid rgba(255,255,255,.28); transition:.15s}
.userbox .logout:hover{background:rgba(255,255,255,.15); border-color:rgba(255,255,255,.5); color:#fff}
/* Кнопка «?» (тур по интерфейсу). Разметку кнопки печатает core.ui.build_header, поэтому и
   стиль её — здесь: пока он лежал копиями в onboarding.css каждого отдела, копии
   разъехались, и у сервиса кнопка стояла СЛЕВА от логотипа, а у стройки справа. Сам тур
   (шаги, пузыри) остаётся отдельческим — он про содержание страниц, а не про шапку. */
.onb-help{order:2; margin-left:auto;
  width:34px; height:34px; flex:0 0 34px; border-radius:50%; border:1px solid rgba(255,255,255,.28);
  background:rgba(255,255,255,.10); color:var(--onDark); font-size:16px; font-weight:700; cursor:pointer;
  display:inline-flex; align-items:center; justify-content:center; transition:.15s; padding:0}
/* Кнопка «Задачи» с бейджем открытых — на КАЖДОЙ странице портала, рядом с именем.
   Задачи приходят с планёрок и от коллег, а замечают их, только когда сам зайдёшь в
   модуль; бейдж в шапке — единственное место, которое видно, чем бы человек ни занимался.
   Бейдж рисуется только при ненулевом счётчике (см. core.ui.кнопка_задач): постоянный
   ноль на видном месте перестают замечать, а с ним и единицу. */
/* ⚠️ `box-sizing` — ЯВНО: у <button> («?») он border-box от браузера, у <a class="headbtn">
   — content-box, и кайма делала значки на два пикселя крупнее кнопки «?». */
.headbtn{order:2; position:relative; margin-left:auto; box-sizing:border-box;
  width:34px; height:34px; flex:0 0 34px; border-radius:50%;
  border:1px solid rgba(255,255,255,.28); background:rgba(255,255,255,.10); color:var(--onDark);
  display:inline-flex; align-items:center; justify-content:center; transition:.15s;
  text-decoration:none}
.headbtn:hover{background:rgba(255,255,255,.2); color:#fff; border-color:rgba(255,255,255,.5)}
/* Значок «Загрузить документ» — кнопка, а не ссылка (окно поверх страницы): у кнопки
   свои поля и шрифт браузера, и без сброса она была бы кругом другого размера. */
button.headbtn{padding:0; cursor:pointer; font:inherit}
/* Счётчик — поверх правого верхнего края иконки. Тёплый, а не красный: это не тревога,
   а «вот сколько на вас», и алый значок висел бы у человека постоянно. */
.tasksbtn .taskcnt, .qbtn .taskcnt{position:absolute; top:-5px; right:-5px; min-width:18px; height:18px;
  padding:0 5px; border-radius:9px; background:var(--amber); color:var(--onAmber);
  font-size:11px; font-weight:700; line-height:18px; text-align:center;
  box-shadow:0 0 0 2px rgba(11,58,84,.55)}
/* Соседи по правому краю: авто-отступ остаётся только у ПЕРВОГО из них, иначе между
   «?», задачами и именем разъезжается пустота во всю ширину шапки. Свой margin у
   соседей НЕ ставим вовсе — расстояние задаёт общий `gap` шапки, и добавленные к нему
   восемь пикселей выглядели дырой ровно в одном месте ряда. */
/* Вопросы без ответа, когда ждёте только вы: значок есть, но приглушён и без числа
   (core.ui.кнопка_вопросов). На телефоне он остаётся в шапке, в отличие от задач: у тех
   есть вкладка внизу, а у вопросов — нет. */
.qbtn.тихо{opacity:.55}
.qbtn.тихо:hover{opacity:1}
.headbtn ~ .headbtn, .onb-help ~ .headbtn{margin-left:0}
.headbtn ~ .userbox{margin-left:12px}
.onb-help:hover{background:rgba(255,255,255,.2); color:#fff; border-color:rgba(255,255,255,.5)}

/* ══ ОБОЛОЧКА ПРИЛОЖЕНИЯ (телефон) ═══════════════════════════════════════════════
   «Открыл с телефона — и это не сайт, а приложение» (владелец, 10.09.2026). Образец —
   Литера: там мобильный вид это не ужатый десктоп, а другая конструкция — вкладки
   внизу, второстепенное шторками, безопасные поля, `dvh` вместо `vh`.

   Живёт ЗДЕСЬ, потому что header.css грузят все страницы портала — это единственное
   место, откуда правило доходит до всех сразу. Разметку панели печатает core.ui.таббар
   (рядом с шапкой: страница, получившая шапку, получает и навигацию).

   Граница — 720px, та же, что у Литеры. */

/* На компьютере панели нет вовсе: там навигация в шапке, и вторая копия внизу экрана
   отнимала бы место у работы. */
.tabbar{display:none}

@media (max-width:720px){
  :root{
    --tb-h:56px
  }

  /* Под панелью не должно оставаться содержимого: последняя строка любой страницы
     иначе прячется за вкладками, и это замечают не сразу — страница выглядит
     дочитанной. */
  body{padding-bottom:calc(var(--tb-h) + env(safe-area-inset-bottom))}

  /* ⚠️ Поля ввода — 16px, и это не про красоту: Safari на iOS САМ увеличивает страницу
     при фокусе в поле мельче 16px и обратно уже не уменьшает. Портал после первого же
     клика в поле оставался бы «отъехавшим». Общая шкала портала (--кегль-поля 13.5)
     остаётся десктопной. */
  input,select,textarea{font-size:16px}

  /* ── Шапка: сжатая, под вырезом ─────────────────────────────────────────────
     Меню, переключатель модулей, «?» и имя со страницы уходят — всё это лежит внизу,
     в шторках «Модули» и «Ещё». Наверху остаётся только марка и связь. */
  header.top{
    /* Отступ сверху — по безопасному полю. С 11.09.2026 строка состояния НЕ прозрачная
       (`black` вместо `black-translucent`, см. core.ui.голова_приложения), и сверху
       вставка равна нулю; правило остаётся страховкой на случай возврата прозрачной
       полосы и ради горизонтального положения. */
    padding:calc(10px + env(safe-area-inset-top)) 0 22px;
    font-size:13px}
  header.top .hwrap{padding:0 14px; gap:8px 10px; flex-wrap:wrap}
  header.top .onb-help,
  header.top .userbox,
  header.top .tasksbtn{display:none}
  /* ⚠️ Логотипу — авто-отступ СПРАВА, иначе значки липнут к нему, а правая половина
     шапки стоит пустой. Вправо их прижимал `margin-left:auto` у `.onb-help`, но «?» на
     телефоне скрыт — а `.onb-help ~ .headbtn{margin-left:0}` продолжает совпадать:
     `display:none` убирает элемент с ЭКРАНА, но не из дерева, и соседний селектор про
     это ничего не знает. Отступ у логотипа от порядка соседей не зависит вовсе. */
  header.top .logo{gap:10px; min-width:0; margin-right:auto}

  /* ── Меню модуля: своя строка с прокруткой ────────────────────────────────────
     🔑 Прятать его было НЕЛЬЗЯ. «Опросный лист · Подбор · Лиды · Готовые КП ·
     Проверяющий · Доработки · Журнал» — это и есть модуль; на телефоне они остались
     только в шторке «Ещё», то есть в двух нажатиях и без счётчиков. Владелец: «в
     мобильном варианте вот этого меню нет».
     Строка ПРОКРУЧИВАЕТСЯ вбок, а не переносится: семь пунктов в две-три строки съели
     бы пол-экрана на каждой странице, а горизонтальная лента — привычный жест и
     показывает, что дальше что-то есть. Прокрутка своя, у `.menu`, страницу она не
     трогает — это единственное место портала, где уезжать вбок правильно.
     ⚠️ Полосу прокрутки прячем: на телефоне она наложенная и не мешает, а на планшете
     с мышью рисовалась бы поперёк пунктов. */
  header.top .menu{
    order:3; flex:0 0 100%; gap:4px; margin:8px -14px -6px; padding:0 14px 4px;
    /* ⚠️ И `flex-wrap`, и `justify-content` перебиваются ЯВНО: у `.menu` на компьютере
       стоит `wrap` и прижатие вправо, и без сброса лента не поехала бы вбок, а
       развернулась в три строки, прижатые к правому краю (проверено — так и вышло). */
    flex-wrap:nowrap; justify-content:flex-start;
    overflow-x:auto; overflow-y:hidden; -webkit-overflow-scrolling:touch;
    scrollbar-width:none}
  header.top .menu::-webkit-scrollbar{display:none}
  /* Переключатель модулей отсюда убран: у него своя вкладка внизу («Модули»), и вторая
     копия занимала бы первое — самое доступное — место в ленте страниц модуля. */
  header.top .menu>.modsw{display:none}
  header.top .menu a{flex:0 0 auto; padding:7px 12px; font-size:13.5px; white-space:nowrap}
  header.top .mark{width:34px; height:34px; flex:0 0 34px}
  header.top .brand{font-size:16px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis}
  header.top .brand small{font-size:9.5px; letter-spacing:.16em}
  header.top .headbtn{width:32px; height:32px; flex:0 0 32px}

  /* ── Полоса, которую съедает «стекло» iOS ─────────────────────────────────────
     🔑 Отключить стекло НЕЛЬЗЯ — проверено дважды. Свежая iOS рисует его над верхним
     краем прокручиваемого содержимого, и отказ от прозрачной строки состояния
     (`black` вместо `black-translucent`, 11.09) эффект не убрал, а только сдвинул: он
     переехал со строки состояния на верх НАШЕЙ шапки, и размытыми стали логотип с
     значками. Веб-приложению выключателя не дано: `scrollEdgeEffectHidden` и
     `scrollEdgeEffectStyle` — это SwiftUI и UIKit.
     Поэтому остаётся второе решение владельца: «ниже спускать, чтобы не наезжало».
     Отдаём стеклу пустую полосу фирменного фона — размывать в ней нечего.
     🔑 **Включает полосу МЕДИАЗАПРОС, а снимает её скрипт — не наоборот.** Первая версия
     держалась на классе от pwa.js (`:root.айфон.в-приложении`) и не сработала вовсе:
     скрипт приехал из кэша старым, класса не было, правка «не сделала ни хрена». Теперь
     промах скрипта стоит лишних 44px на Android, а не потерянной правки на iPhone —
     из двух отказов выбран безобидный.
     ⚠️ Величина подобрана по живому айфону (замер по скриншоту: тает примерно к 40pt
     от верха веб-вида). Меняя, смотри на ТЕЛЕФОНЕ — ни в браузере, ни в эмуляторе стекла
     нет вовсе, и правка выглядит там пустой тратой места. */
  @media (display-mode: standalone){
    header.top{padding-top:calc(44px + env(safe-area-inset-top))}
  }
  /* Android: стекла нет, полоса не нужна. Класс ставит pwa.js — не доехал, останется
     чуть более высокая шапка, и только. */
  :root.не-айфон header.top{padding-top:calc(10px + env(safe-area-inset-top))}
  .wave{height:26px}
  /* Плашка «ваша доработка выполнена» — от края до края, как и всё остальное. */
  .onbar{margin:10px 12px 0; font-size:13px}

  /* ── Нижняя панель ──────────────────────────────────────────────────────────── */
  .tabbar{
    display:flex; position:fixed; left:0; right:0; bottom:0; z-index:80;
    height:calc(var(--tb-h) + env(safe-area-inset-bottom));
    padding-bottom:env(safe-area-inset-bottom);
    /* Стекло: цвет — токеном, прозрачность — здесь. Жёсткое rgba(255,255,255,.94)
       пережило бы смену темы белой полосой поперёк тёмного экрана. */
    background:color-mix(in srgb, var(--card) 94%, transparent);
    -webkit-backdrop-filter:blur(12px); backdrop-filter:blur(12px);
    border-top:1px solid var(--line); box-shadow:0 -2px 14px rgba(11,58,84,.07);
    font-family:system-ui,-apple-system,"Segoe UI",Roboto,Arial,sans-serif}
  /* ⚠️ Всё, что может прилететь со страницы, гасим ЯВНО. Модули стилизуют ГОЛЫЕ
     details/summary под свои раскрывающиеся блоки (у прайсов — белая карточка с рамкой
     и своей стрелкой), и без этих сбросов вкладки «Модули» и «Ещё» выглядели в прайсах
     двумя полями ввода поверх панели. Ровно та же грабля уже была у `.modsw` в шапке —
     потому и селекторы такие же приземлённые, от `.tabbar`. */
  .tabbar details,.tabbar summary{
    background:none; border:0; margin:0; padding:0; box-shadow:none; border-radius:0}
  /* Каждый пункт — ровно четверть ширины: вкладки не должны переставлять друг друга
     при появлении бейджа. */
  .tabbar>a,.tabbar>details{flex:1 1 0; min-width:0}
  .tabbar>a,.tabbar summary{
    display:flex; flex-direction:column; align-items:center; justify-content:center;
    gap:2px; height:var(--tb-h); color:var(--muted); text-decoration:none; font-size:10.5px;
    font-weight:600; letter-spacing:.01em; cursor:pointer; list-style:none;
    position:relative; -webkit-tap-highlight-color:transparent; touch-action:manipulation;
    /* Выделения текста при нажатии на вкладку быть не должно: длинное касание по
       подписи подсвечивало её синим, как в документе, — в приложении так не бывает. */
    -webkit-user-select:none; user-select:none}
  .tabbar summary::-webkit-details-marker{display:none}
  .tabbar summary::before,.tabbar summary::after{content:none}
  .tabbar>a>span,.tabbar summary>span{white-space:nowrap}
  /* Значок в «таблетке»: активную вкладку одним цветом на светлом фоне почти не видно —
     ровно та же грабля, что у Литеры с нижними вкладками. */
  .tabbar>a>svg,.tabbar summary>svg{
    padding:2px 12px; border-radius:999px; box-sizing:content-box; transition:.15s}
  .tabbar>a.тек{color:var(--teal-d)}
  .tabbar>a.тек>svg{background:var(--bg1)}
  .tabbar details[open]>summary{color:var(--teal-d)}
  .tabbar details[open]>summary>svg{background:var(--bg1)}
  .tabbar>a:active>svg,.tabbar summary:active>svg{transform:scale(.92)}
  .tb-cnt{position:absolute; top:2px; left:calc(50% + 6px); min-width:17px; height:17px;
    padding:0 5px; border-radius:9px; background:var(--amber); color:var(--onAmber);
    font-size:10.5px; font-weight:700; line-height:17px; text-align:center}

  /* ── Шторки ─────────────────────────────────────────────────────────────────
     Лист выезжает НАД панелью, а не поверх всего экрана: вкладки остаются видны, и
     нажатие на ту же вкладку закрывает лист — это единственный способ закрыть его без
     скрипта (см. core.ui.таббар). */
  .tb-шторка{position:static}
  /* Появление шторки. Без него лист возникает мгновенно и читается как подмена экрана:
     непонятно, выехало снизу или страница сменилась. Восемнадцать сотых — ровно столько,
     чтобы глаз успел заметить направление и не начал ждать.
     ⚠️ Анимация, а не переход: `<details>` переключает `display`, а `transition` на
     появление из `display:none` не работает — до `@starting-style` доросли не все, кем
     портал открывают. */
  @keyframes выезд-шторки{from{transform:translateY(14px); opacity:0} to{transform:none; opacity:1}}
  .tb-шторка[open] .tb-лист{animation:выезд-шторки .18s ease-out}
  @media (prefers-reduced-motion:reduce){
    .tb-шторка[open] .tb-лист{animation:none}
  }
  .tb-лист{
    position:fixed; left:0; right:0; z-index:79;
    bottom:calc(var(--tb-h) + env(safe-area-inset-bottom));
    max-height:70dvh; overflow-y:auto; -webkit-overflow-scrolling:touch;
    background:var(--card); border-top:1px solid var(--line); border-radius:16px 16px 0 0;
    padding:10px 12px 16px; color:var(--strong);
    box-shadow:0 -18px 44px rgba(6,28,42,.24)}
  .tb-заг{font-size:10.5px; font-weight:700; letter-spacing:.14em; text-transform:uppercase;
    color:var(--muted); padding:10px 8px 6px}
  .tb-меню{display:flex; flex-direction:column; gap:2px}
  .tb-меню a{display:flex; align-items:center; gap:9px; padding:12px 10px; border-radius:11px;
    color:var(--strong); text-decoration:none; font-size:15px; font-weight:600; background:none}
  .tb-меню a:active{background:var(--bg1)}
  .tb-меню a.active,.tb-меню a.тек{background:var(--bg1); color:var(--teal-d)}
  .tb-меню a .cnt{margin-left:auto}
  .tb-меню a>svg{flex:0 0 auto; color:var(--muted2)}
  .tb-меню a.тек>svg,.tb-меню a.active>svg{color:var(--teal-d)}
  .tb-меню a.modmenu-home{color:var(--teal-d); border-bottom:1px solid var(--line); border-radius:11px 11px 0 0}
  /* Тот же разделитель в шторке телефона: перечень модулей там строится той же
     функцией (core.ui.пункты_модулей), и второй стиль разъехался бы с первым. */
  .tb-меню .modmenu-раздел{font-size:10.5px; font-weight:700; letter-spacing:.14em;
    text-transform:uppercase; color:var(--muted); padding:12px 10px 4px; margin-top:4px;
    border-top:1px solid var(--line)}
  .tb-меню a.modmenu-home + .modmenu-раздел{border-top:0; margin-top:0}
  /* ⚠️ `display` в СВОИХ правилах перебивает атрибут `hidden`: у браузерного
     `[hidden]{display:none}` специфичность 0,0,1, а у любого правила по классу выше.
     Кнопку установки и подсказку скрывает/показывает pwa.js именно этим атрибутом, и
     из-за одного `display:block` ниже кнопка «Установить приложение» висела на экране
     всегда — в том числе там, где установить нечего. Возвращаем атрибуту силу; правило
     нарочно ограничено панелью, а не всей страницей: у модулей свои `[hidden]`. */
  .tabbar [hidden]{display:none !important}
  /* Установка на домашний экран — то, ради чего всё и делалось. Кнопку показывает
     core/static/pwa.js (у Chrome есть событие), подсказку — он же для iOS. */
  .tb-ставим{display:block; width:100%; margin:12px 0 0; padding:13px 16px; border:0;
    border-radius:12px; background:var(--teal); color:var(--onAccent); font-size:15px; font-weight:700}
  .tb-подсказка{margin:12px 2px 0; font-size:12.5px; line-height:1.45; color:var(--muted)}
  /* Уже установлено — предлагать установку незачем. */
  :root.в-приложении .tb-ставим,:root.в-приложении .tb-подсказка{display:none}
}

/* ══ СТРАНИЦА МОДУЛЯ НА ТЕЛЕФОНЕ — общий слой ═══════════════════════════════════
   «Дальше нужно адаптировать все модули под вид мобильного приложения» (владелец,
   11.09.2026). Обход всех страниц на 375px показал три одинаковые беды у всех модулей
   сразу — поэтому и лечатся они ЗДЕСЬ, одним местом, а не двадцатью копиями:
   - кнопки высотой 28–36px («Обновить», фильтры «Все / Открытые», «Мои / Я поручил»)
     и поля 32–38px — палец в них попадает через раз; норма касания — 44 точки;
   - вступление под заголовком в 5–7 строк: на телефоне это целый экран до первой
     кнопки, а читают его один раз;
   - контейнер страницы с полями по 20–24px, а у «Оплат» и «Клиентов» ещё и
     `max-width:90vw` — на телефоне содержимое сжималось до 290px из 375.

   🔑 Селекторы начинаются с `body` НАРОЧНО. Стили модулей идут ПОСЛЕ header.css, и
   правило той же специфичности («.wrap», «button») у модуля выигрывало бы у общего слоя.
   `body .wrap` (0,1,1) бьёт `.wrap` (0,1,0) без `!important`, которым потом не
   перебить ничего.

   ⚠️ Шапка и нижняя панель из правил касания ИСКЛЮЧЕНЫ (`:not(header.top *)`,
   `:not(.tabbar *)`): у них свои выверенные размеры, и 44px сломали бы им геометрию. */
@media (max-width:720px){
  body .wrap{max-width:none; padding-left:14px; padding-right:14px}
  body .wrap h1{font-size:22px; line-height:1.2}

  /* Вступление — три строки, по касанию раскрывается целиком (core/static/pwa.js).
     Обрезаем, а не прячем: текст объясняет, что делать на странице, и первые три строки
     — это обычно вся суть; остальное — оговорки для того, кто уже спросил «а почему». */
  /* `.intro` — у «Проверяющего» вступление стоит не под заголовком, а после строки
     счётчиков и фильтров, отдельным блоком; семь строк, самое длинное на портале. */
  body :is(.wrap h1 + p, .wrap .intro){display:-webkit-box; -webkit-box-orient:vertical;
    -webkit-line-clamp:3; overflow:hidden}
  body :is(.wrap h1 + p, .wrap .intro).обрезано{cursor:pointer}
  body :is(.wrap h1 + p, .wrap .intro).раскрыто{display:block; -webkit-line-clamp:unset;
    overflow:visible}

  /* Цели касания — 44 точки. min-height, а не height: у кнопки в две строки текста
     высота растёт сама, и зажимать её нельзя. */
  body :is(button, .btn, [type=submit], [type=button]):not(header.top *):not(.tabbar *){
    min-height:44px}
  /* Ссылка-кнопка сама текст по высоте не центрирует, в отличие от <button>. */
  body a.btn:not(header.top *):not(.tabbar *){display:inline-flex; align-items:center;
    justify-content:center}
  /* Сегменты «Авто / Варианты / Перечень» и чипы — это <label> и <span>, а не кнопки,
     но нажимают их так же. */
  body :is(.seg label, .chip):not(header.top *):not(.tabbar *){min-height:44px;
    display:inline-flex; align-items:center}
  body :is(input:not([type=checkbox]):not([type=radio]):not([type=range]):not([type=color]):not([type=file]):not([type=hidden]),
           select):not(header.top *):not(.tabbar *){min-height:44px}
  /* Ссылки, оформленные кнопками, — правило выше их не видит: это <a>, а не <button>.
     Замер нашёл их по рамке/фону с отступами и высоте ниже 40: «⬇ КП .pdf» и «Смета .xlsx»
     в лидах (36px), действия в «Проверяющем» и «Доработках», ссылки журнала, фильтры
     «Что нового» (31px), «Скачать WireGuard» на «Удалённой работе» (34px). Перечень
     контейнеров, а не «все ссылки»: ссылка в тексте абзаца кнопкой не становится. */
  body :is(.acts, .grpacts, .links, .фильтр) a, body a.скачать{min-height:44px;
    display:inline-flex; align-items:center; justify-content:center}
  /* Подписи полей КАПСОМ — 12px вместо 11: вразрядку и капсом 11px на телефоне читается
     с усилием, а над каждым полем опросного листа и подбора их по двадцать штук. */
  body .wrap :is(.lab, .поле > label){font-size:12px}

  /* ── Модальные окна → листы ──────────────────────────────────────────────────
     На компьютере предпросмотр КП и сметы — окно с полями по 24px вокруг; на телефоне
     эти поля съедают десятую часть экрана у PDF, который и так мелкий. Лист во весь
     экран, полоса с названием и «закрыть» — сверху, как у приложения.
     🔑 Только `.modal.open`: у «Проверяющего» `.modal` — ВНУТРЕННЕЕ окно в своём
     оверлее `.ovl`, и класса `open` оно не получает никогда (сверено по скрипту).
     Правило на голый `.modal` сняло бы ему фон и скругление.
     ⚠️ z-index 90 — выше нижней панели (80) и компактной шапки (70): у оверлеев модулей
     стояло 50, и панель легла бы поверх низа предпросмотра (KIT-49 — шапка поверх верха). */
  body .modal.open{padding:env(safe-area-inset-top) 0 0; z-index:90}
  body .modal.open :is(.head, .mhead){margin:0; padding:8px 12px}
  body .modal.open .pvbody{border-radius:0}
  body .modal.open :is(.head, .mhead) .x{width:44px; height:44px; flex-basis:44px}
  /* «Проверяющий»: окно вопроса рассчитано на 900×1100 — на телефоне только во весь экран. */
  body .ovl.on{padding:0; align-items:stretch; justify-content:stretch; z-index:90}
  body .ovl.on > .modal{width:100%; height:100%; max-height:none; border-radius:0;
    padding-top:env(safe-area-inset-top)}
  /* Короткий диалог подтверждения (конфигуратор) — шторкой снизу, как системные. */
  body .завеса.открыта{align-items:flex-end; justify-content:stretch; padding:0; z-index:90}
  body .завеса.открыта > .диалог{max-width:none; border-radius:18px 18px 0 0;
    padding-bottom:calc(24px + env(safe-area-inset-bottom)); animation:выезд-шторки .2s ease-out}

  /* ── Главная кнопка длинной формы — всегда под пальцем ───────────────────────
     Опросный лист — 3900px, генератор сервиса — 1600px; «Далее» и «Собрать КП» стоят в
     самом конце, и до них листают по пять экранов.
     `position:sticky`, а не `fixed`: пока форма на экране, кнопка висит над нижней
     панелью; дошёл до конца — встаёт на своё место. `fixed` закрывал бы последнее поле
     формы навсегда.
     ⚠️ Липкий элемент не покидает СВОЕГО РОДИТЕЛЯ. У этих двух кнопка — прямой ребёнок
     всей формы, и липнет на всю её высоту. У «Собрать смету и КП» в конфигураторе
     родитель — строка кнопок в последней карточке высотой 216px, и sticky там не делает
     ничего (замерено: кнопка ниже экрана). Без переделки разметки не лечится, а
     страница там всего в два экрана — поэтому её здесь нет. */
  /* ⚠️ Зазор 18px, хотя задуманы 10: замер на 375px показал кнопку ВПЛОТНУЮ к панели
     при вычисленном `bottom:66px` — десять точек куда-то уходят, и на всех трёх
     замерах одинаково. Причину не нашёл; 18 дают видимый зазор и там, где они уходят,
     и там, где нет (тогда просто 18). */
  body .cta#go{position:sticky; z-index:6;
    bottom:calc(var(--tb-h) + env(safe-area-inset-bottom) + 18px);
    box-shadow:0 10px 28px rgba(0,0,0,.35)}

  /* Главная кнопка там, где sticky бессилен — у кнопки короткий родитель: закреплена
     над панелью. «Собрать смету и КП» в конфигураторе стоит в строке из четырёх кнопок
     последней карточки, «Собрать .docx» в договорах — в своей строке под формой.
     Помечаются в разметке классом `главное-действие`, а не перечнем id здесь: какую
     кнопку считать главной, решает страница.
     Запас снизу у страницы — чтобы последняя карточка не уходила под кнопку. */
  body .главное-действие{position:fixed; z-index:6; left:14px; right:14px; width:auto;
    margin:0; min-height:48px; bottom:calc(var(--tb-h) + env(safe-area-inset-bottom) + 10px);
    box-shadow:0 10px 28px rgba(0,0,0,.35)}
  body .wrap:has(.главное-действие){padding-bottom:calc(48px + 10px + 24px)}
}

/* ══ ФОН ОКНА ПРЕДПРОСМОТРА — непрозрачный ══════════════════════════════════════════
   У окна предпросмотра (`.modal.open` в четырёх модулях) фон был `rgba(…, .55)`: полоса с
   именем файла, «Правками», «Скачать» и «×» лежала прямо на полупрозрачной завесе, и
   сквозь неё проступали кнопки шапки страницы — значки, меню, «Выйти», рядом с кнопками
   самого окна (владелец, 11.09.2026). Ровно эту беду уже лечили у разметки доработок
   (`.kprev`, фон .97 — «текст на тексте, нечитаемо»); здесь то же решение, одним местом
   на все четыре окна.
   На компьютере завеса почти непрозрачная (страница угадывается, но не читается), на
   телефоне окно во весь экран, и завеса там — просто фон приложения.
   `body .modal.open` (0,2,1) бьёт и `.modal`, и `.modal.open` модулей без `!important`. */
body .modal.open{background:rgba(6,22,32,.9); -webkit-backdrop-filter:blur(4px); backdrop-filter:blur(4px)}
@media (max-width:720px){
  body .modal.open{background:var(--deep1); -webkit-backdrop-filter:none; backdrop-filter:none}
}

/* ══ ПРЕДПРОСМОТР ДОКУМЕНТОВ — страницы картинками и неподвижный фон ═══════════════
   На телефоне и планшете core/static/pwa.js показывает документ столбиком страниц PNG
   вместо PDF в iframe: iOS рисует такой PDF одной неподвижной первой страницей.
   Условие то же, что у скрипта, — касание без наведения, а не ширина экрана. */
.pvbody .страницы{position:absolute; inset:0; overflow-y:auto; overscroll-behavior:contain;
  -webkit-overflow-scrolling:touch; padding:10px; display:flex; flex-direction:column;
  gap:10px; background:var(--bg2)}
/* Страница — бумага, в обеих темах белая: это вид документа, который уйдёт заказчику. */
.pvbody .страницы img{display:block; width:100%; height:auto; background:#fff;
  border-radius:4px; box-shadow:0 2px 10px rgba(0,0,0,.25)}

/* 🔑 Фон под открытым окном не прокручивается. Раньше жест, не нашедший, что листать в
   окне, уходил на страницу позади — «двигается только сайт позади модалки». Держим ОБА
   запрета: `overflow:hidden` у корня останавливает страницу, `overscroll-behavior:contain`
   у самого окна не отдаёт наружу докрученную до края прокрутку.
   ⚠️ Список окон — все оверлеи портала: предпросмотр (`.modal.open`), окно
   «Проверяющего» (`.ovl.on`), подтверждение конфигуратора (`.завеса.открыта`) и
   разметка доработок (`.kprev.open`). Новое окно без записи сюда оставит фон живым. */
.карт-знач{display:contents}
html:has(.modal.open, .ovl.on, .завеса.открыта, .kprev.open){overflow:hidden}
.modal.open, .ovl.on, .завеса.открыта, .kprev.open{overscroll-behavior:contain}

/* 🔑 **Прокрутка внутри блока НЕ уезжает на страницу** — то же правило, что у окон выше,
   но для любого блока со своей полосой: списка заказов 1С, стенограммы планёрки,
   бокового оглавления вики, длинной таблицы договоров. Владелец, 20.09.2026: «промотаешь
   список до конца — а потом страница уезжает».
   ⚠️ **Правилом ядра, а не свойством у каждого блока:** приём уже стоял точечно в пяти
   местах из десяти, и новый прокручиваемый блок про него забывал — а заметить это можно
   только колесом мыши, ровно в тот момент, когда список докручен до края.
   ⚠️ **Кроме корня:** `overscroll-behavior` у `html`/`body` выключает «потянуть, чтобы
   обновить» на телефоне — это не то, о чём просили. Элементам без своей прокрутки
   правило не делает ничего.
   ⚠️ **Кроме многострочного поля:** `textarea` браузер считает прокручиваемым ВСЕГДА, даже
   когда текст помещается и полосы нет, — и колесо над полем «Приход из чата» не крутило
   страницу вовсе (владелец, 07.10.2026). Поле с длинным текстом, докрученное до края,
   отдаёт прокрутку странице — как в любом браузере. */
*:not(html):not(body):not(textarea){overscroll-behavior:contain}

/* Подсказки-тур («Действия с документом» и нижняя полоса «Подсказки по интерфейсу») на
   телефоне поверх предпросмотра НЕ показываются: пузырь, рассчитанный на окно шириной в
   900px, ложился прямо на документ и закрывал его половину. Тур привязан к окну и сам
   снимается при его закрытии (onboarding.js отделов), поэтому прятать достаточно, пока
   окно открыто. Условие — касание без наведения, как у предпросмотра страницами. */
@media (hover:none) and (pointer:coarse){
  html:has(.modal.open) :is(.onb-ov, .onb-bub, .onb-bar){display:none !important}
}

/* ══ ТАБЛИЦЫ КАРТОЧКАМИ (телефон) ════════════════════════════════════════════════
   Таблица в десять колонок на экране 390px не сжимается — она уезжает вбок вместе со
   всей страницей. Помеченная `class="карточками"` таблица на телефоне разворачивается:
   строка становится карточкой, ячейка — парой «подпись — значение». Подписи проставляет
   core/static/pwa.js (атрибут `data-label`), беря их из строки заголовков самой таблицы.

   Механика ОБЩАЯ и лежит здесь, а не у модулей: оплаты и прайсы получили её вместе, и
   вторая копия разъехалась бы — у одного модуля карточки, у другого прокрутка вбок.
   Включается только классом: не всякая таблица портала выигрывает от разворота, и
   молча переверстать все — не то же самое, что дать модулю это выбрать.

   ⚠️ Без подписей карточка бессмысленна: без скрипта таблица остаётся ТАБЛИЦЕЙ (правила
   ниже требуют `data-label` там, где он нужен, но саму раскладку включают всегда) —
   поэтому в разметке модулей у широких таблиц по-прежнему стоит `.прокрутка`: она
   остаётся запасным путём, если скрипт не доехал. */
@media (max-width:720px){
  /* ⚠️ `!important` здесь не роскошь: ширины заданы по id (`#таб-чс{min-width:1020px}`,
     специфичность 1,0,0) и в `<style>` страницы, который идёт ПОСЛЕ header.css. Без него
     таблица осталась бы шириной в тысячу пикселей, только уже карточками. */
  table.карточками{display:block; width:100% !important; min-width:0 !important;
    border-collapse:collapse}
  .карточками thead{display:none}
  .карточками tbody{display:block}
  /* У прайсов строка заголовков лежит первой строкой ВНУТРИ tbody, а не в thead —
     прячем и её, иначе первой «карточкой» станут названия колонок. */
  .карточками tbody>tr:has(th){display:none}
  .карточками tr{display:block; margin:0 0 10px; padding:10px 12px;
    background:var(--card); border:1px solid var(--line); border-radius:12px;
    box-shadow:0 1px 2px rgba(11,58,84,.04)}
  .карточками td{display:grid; grid-template-columns:minmax(84px,36%) 1fr; gap:10px;
    align-items:baseline; padding:4px 0; border:0 !important;
    width:auto !important; max-width:none !important;
    text-align:left !important; white-space:normal !important}
  .карточками td::before{content:attr(data-label); color:var(--muted); font-size:11.5px;
    font-weight:700; letter-spacing:.02em; line-height:1.5}
  /* Колонка без заголовка — это кнопка действия, а не поле: подпись ей не нужна, и
     место под неё тоже. */
  .карточками td[data-label=""]{display:block}
  .карточками td[data-label=""]::before{content:none}
  /* Пустая ячейка карточку только удлиняет. `:empty` ловит ячейки без единого узла;
     прочерк «—» модули ставят сами и он остаётся — это их слово, а не наше. */
  .карточками td:empty{display:none}
  /* Ячейка карточки — сетка, и плашка/тег в ней становится клеткой: растягивается на
     всю ширину значения («из таблицы» во всю карточку). Метки — по своему тексту. */
  .карточками td > :is(.плашка, .тег, .badge),
  .карточками td > :is(span, b, em, small):only-child{justify-self:start}
  /* Несколько узлов ячейки pwa.js сводит в одну `.карт-знач` — она и есть значение. */
  .карточками td > .карт-знач{display:block; min-width:0}
  /* Пустая таблица («оплаты пока не хранятся») — одна ячейка `.пусто`. Как первая
     ячейка она получала оформление заголовка карточки: жирно, с чертой и в рамке.
     Это подпись, а не запись — без рамки, обычным серым текстом. */
  .карточками tr:has(> td.пусто:only-child){background:none; border:0; box-shadow:none;
    padding:4px 0; margin:0}
  /* Строка из ОДНОЙ ячейки на всю ширину (colspan) — не запись, а вставка: раскрытая
     форма правки у оплат, пояснение под строкой. Как первая ячейка она получала оформление
     заголовка карточки — вся форма правки жирным 15px с чертой, в третьей рамке подряд. */
  .карточками tr:has(> td[colspan]:only-child){background:none; border:0; box-shadow:none;
    padding:0}
  .карточками td[colspan]:only-child{font-weight:400; font-size:inherit;
    border-bottom:0 !important; padding:0; margin:0}
  .карточками td.пусто:only-child{font-weight:400; font-size:14px; color:var(--muted);
    border-bottom:0 !important; padding:0; margin:0}
  /* Первая ячейка — заголовок карточки: у оплат это дата, у прайсов артикул или
     поставщик. Без этого карточка читается как ровный список из десяти строк, в котором
     не за что зацепиться глазом. */
  .карточками td:first-child{display:block; font-weight:700; font-size:15px;
    padding:0 0 6px; margin-bottom:4px; border-bottom:1px solid var(--line2) !important}
  .карточками td:first-child::before{content:none}
  /* Кнопки внутри карточки — во всю ширину: «Позиции» и «Вернуть в подбор» шириной в
     палец нажимаются, шириной в семьдесят пикселей — как повезёт. */
  .карточками td button{width:100%; padding:10px 12px; margin-top:4px}
  /* Обёртка прокрутки модуля больше не нужна: содержимое влезло. Оставленная прокрутка
     даёт «полтора пикселя вбок» и страницу, которая дрожит под пальцем. */
  .прокрутка:has(>table.карточками){overflow-x:visible}
}

/* ── Кромка под строкой состояния (приложение с главного экрана, iOS 26) ───────────
   Над строкой состояния iOS рисует размытие-«фейд» и красит его по ЦВЕТУ страницы: по
   закреплённому у верхнего края элементу, иначе по фону страницы. Фон главной — только
   градиент (`background-color` прозрачный), и в светлой теме устройства фейд выходил
   белёсым поверх тёмно-синей шапки (владелец, 11.09.2026). В тёмной теме этого не было:
   там у `body` сплошной тёмный фон. Даём iOS, что взять: тонкую закреплённую полосу
   цвета шапки ровно в зону строки состояния и тот же цвет у корня страницы (он же
   виден при оттягивании страницы вниз — в тон шапке). `body::after`, а не `::before`:
   `::before` у главной занят сеткой-текстурой. */
@media (display-mode: standalone){
  html{background-color:var(--deep1)}
  body::after{content:""; position:fixed; top:0; left:0; right:0;
    height:env(safe-area-inset-top); background:var(--deep1);
    z-index:2147483000; pointer-events:none}
}

/* ── Низкий экран: телефон горизонтально ──────────────────────────────────────────
   На 667×375 закреплённые панель (56px) и главная кнопка над ней (48px + зазоры)
   съедали почти треть высоты, а шапка с меню модуля — ещё треть, пока не прокрутишь.
   Здесь панель — только значки (44px; счётчик задач `span.tb-cnt` остаётся — прячутся
   подписи без класса), главная кнопка — обычной кнопкой на своём месте. */
@media (max-width:720px) and (max-height:480px){
  :root{--tb-h:44px}
  :is(.tabbar>a, .tabbar summary)>span:not([class]){display:none}
  body .главное-действие{position:static; left:auto; right:auto; width:100%; margin:12px 0 0;
    box-shadow:none}
  body .wrap:has(.главное-действие){padding-bottom:24px}
  body .cta#go{position:static; box-shadow:none}
}

/* ── Поля ввода на телефоне — 16px ─────────────────────────────────────────────────
   Safari на айфоне УВЕЛИЧИВАЕТ страницу при фокусе в поле мельче 16px и сам её обратно
   не уменьшает: дальше человек водит страницу пальцем. Прогон 11.09.2026: 13,5px в
   опросном листе, оплатах, прайсах и конфигураторе, 14,5 в договорах, 15 в карточке —
   16 было только у «Задач». Модули задают кегль полей своими селекторами (в том числе
   по id), поэтому `!important`: это не оформление, а условие, при котором поле вообще
   можно заполнить без возни. Галки, переключатели и ползунки не трогаем — у них нет
   клавиатуры и зума. */
@media (max-width:720px){
  body :is(input:not([type=checkbox]):not([type=radio]):not([type=range]):not([type=file]),
    select, textarea){font-size:16px !important}
}

/* ── Вырез экрана сбоку: айфон горизонтально ───────────────────────────────────────
   Страница растянута под вырез (`viewport-fit=cover`), а боковых отступов по безопасным
   полям не было нигде: в горизонтальном положении края текста уходили под «чёлку».
   Отступ — у body: на устройствах без выреза он нулевой, и ни на компьютере, ни на
   планшете ничего не меняется. Страницы входа и ошибок ставят свой отступ позже, с
   теми же полями (`СТИЛЬ_ВХОДА`), — их longhand здесь не перебивает. */
body{padding-left:env(safe-area-inset-left); padding-right:env(safe-area-inset-right)}

/* ── «Залипающее» наведение на сенсорных экранах ───────────────────────────────────
   На айфоне `:hover` после касания остаётся на элементе, пока не коснёшься другого
   места: кнопки «Доработок» и «Проверяющего», плитки главной и опросного листа так и
   оставались приподнятыми (`transform` в `:hover`, ~13 правил по модулям). На экранах
   без наведения подъём снимаем у кликабельного. `:not(:active)` — чтобы не погасить
   отклик на само нажатие, пока палец на кнопке. */
@media (hover:none) and (pointer:coarse){
  :is(a, button, summary, label, [role=button], .btn):hover:not(:active){transform:none !important}
}

/* ══ ПРОСМОТР КАРТИНКИ ОКНОМ ПОВЕРХ СТРАНИЦЫ ══════════════════════════════════════
   Галерея — любой контейнер с `data-галерея`, внутри ссылки на сами изображения
   (скриншоты ленты «Что нового», фотографии отчёта о выезде). Клик открывает снимок
   окном, стрелки листают соседние снимки ТОЙ ЖЕ галереи.
   🔑 **Одно место на портал, а не копия в шаблоне.** До 22.09.2026 окно жило только в
   `changes.html`, и фотографии выезда открывались отдельной вкладкой — то есть новая
   галерея про общий приём просто не знала. Скрипт — `core/static/pwa.js`.
   Затемнение одинаково тёмное в обеих темах: это рама для картинки, а не часть страницы. */
[data-галерея] a{cursor:zoom-in}
.лайтбокс{position:fixed; inset:0; z-index:1100; display:grid;
  grid-template-columns:56px minmax(0,1fr) 56px; grid-template-rows:minmax(0,1fr);
  align-items:center; justify-items:center; gap:8px;
  padding:28px 16px; background:rgba(6,16,24,.9); -webkit-backdrop-filter:blur(6px);
  backdrop-filter:blur(6px)}
.лайтбокс[hidden]{display:none!important}
/* Строка сетки не выше окна (minmax(0,1fr) у .лайтбокс), а картинка — не выше экрана:
   иначе крупный снимок растягивал строку, и «по центру» уводило его вниз за край. */
.лб-кадр{margin:0; display:flex; flex-direction:column; align-items:center; gap:12px;
  min-width:0; min-height:0; max-height:100%}
.лб-кадр img{display:block; max-width:100%; max-height:calc(100vh - 130px); object-fit:contain;
  border-radius:12px; box-shadow:0 24px 70px rgba(0,0,0,.55); background:#fff}
.лб-кадр figcaption{max-width:70ch; color:#e4eff5; font-size:14.5px; text-align:center}
.лб-счёт{color:#9ab2c0; font-variant-numeric:tabular-nums}
.лайтбокс button{width:46px; height:46px; border:1px solid rgba(255,255,255,.2); border-radius:12px;
  background:rgba(255,255,255,.08); color:#fff; font-size:26px; line-height:1; cursor:pointer}
.лайтбокс button:hover{background:rgba(255,255,255,.18)}
.лайтбокс button:focus-visible{outline:2px solid var(--teal); outline-offset:2px}
.лб-закрыть{position:absolute; top:calc(14px + env(safe-area-inset-top)); right:14px}
.лайтбокс.один .лб-назад, .лайтбокс.один .лб-вперёд{visibility:hidden}
@media (max-width:640px){
  .лайтбокс{grid-template-columns:minmax(0,1fr); padding:64px 10px 84px}
  .лб-назад, .лб-вперёд{position:absolute; bottom:calc(18px + env(safe-area-inset-bottom))}
  .лб-назад{left:18px}
  .лб-вперёд{right:18px}
}

/* ══ КОМПАКТНАЯ ШАПКА ══════════════════════════════════════════════════════════════
   Пока полная шапка за верхом экрана, сверху висит её узкая полоса: знак, название
   модуля и значки — заявка, загрузка, база знаний, чат, задачи. Без неё значок «Заявка
   на доработку» был бы недоступен ровно там, где о доработке и думают: посреди длинного
   списка (владелец, 07.10.2026). Переключает `core/static/pwa.js` классом на <html>.
   🔑 Это ТА ЖЕ шапка, а не копия: значки, счётчик задач и их обработчики одни.
   🔑 `--шапка-над` — высота полосы (0, пока полная шапка на экране). Каждое липкое
   правило портала прибавляет её к своему `top`, иначе заголовки таблиц и пульт
   редактора уезжали бы под полосу; стережёт `test_липкое_учитывает_компактную_шапку`.
   Блок стоит в КОНЦЕ файла: он обязан перебить телефонный отступ шапки под строку
   состояния (`:root.не-айфон header.top` той же силы). */
:root{--шапка-над:0px}
html{scroll-padding-top:var(--шапка-над)}
.шапка-место{display:none}
:root.шапка-сжата .шапка-место{display:block}
/* Фон — явно: у главной своей заливки у шапки нет (фон там у всей страницы), и полоса
   выходила прозрачной поверх плиток. */
:root.шапка-сжата header.top{position:fixed; top:0; left:0; right:0; z-index:70;
  background:linear-gradient(135deg,var(--deep1),var(--deep2));
  padding:6px 0; padding-top:calc(6px + env(safe-area-inset-top));
  box-shadow:0 6px 18px rgba(0,0,0,.28); animation:шапка-въезд .16s ease-out}
:root.шапка-сжата header.top::before,
:root.шапка-сжата header.top .wave,
:root.шапка-сжата header.top .menu{display:none}
:root.шапка-сжата header.top .logo{gap:10px}
:root.шапка-сжата header.top .mark{width:28px; height:28px; flex:0 0 28px}
:root.шапка-сжата header.top .brand{display:flex; align-items:baseline; gap:8px; font-size:15px}
:root.шапка-сжата header.top .brand small{margin-top:0}
:root.шапка-сжата header.top .headbtn,
:root.шапка-сжата header.top .onb-help{width:30px; height:30px; flex:0 0 30px}
/* Телефон: значков пять, а ширины 390 px — полоса в ОДНУ строку, вместо «КИТ-СВ ·
   Оплаты» только название модуля (font-size:0 гасит текст бренда, но не его подпись). */
@media (max-width:720px){
  :root.шапка-сжата header.top .hwrap{flex-wrap:nowrap}
  :root.шапка-сжата header.top .logo{min-width:0; margin-right:auto}
  :root.шапка-сжата header.top .brand{font-size:0; min-width:0; overflow:hidden}
  :root.шапка-сжата header.top .brand small{font-size:12px; letter-spacing:.12em;
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis}
}
@keyframes шапка-въезд{from{transform:translateY(-100%)}to{transform:none}}
@media (prefers-reduced-motion:reduce){:root.шапка-сжата header.top{animation:none}}

/* ══ ЗНАЧКИ ШАПКИ: ПОДПИСЬ ПРИ НАВЕДЕНИИ ═════════════════════════════════════════
   Под значком мягко проявляется плашка с его названием (владелец, 16.10.2026: вместо
   системной подсказки `title`, которая всплывала через секунду серым квадратом).
   🔑 Подпись — `aria-label` самой кнопки, своей копии названий в CSS нет: значок
   добавят — подпись появится сама, переименуют — не разъедется.
   🔑 Плашка ПОВЕРХ страницы, а не в ряду: первая редакция раздвигала значок в
   «таблетку» с названием, и ряд (он прижат вправо) ездил под мышью — «пляшут, грубо»
   (владелец, 16.10.2026). Здесь раскладка не меняется вовсе, анимируются только
   прозрачность и transform.
   Появление — с короткой задержкой (мышь, проведённая по ряду, не зажигает каждый
   значок по пути), исчезновение — быстрее и сразу. Только где есть мышь и шире
   телефона: касанием «наведения» нет, а на телефоне значки живут в нижней панели. */
@media (hover:hover) and (pointer:fine) and (min-width:721px){
  header.top .hwrap>:is(.headbtn,.onb-help){position:relative}
  header.top .hwrap>:is(.headbtn,.onb-help)::after,
  header.top .hwrap>:is(.headbtn,.onb-help)::before{position:absolute; left:50%; top:100%;
    pointer-events:none; opacity:0; z-index:80;
    transition:opacity .14s ease, transform .14s ease; transition-delay:0s}
  header.top .hwrap>:is(.headbtn,.onb-help)::after{content:attr(aria-label);
    margin-top:9px; padding:6px 11px; border-radius:9px; white-space:nowrap;
    background:rgba(9,32,47,.94); color:#fff; border:1px solid rgba(255,255,255,.14);
    box-shadow:0 10px 28px rgba(0,0,0,.32), 0 2px 6px rgba(0,0,0,.18);
    font-size:12.5px; font-weight:600; letter-spacing:.01em; line-height:1.2;
    transform:translate(-50%, -4px) scale(.96); transform-origin:50% 0}
  /* Стрелка — квадрат, повёрнутый на 45°, той же заливки и с той же каймой сверху. */
  header.top .hwrap>:is(.headbtn,.onb-help)::before{content:""; width:9px; height:9px;
    margin-top:5px; background:rgba(9,32,47,.94);
    border-left:1px solid rgba(255,255,255,.14); border-top:1px solid rgba(255,255,255,.14);
    border-radius:2px 0 0 0; transform:translate(-50%, -4px) rotate(45deg)}
  header.top .hwrap>:is(.headbtn,.onb-help):is(:hover,:focus-visible)::after{opacity:1;
    transform:translate(-50%, 0) scale(1);
    transition:opacity .22s ease, transform .32s cubic-bezier(.16,1,.3,1); transition-delay:.18s}
  header.top .hwrap>:is(.headbtn,.onb-help):is(:hover,:focus-visible)::before{opacity:1;
    transform:translate(-50%, 0) rotate(45deg);
    transition:opacity .22s ease, transform .32s cubic-bezier(.16,1,.3,1); transition-delay:.18s}
  /* У «Задач» в aria-label ещё и число («Задачи: открытых 50») — для чтения с экрана;
     на плашке оно повторяло бы бейдж. */
  header.top .hwrap>.tasksbtn::after{content:"Задачи"}
}
@media (prefers-reduced-motion:reduce){
  header.top .hwrap>:is(.headbtn,.onb-help)::after,
  header.top .hwrap>:is(.headbtn,.onb-help)::before{transition:none}
}
