/* Кит ERP: оболочка и компоненты. Значения — только из tokens.css; стилей в разметке нет (scripts/erp_lint.py).
 * Стиль — как кабинет и главная сайта (Елена 02.11.2026: «как у нас на сайте», минимализм, только суть):
 * шрифт системный (tokens.css): 400 текст, 500 заголовки, капс с разрядкой 1 px в меню, на кнопках и подписях, ровные
 * отступы по сетке 8 px. Обводок нет нигде (брендбук ERP, правила 11–13): поле — текст на тонкой линии снизу, чип и вторая
 * кнопка — слово, окно и уведомление — тень, фокус — линия под словом.
 * Телефон — по умолчанию, комп — от 1024 px: меню слева вместо нижней панели, лист справа вместо снизу. */

*, *::before, *::after { box-sizing: border-box; }
/* без «резины» и без обновления браузера жестом: у приложения свой жест вниз (ui/pull.js) — иначе в Chrome
   обновление срабатывало бы дважды, а на iPhone шапка и нижняя панель дёргались */
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; overscroll-behavior-y: none; }
html.is-sheet-open { overflow: hidden; }
/* полосы прокрутки страницы нет (Елена 03.11.2026: «мне не нужны полосы прокрутки нигде»): Chrome на компе рисовал её
   справа, 15 px, и шапка с краем таблицы прыгали между длинным и коротким экраном. Листается колесом и пальцем, как было */
html, body { scrollbar-width: none; }
html::-webkit-scrollbar, body::-webkit-scrollbar { display: none; }
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font: 400 var(--t-body)/1.6 var(--font);
  -webkit-tap-highlight-color: transparent;
}
a { color: inherit; }
p { margin: 0; }
h1, h2, h3 { margin: 0; font-weight: 500; }
button { font: inherit; color: inherit; }
input, select, textarea { font-family: var(--font); font-size: 16px; }
[hidden] { display: none !important; }
::selection { background: var(--metal-glow); }
/* фокус с клавиатуры (Tab на компе) — линия металла под элементом, не рамка (брендбук ERP, правило 13); мышью и
   пальцем его не видно. Подчёркивание текста не годится: у кнопок и пунктов меню flex, до слова оно не доходит.
   Поле кита в фокусе и так с чёрной линией; лист и страница (tabindex -1) получают фокус от приложения, не от Tab */
:focus-visible { outline: none; }
:where(:focus-visible:not([tabindex="-1"], .field-input)) { box-shadow: 0 2px 0 var(--metal); }   /* вес 0 — слова ниже его меняют */
/* слово без коробки (кнопка-слово, вкладка, пункт меню, профиль) — черта под самим словом: линия под невидимой коробкой
   легла бы дугой по её скруглению, а у выбранной вкладки совпала бы с меткой «где я» */
.btn-secondary:focus-visible, .btn-quiet:focus-visible, .btn-danger:focus-visible, .tab:focus-visible,
.side-item:focus-visible, .more-item:focus-visible, .tabs-item:focus-visible, .bar-profile:focus-visible,
.chip input:focus-visible + span, .check input:focus-visible ~ .check-label {
  box-shadow: none;
  text-decoration: underline;
  text-decoration-color: var(--metal);
  text-decoration-thickness: 2px;
  text-underline-offset: 6px;
}
.ico { width: 24px; height: 24px; flex: none; }
.logo { display: block; width: 100%; height: auto; }

/* капс с разрядкой 1 px — как меню, кнопки и подписи сайта */
.tab-label, .side-item, .more-item, .tabs-item, .btn, .bar-profile,
.chips-label, .kit-mark, .kit-caption, .pair dt, .tbl th {
  text-transform: uppercase;
  letter-spacing: var(--caps);
}
/* навигация — плотнее основного текста: тонкий 300 светло-серым в меню еле виден и нечёткий (Елена 02.11);
   мелкий капс без antialiased — у букв чёткий край */
.tab, .side-item, .more-item, .tabs-item, .bar-profile {
  font-weight: 400;
  color: var(--nav-ink);
  -webkit-font-smoothing: auto;
  -moz-osx-font-smoothing: auto;
  text-rendering: optimizeLegibility;
}
.tab[aria-current], .side-item[aria-current], .more-item[aria-current], .tabs-item[aria-current] { color: var(--ink); }
/* «где я» в списках меню — ещё и плотнее (аудит акцентов 10.11.2026): пункт в столбце, соседей вес не сдвигает.
   Нижняя панель и вкладки — без веса: их ряд ровно по словам, плотное слово сдвигало бы соседей при каждом переходе */
.side-item[aria-current], .more-item[aria-current] { font-weight: 500; }

/* --- оболочка ------------------------------------------------------------- */

.shell-side { display: none; }
.shell-main { min-height: 100dvh; }

.bar {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: calc(var(--bar-h) + var(--safe-top));
  padding: var(--safe-top) max(var(--gutter), var(--safe-right)) 0 max(var(--gutter), var(--safe-left));
  background: var(--paper);
  border-bottom: 1px solid var(--line);
}
.bar-back { margin-left: -12px; }
.bar-back:not([hidden]) + .bar-logo { display: none; }
.bar-logo { display: flex; align-items: center; width: 84px; min-height: var(--tap); color: var(--ink); }
/* профиль — в правом верхнем углу (Елена 02.11.2026) */
.bar-profile {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  margin-left: auto;
  padding: 0;
  border: 0;
  background: none;
  font-size: var(--t-nav);
  cursor: pointer;
}

.page {
  padding: 0 max(var(--gutter), var(--safe-right)) calc(var(--nav-h) + var(--safe-bottom) + 32px) max(var(--gutter), var(--safe-left));
  outline: none;
}
.page-title { margin: 24px 0 16px; font-size: var(--t-h1); line-height: 1.2; }

/* нижняя панель: названия разделов капсом */
.shell-tabbar { position: fixed; left: 0; right: 0; bottom: 0; z-index: 30; }
.tabbar {
  display: flex;
  padding: 0 var(--safe-right) var(--safe-bottom) var(--safe-left);
  background: var(--paper);
  border-top: 1px solid var(--line);
}
/* пункты — поровну; название шире своей доли — пункт не уже названия, остальные уступают (раньше «Расписание» вылезало
   из ячейки и почти слипалось с соседом, UX 4.7 С3). Узкий телефон — доли по длине названий: зазоры между словами ровные
   (2.99). Пункт не уже цели нажатия — минимум у названия */
.tab {
  position: relative;
  flex: 1 1 0;
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: min-content;
  min-height: var(--nav-h);
  padding: 8px 2px;
  border: 0;
  background: none;
  text-decoration: none;
  cursor: pointer;
}
/* нижняя панель — обычными буквами и одной строкой (Елена 02.11.2026, «а»): пять пунктов с «Финансами» капсом
   не влезали ни в один телефон («ФИНАНС/Ы»); так — от 320 px (замер на KZ). Меню слева и вкладки — капсом */
.tab-label { min-width: calc(var(--tap) - 4px); font-size: var(--t-nav); line-height: 1.35; text-align: center; white-space: nowrap; text-transform: none; letter-spacing: 0; }
@media (max-width: 359px) {
  .tab { flex-basis: auto; }
}
.tab[aria-current]::before {
  content: '';
  position: absolute;
  top: -1px;
  left: 50%;
  width: 24px;
  height: 2px;
  background: var(--metal);
  transform: translateX(-50%);
}

/* меню слева */
.side {
  display: flex;
  flex-direction: column;
  height: 100dvh;
  padding: 20px 24px 20px 18px;
  overflow-y: auto;
  scrollbar-width: none;
  background: var(--paper);
  border-right: 1px solid var(--line);
}
/* раскрытые подпункты выше окна — меню листается колесом без полосы (Елена 03.11.2026: «убрать нах все эти полосы») */
.side::-webkit-scrollbar { display: none; }
.side-logo { display: flex; align-items: center; width: 104px; min-height: var(--tap); margin: 0 0 16px 18px; color: var(--ink); }
/* группы — одинаково в обоих меню: тонкая линия и равный воздух */
.side-group + .side-group { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--line-soft); }
/* мышь, не палец: 34 px — 17 разделов входят в окно ноутбука 1440×790 */
.side-item {
  position: relative;
  display: flex;
  align-items: center;
  min-height: 34px;
  padding-left: 18px;
  font-size: var(--t-nav);
  text-decoration: none;
}
.side-item[aria-current]::before {
  content: '';
  position: absolute;
  left: 0;
  top: 50%;
  width: 10px;
  height: 2px;
  background: var(--metal);
}

@media (min-width: 1024px) {
  .shell { display: grid; grid-template-columns: var(--side-w) minmax(0, 1fr); }
  .shell-side { display: block; position: sticky; top: 0; height: 100dvh; }
  .shell-tabbar { display: none; }
  .bar {
    min-height: calc(24px + var(--tap));
    padding-top: 24px;
    border-bottom: 0;
  }
  .bar-logo { display: none; }
  .page { max-width: calc(var(--content-max) + 2 * var(--gutter)); padding-bottom: 64px; }
  .page-title { margin: 8px 0 24px; }
}

/* обновление жестом вниз */
.pull {
  position: fixed;
  top: calc(var(--bar-h) + var(--safe-top));
  left: 50%;
  z-index: 15;
  height: 0;
  pointer-events: none;
}
.pull-spin {
  display: block;
  width: 24px;
  height: 24px;
  margin-left: -12px;
  border: 1px solid var(--line);
  border-top-color: var(--ink);
  border-radius: 50%;
  background: var(--paper);
  opacity: 0;
  translate: 0 calc(var(--pull, 0px) - 32px);   /* сдвиг отдельно от вращения (spin крутит transform) */
}
.pull.is-pulling .pull-spin { opacity: 1; }
.pull.is-armed .pull-spin { border-color: var(--ink); border-top-color: var(--metal); }
.pull.is-busy .pull-spin { opacity: 1; translate: 0 16px; animation: spin .8s linear infinite; }

/* --- кнопки: как .cab-pay-btn сайта ---------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: var(--control-h);
  min-width: var(--tap);
  padding: 0 24px;
  border: 1px solid transparent;
  border-radius: var(--radius-btn);
  font-size: var(--t-btn);
  font-weight: 500;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.btn-primary { background: var(--ink); color: var(--paper); }
/* без рамок (правило 13): вторая — чёрное слово (Елена 02.11.2026, «1 а»), тихая — серое, остановить и удалить — красное */
.btn-secondary { background: none; color: var(--ink); padding: 0; }
.btn-quiet { background: none; color: var(--ink-3); padding: 0; }
.btn-danger { background: none; color: var(--bad-ink); padding: 0; }
.btn:disabled, .btn[aria-disabled='true'] { opacity: .35; cursor: not-allowed; }
.btn.is-busy { opacity: .7; cursor: progress; }
.btn.is-busy::before {
  content: '';
  width: 14px;
  height: 14px;
  border: 1px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: spin .8s linear infinite;
}
.btn-block { display: flex; width: 100%; }
/* слово во всю ширину — от левого края, как заголовок листа над ним; нажимается вся строка */
.btn-block:is(.btn-secondary, .btn-quiet, .btn-danger) { justify-content: flex-start; }
/* кнопка-слово — коробка по слову, цель нажатия не уже 44 px — невидимым слоем по центру слова, как у названия колонки:
   слово уже 44 px («CSV», «НЕТ») стояло посреди коробки 44 px, и до соседнего слова выходило 33–41 px вместо 24 — с
   любой стороны (приёмки 11.11: «Печать · CSV», «Нет · Отменить»). :where — без веса: раздел, который сам ставит кнопке
   ширину или положение, берёт своё */
.btn:where(.btn-secondary, .btn-quiet, .btn-danger) { min-width: 0; }
:where(.btn:is(.btn-secondary, .btn-quiet, .btn-danger)) { position: relative; }
:where(.btn:is(.btn-secondary, .btn-quiet, .btn-danger))::after {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: max(100%, var(--tap));
  transform: translateX(-50%);
}
.btn-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--tap);
  height: var(--tap);
  flex: none;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: none;
  color: var(--ink);
  cursor: pointer;
}
.btn-icon:focus-visible:not([tabindex="-1"]) { box-shadow: none; background: var(--mist); }   /* значок без слова */
/* неактивный значок — бледнее, как .btn:disabled (её 290 v2: печать видна с открытия, неактивной, пока печатать нечего) */
.btn-icon:disabled { opacity: .35; cursor: default; }
/* значок на время запроса (setBusy в ui/form.js) — кружок вместо рисунка, как у .btn: обложка кружка в «Контенте»
   грузилась без знака работы (ревью выката e6, 13.11) */
.btn-icon.is-busy { opacity: .7; cursor: progress; }
.btn-icon.is-busy > .ico { display: none; }
.btn-icon.is-busy::before {
  content: '';
  width: 14px;
  height: 14px;
  border: 1px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: spin .8s linear infinite;
}

/* --- строка «название + значки» (правило 15: «+» у названия вместо залитой «Новая …», скрепка у названия вместо
   «Загрузить»): значки сразу за названием раздела (.page-head, ctx.acts в shell.js) или блока; значок по середине строки
   названия и не раздвигает её — кнопка 44 px заходит в поля строки ------------------------------------------------- */
.head-row { display: flex; flex-wrap: wrap; align-items: center; column-gap: 4px; margin: 0 0 8px; }
.head-row > :first-child { margin-top: 0; margin-bottom: 0; }   /* отступ под названием — у строки, значок по его середине */
.head-row > .btn-icon, .page-acts { margin-top: -10px; margin-bottom: -10px; }
/* значок у названия блока — 14 px, по росту букв названия (правило 15; её «кнопка больше названия раздела», 11.11):
   кикер 11 px капсом и название кружка 15 px; у названия раздела (.page-head) — 24 px, как везде. Цель нажатия — те же
   44 px; строку названия значок не раздвигает — кнопка заходит в поля строки на (44 − 14) / 2 */
.head-row:not(.page-head) > .btn-icon { margin-top: -15px; margin-bottom: -15px; }
.head-row:not(.page-head) > .btn-icon .ico { width: 14px; height: 14px; }
/* удалить — красным, как красное слово «Удалить» (брендбук, разд. 5 «Кнопки») */
.btn-icon.is-danger { color: var(--bad-ink); }
/* у названия раздела — строкой текста, не flex: значок встаёт сразу за последним словом, и у длинного названия тоже
   («Расчёты с партнёрами» на 390, длинное задание — не у правого края и не строкой ниже; UX 13.11, два круга). Шрифт
   строки — шрифт названия: vertical-align: middle ставит значок по середине его букв. Поля кнопки 44 px отрицательные:
   в строку значок входит шириной рисунка (рисунок — в 8 px за словом), цель нажатия — прежние 44 px */
.page-head { display: block; margin: 24px 0 16px; font-size: var(--t-h1); line-height: 1.2; }
.page-head[hidden] { display: none; }
.page-head > .page-title { display: inline; margin: 0; overflow-wrap: break-word; }
.page-head > .page-title[hidden] { display: none; }
.page-acts { display: inline-flex; align-items: center; vertical-align: middle; margin-left: -2px; margin-right: -10px; }
.page-acts:empty { display: none; }
@media (min-width: 1024px) {
  /* длинное название карточки (задание) — не шире карточки (UX 13.11) */
  .page-head { margin: 8px 0 24px; max-width: 720px; }
}

/* выбор вида у «+» (ui/menu.js): окно под значком, с тенью, без рамки (правило 13), строки — слова */
.pick-menu {
  position: fixed;
  z-index: 40;
  min-width: 200px;
  padding: 8px 0;
  border-radius: var(--radius-btn);
  background: var(--paper);
  box-shadow: var(--shadow-pop);
}
.pick-menu-item {
  display: block;
  width: 100%;
  min-height: var(--tap);
  padding: 0 16px;
  border: 0;
  background: none;
  font: inherit;
  font-size: var(--t-body);
  text-align: left;
  color: var(--ink);
  cursor: pointer;
}
.pick-menu-item:focus-visible { outline: none; box-shadow: inset 0 -2px 0 var(--metal); }

/* --- поля: текст на тонкой линии снизу, без рамки и подложки (Елена 02.11.2026: «перестать использовать эти обводки
   везде»); название внутри поля, под полем — только ошибка ----------------------------------------------------- */

.form { max-width: 440px; }
.field { position: relative; margin: 0 0 16px; }
.field-input {
  display: block;
  width: 100%;
  height: 52px;
  padding: 22px 0 6px;
  border: 0;
  border-bottom: 1px solid var(--line);
  border-radius: 0;
  background: transparent;
  color: var(--ink);
  font-size: var(--field-font);
  font-weight: 400;
  line-height: 1.25;
  -webkit-appearance: none;
  appearance: none;
  transition: border-color var(--dur) var(--ease);
}
.field-input::placeholder { color: transparent; }
.field-input:focus { outline: none; border-bottom-color: var(--ink); }
.field-input:-webkit-autofill { -webkit-box-shadow: 0 0 0 40px var(--paper) inset; }
.field-label {
  position: absolute;
  left: 0;
  top: 16px;
  font-size: var(--t-body);
  font-weight: 400;
  line-height: 1.2;
  color: var(--ink-3);
  pointer-events: none;
  transition: top var(--dur) var(--ease), font-size var(--dur) var(--ease);
}
/* поле не пустое или в фокусе — название уходит вверх мелким капсом, как подписи полей сайта */
.field-input:focus + .field-label,
.field-input:not(:placeholder-shown) + .field-label,
.field-input:-webkit-autofill + .field-label {
  top: 7px;
  font-size: var(--t-label);
  font-weight: 400;
  letter-spacing: var(--caps);
  text-transform: uppercase;
}
.field-area { height: auto; min-height: 104px; padding-top: 26px; resize: none; }
/* поиск — лупа вместо слова «Поиск» (Елена 11.11.2026, № 282), в конце строки справа, как значок календаря в поле
   даты (её 13.11: «почему лупа в начале строки»): рисунок 24 px на 10 px от края, по середине поля; текст — по середине
   поля от левого края. Набрали — на месте лупы «Стереть» раздела, лупа прячется. Системный крестик и лупа браузера не
   рисуются — свои из набора кита */
.field-search .field-input { padding: 14px 44px 14px 0; }
.field-search .field-input::-webkit-search-cancel-button, .field-search .field-input::-webkit-search-decoration { -webkit-appearance: none; appearance: none; }
.field-search-ico { position: absolute; right: 10px; top: 14px; color: var(--ink-3); pointer-events: none; }
.field-search .field-input:focus ~ .field-search-ico { color: var(--ink); }
.field-search .field-input:not(:placeholder-shown) ~ .field-search-ico { visibility: hidden; }
/* «Стереть» — крестик набора кита (ui/field.js) на месте лупы, цель 44 px у правого края, серый — тише набранного;
   пустое поле — крестика нет (ревью выката e6, 13.11: свой «Стереть» во всех полях поиска, системный спрятан) */
.field-clear { position: absolute; right: 0; top: 4px; display: flex; align-items: center; justify-content: center;
  width: var(--tap); height: var(--tap); padding: 0; border: 0; border-radius: var(--radius-btn); background: none;
  color: var(--ink-3); cursor: pointer; }
.field-search .field-input:placeholder-shown ~ .field-clear { display: none; }
.field-clear:focus-visible { outline: none; background: var(--mist); color: var(--ink); }
@media (hover: hover) {
  .field-clear:hover { color: var(--ink); }
}
.has-error .field-input { border-bottom-color: var(--bad); }
.field-error { margin-top: 6px; font-size: var(--t-btn); color: var(--bad-ink); }
/* кнопки-слова рядом — через 24 px: ближе два слова читаются одной фразой */
.form-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 16px 24px; margin-top: 24px; }
.form-actions > .btn-icon:first-child { margin-left: -10px; }   /* рисунок значка — по краю полей, не кнопки 44 px */

/* поле со списком (pickField в ui/field.js; правило 16 — выбор одним полем, чипов наружу нет): как текстовое поле —
   название внутри, выбранное — значением, линия снизу, справа ▾ (по середине цели 44 px у правого края, на одной
   вертикали со значками полей). Список — окошко поверх, как меню колонки и выбор у «+» (тень, без рамки, правило 13):
   под полем по его ширине, поля ниже не сдвигает (её 253, Ц3 v6: «нах всё из списка вывалено»); внизу экрана места
   нет — над полем (.is-up, ui/field.js). Длинный список листается внутри окошка, полосы нет. Строка — цель 44 px,
   выбранная — 500 и ✓, как в меню колонки */
.pick { position: relative; border: 0; padding: 0; min-width: 0; }
.pick-btn { display: flex; align-items: center; gap: 8px; padding-right: 10px; text-align: left; cursor: pointer; }
.pick-value { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pick-ico { color: var(--ink-3); transition: transform var(--dur) var(--ease); }
.pick.is-open .pick-ico { transform: rotate(180deg); }
.pick.is-open .pick-btn { border-bottom-color: var(--ink); }
.pick-label { padding: 0; }
/* пустое поле: ▾ на линии названия внутри поля, как значки соседних полей (UX кита 13.11: было на 8 px ниже) */
.pick:not(.has-value) .pick-btn { padding-top: 14px; padding-bottom: 14px; }
.pick.has-value .pick-label, .pick.is-open .pick-label {
  top: 7px;
  font-size: var(--t-label);
  letter-spacing: var(--caps);
  text-transform: uppercase;
}
.pick-list {
  position: absolute;
  top: 56px;
  left: 0;
  right: 0;
  z-index: 45;
  max-height: min(320px, 50dvh);
  overflow-y: auto;
  scrollbar-width: none;
  padding: 8px 0;
  border-radius: var(--radius-btn);
  background: var(--paper);
  box-shadow: var(--shadow-pop);
}
.pick-list::-webkit-scrollbar { display: none; }
.pick.is-up .pick-list { top: auto; bottom: calc(100% + 4px); }
/* в листе окошко долистывается до низа — не на нижнее поле листа и не на полоску «домой» iPhone (ui/field.js place) */
.sheet .pick-list { scroll-margin-bottom: calc(24px + var(--safe-bottom)); }
.pick-opt { position: relative; display: flex; align-items: center; min-height: var(--tap); padding: 10px 16px; cursor: pointer; }
@media (hover: hover) {
  .pick-opt:hover { background: var(--mist); }
}
.pick-opt input { position: absolute; width: 1px; height: 1px; opacity: 0; margin: 0; pointer-events: none; }
.pick-opt span { font-size: var(--t-body); line-height: 1.3; color: var(--ink-2); }
.pick-opt input:checked + span { color: var(--ink); font-weight: 500; }
.pick-opt input:checked + span::after { content: ' ✓'; }
.pick-opt input:focus-visible + span { box-shadow: 0 2px 0 var(--metal); }
[inert] .pick-btn, .pick-btn:disabled { cursor: default; }
[inert] .pick-ico { visibility: hidden; }

/* чипы: выбор одного или нескольких. Слово без рамки и подложки, выбранный — чёрная таблетка вокруг слова (правило 12).
   Ряд сдвинут на поле таблетки: первое слово стоит по краю текста, как подпись над ним */
.chips { border: 0; padding: 0; margin: 0 0 16px; min-width: 0; }
.chips-label { padding: 0; margin-bottom: 8px; font-size: var(--t-label); font-weight: 400; color: var(--ink-3); }
/* между словами 8 px, как у соседних групп кита (.kit-row, кнопки-иконки): при 4 px две выбранные таблетки рядом читались
   одной (UX окна 31, 10.11.2026, очередь № 85) */
.chips-row { display: flex; flex-wrap: wrap; gap: 0 8px; margin-left: -12px; }
.chip { position: relative; display: inline-flex; }
.chip input, .check input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  margin: 0;
  pointer-events: none;
}
.chip span {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--tap);
  min-height: var(--tap);
  padding: 0 12px;
  border-radius: 999px;
  color: var(--nav-ink);
  font-size: var(--t-nav);
  cursor: pointer;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.chip input:checked + span { background: var(--ink); color: var(--paper); }
/* выбор нельзя менять (сохранённая рассылка — канал) — невыбранные тише */
[inert] .chip input:not(:checked) + span, .chip input:disabled + span { color: var(--ink-3); cursor: default; }

/* флажок и переключатель */
.check {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: var(--tap);
  margin: 0 0 4px;
  cursor: pointer;
}
.check-mark {
  position: relative;
  width: 20px;
  height: 20px;
  flex: none;
  border-radius: 4px;
  background: var(--control-off);   /* без рамки (правило 13): пустой — серый квадрат, отмеченный — чёрный */
  transition: background var(--dur) var(--ease);
}
.check input:checked + .check-mark { background: var(--ink); }
.check input:checked + .check-mark::after {
  content: '';
  position: absolute;
  left: 7px;
  top: 3px;
  width: 5px;
  height: 10px;
  border: solid var(--paper);
  border-width: 0 1.5px 1.5px 0;
  transform: rotate(45deg);
}
/* часть выбрана («Все» в фильтре колонки) — черта вместо галочки */
.check input:indeterminate + .check-mark { background: var(--ink); }
.check input:indeterminate + .check-mark::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 10px;
  height: 1.5px;
  background: var(--paper);
  transform: translate(-50%, -50%);
}
.check-toggle .check-mark { width: 40px; height: 22px; border-radius: 999px; }
.check-toggle .check-mark::after,
.check-toggle input:checked + .check-mark::after {
  content: '';
  position: absolute;
  left: 3px;
  top: 3px;
  width: 16px;
  height: 16px;
  border: 0;
  border-radius: 50%;
  background: var(--paper);
  transform: none;
  transition: transform var(--dur) var(--ease), background var(--dur) var(--ease);
}
.check-toggle input:checked + .check-mark::after { transform: translateX(18px); }

/* вкладки внутри раздела */
.tabs { margin: 0 calc(-1 * var(--gutter)) 16px; border-bottom: 1px solid var(--line); }
.tabs-row {
  display: flex;
  gap: 20px;
  padding: 0 var(--gutter);
  overflow-x: auto;
  scrollbar-width: none;
}
.tabs-row::-webkit-scrollbar { display: none; }
/* край, за которым есть ещё вкладки, растворяется (ui/nav.js): у края экрана не обрывок слова, а «дальше есть» */
.tabs-row.is-cut-end {
  -webkit-mask-image: linear-gradient(to left, transparent, #000 32px);
  mask-image: linear-gradient(to left, transparent, #000 32px);
}
.tabs-row.is-cut-start {
  -webkit-mask-image: linear-gradient(to right, transparent, #000 32px);
  mask-image: linear-gradient(to right, transparent, #000 32px);
}
.tabs-row.is-cut-start.is-cut-end {
  -webkit-mask-image: linear-gradient(to right, transparent, #000 32px, #000 calc(100% - 32px), transparent);
  mask-image: linear-gradient(to right, transparent, #000 32px, #000 calc(100% - 32px), transparent);
}
.tabs-item {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--tap);
  min-height: var(--tap);
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  font-size: var(--t-nav);
  text-decoration: none;
  white-space: nowrap;
}
.tabs-item[aria-current] { border-bottom-color: var(--metal); }
@media (min-width: 1024px) {
  .tabs { margin-left: 0; margin-right: 0; }
  .tabs-row { padding: 0; }
}

/* --- список: строки на телефоне, таблица на компе ------------------------------ */

.rows { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--line-soft); }
.rows li { border-bottom: 1px solid var(--line-soft); }
.row {
  display: flex;
  align-items: center;
  gap: 16px;
  min-height: 64px;
  padding: 12px 0;
  text-decoration: none;
}
.row-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.row-title, .row-sub { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.row-title { font-weight: 400; }
.row-sub { font-size: var(--t-btn); color: var(--ink-3); }
.row-end { flex: none; font-weight: 400; font-variant-numeric: tabular-nums; text-align: right; white-space: nowrap; }

.tbl { width: 100%; border-collapse: collapse; }
.tbl :where(th) { padding: 0 16px 10px 0; }
.tbl th {
  border-bottom: 1px solid var(--th-rule);
  font-size: var(--t-label);
  font-weight: 400;
  color: var(--th-ink);
  text-align: left;
  white-space: nowrap;
}
.tbl :where(td) { padding: 14px 16px 14px 0; }
.tbl td { border-bottom: 1px solid var(--line-soft); vertical-align: top; }
/* у последней колонки поля справа нет: суммы стоят по краю содержимого. :where — таблицы-сетки разделов
   (.o-tbl и др.) задают свои поля ячеек и их не теряют */
.tbl :where(th:last-child, td:last-child) { padding-right: 0; }
.tbl tbody tr { position: relative; }
.tbl-link { font-weight: 400; text-decoration: none; }
.tbl-link::after { content: ''; position: absolute; inset: 0; }
.tbl .num { text-align: right; font-variant-numeric: tabular-nums; }

/* --- таблица реестра (ui/table.js, 2.87): сетка как в Excel, без рамки вокруг (брендбук ERP, правило 14) ---------------
   Полос прокрутки нет (Елена 03.11.2026: «зачем полоса прокрутки? убрать нах все эти полосы»): своей вертикальной
   прокрутки у таблицы нет — листается страница; шире экрана — вбок пальцем, полоса скрыта, справа тень, пока за краем
   есть колонки, первая колонка прибита; влезает — строка названий прибита под шапкой приложения (is-fit) */
.rt-wrap { position: relative; }
.rt-box {
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
}
.rt-box::-webkit-scrollbar { display: none; }
.rt-wrap::after {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: 4;
  width: 24px;
  background: linear-gradient(to left, rgba(26, 26, 26, .10), rgba(26, 26, 26, 0));
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur) var(--ease);
}
.rt-wrap.is-more::after { opacity: 1; }
/* влезает по ширине — у блока нет своей прокрутки: палец и колесо над таблицей листают страницу (UX 2.41) */
.rt-wrap.is-fit > .rt-box { overflow: visible; }
.rt-wrap.is-fit .rt thead th { top: calc(var(--bar-h) + var(--safe-top)); }
/* шире блока — прилипание CSS внутри прокрутки вбок не работает: строку названий сдвигает вслед за страницей ui/table.js
   (--rt-head-y), она держится под шапкой приложения и на телефоне (UX ce 03.11.2026, М4) */
.rt-wrap:not(.is-fit) .rt > thead th { transform: translateY(var(--rt-head-y, 0px)); }
@media (min-width: 1024px) {
  .rt-wrap.is-fit .rt thead th { top: calc(24px + var(--tap)); }
}
/* таблица в листе («Мои документы»): строка названий прибита под шапкой листа, а не под шапкой приложения — лист сам
   листается, отступ считается от его края за вычетом поля листа (8 px телефон, 24 px комп; шапка листа — 56 px).
   С отступом шапки приложения на компе строка названий стояла на 12 px поверх первой строки, а при прокрутке под шапкой
   листа оставалась щель 36 px (UX окна 47, 10.11.2026). Действует на все листы: шапка 56 px есть у каждого (ui/sheet.js);
   без шапки — только окно профиля на компе (.sheet-pop), таблиц в нём нет (проверка хвостов ревью 10.11, № 84).
   Высота шапки — --sheet-head-h (ui/sheet.js меряет её ResizeObserver'ом): заголовок в 3–4 строки выше 56 px прятал
   строку названий под шапкой (№ 94); до первого замера — 56 px */
.sheet .rt-wrap.is-fit .rt thead th { top: calc(var(--sheet-head-h, 56px) - 8px); }
@media (min-width: 1024px) {
  .sheet .rt-wrap.is-fit .rt thead th { top: calc(var(--sheet-head-h, 56px) - 24px); }
}
.rt {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--t-nav);
}
.rt th, .rt td {
  padding: 8px 12px;
  border-bottom: 1px solid var(--line);
  background: var(--paper);
  white-space: nowrap;
  vertical-align: middle;
  text-align: left;
}
/* строка названий — без серой плашки, чёрным капсом над чёрной линией (аудит акцентов 10.11.2026: серая шапка и серая
   сетка вместе давали «всё серо»); сетка «как в Excel» под ней — прежняя */
.rt thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  padding-top: 0;
  padding-bottom: 0;
  border-bottom-color: var(--th-rule);
  background: var(--th-bg);
  color: var(--th-ink);
  font-size: var(--t-btn);
  font-weight: 400;
  letter-spacing: var(--caps);
  text-transform: uppercase;
}
/* без меню (вкладка в карточке) — высоту строки названий дают поля, а не кнопка */
.rt-plain thead th { padding-top: 8px; padding-bottom: 8px; }
.rt th + th, .rt td + td { border-left: 1px solid var(--line); }
.rt .num { text-align: right; font-variant-numeric: tabular-nums; }
.rt .rt-tight { width: 1%; }
/* комп: таблица — по ширине содержимого (2.98, Елена 06.11, №174: «зачем на десктоп растягивать таблицы до конца, если
   данных нет»): узкая не тянется до края; широкая — по-прежнему в ширину блока (fit — с переносом текста) или вбок.
   Колонка в 1 % в такой таблице растянула бы её обратно до края — на компе колонке «по содержимому» хватает auto.
   Ширины колонок задал раздел (colClass → <colgroup>, «Сертификаты»: table-layout: fixed, «вся таблица в окне» — 2.27) —
   таблица, как была, в ширину блока: фиксированной раскладке нужна ширина */
@media (min-width: 1024px) {
  .rt { width: auto; }
  .rt .rt-tight { width: auto; }
  .rt:has(> colgroup) { width: 100%; }
}
.rt-pin { position: sticky; left: 0; z-index: 1; box-shadow: 1px 0 0 var(--line); }
.rt thead .rt-pin { z-index: 3; }
/* вторая прибитая (№ и имя клиента) — сразу за первой: отступ — ширина первой, считает ui/table.js (edges) */
.rt-pin2 { left: var(--rt-c2, 0px); }
.rt tbody tr.is-link { cursor: pointer; }
/* не действует (купон аннулирован), запланировано — серым */
.rt tbody tr.is-quiet td { color: var(--ink-3); }
/* длинное — одной строкой с многоточием, целиком — в карточке и во всплывающей подсказке */
.rt-cut { display: block; max-width: 200px; overflow: hidden; text-overflow: ellipsis; }
/* ссылка или кнопка на всю ячейку: цель нажатия не меньше строки, Tab с клавиатуры */
.rt-a {
  display: block;
  margin: -8px -12px;
  padding: 8px 12px;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  text-underline-offset: 3px;
  text-decoration-color: var(--link-line);   /* ссылка в ячейке — чертой металла, как ссылки сайта */
  cursor: pointer;
}
button.rt-a { width: calc(100% + 24px); }
/* ключ строки (код, название) — плотнее, без черты */
.rt-key { font-weight: 500; text-decoration: none; }
/* плотная — поля ячеек 8 px: реестр из многих колонок («Клиенты», «Сертификаты») */
.rt-dense :is(th, td) { padding-left: 8px; padding-right: 8px; }
.rt-dense .rt-a { margin: -8px; padding: 8px; }
.rt-dense button.rt-a { width: calc(100% + 16px); }
/* комп: в ширину окна — поля ячеек уже, текст переносится только по пробелам, не по слогам («Дей-ствует», «СТА-ТУС» —
   решение UX 2.86 для карточки клиента, 2.87 — для всех); не влезло — таблица листается вбок, строка названий прибита */
@media (min-width: 1024px) {
  .rt-fit th, .rt-fit td { padding-left: 8px; padding-right: 8px; white-space: normal; hyphens: manual; }
  .rt-fit thead th { font-size: var(--t-label); }
  .rt-fit .rt-head { white-space: normal; text-align: left; hyphens: manual; }
  .rt-fit .rt-a { margin: -8px; padding: 8px; }
  .rt-fit button.rt-a { width: calc(100% + 16px); }
}
/* телефон: шапка — мелким капсом подписей, колонки цифр и дат — без лишних полей (Елена 02.11.2026: «зачем столько
   места на просмотры»); строка, которая открывает объект, — цель нажатия пальцем, не ниже 44 px (с полями 8 px была 38) */
@media (max-width: 1023px) {
  .rt thead th { font-size: var(--t-label); }
  .rt :is(th, td).rt-tight { padding-left: 8px; padding-right: 8px; }
  .rt tbody tr.is-link > td { height: var(--tap); }
  /* ссылка или кнопка на всю ячейку — не ниже 44 px и на строке без is-link (пустая ячейка «План» БДР была 64×37, 2.99):
     поля 12 px вместо 8 — строка 44 px, текст по середине, как в соседних ячейках */
  .rt .rt-a, .rt-dense .rt-a { padding-top: 12px; padding-bottom: 12px; }
}
/* строка, открывающая объект, без своей ссылки — в порядке Tab на компе (ui/table.js, 2.99 М6): фокус — линия металла
   под строкой, как у остальных элементов (правило 13) */
.rt tbody tr[tabindex]:focus-visible { box-shadow: none; }
.rt tbody tr[tabindex]:focus-visible > td { box-shadow: inset 0 -2px 0 var(--metal); }

/* название колонки — кнопка меню: сортировка и фильтр; с фильтром или сортировкой — чёрное с чертой */
.rt-head {
  position: relative;
  display: inline-flex;
  gap: 4px;
  align-items: center;
  min-height: 44px;
  padding: 0 12px 0 0;
  border: 0;
  background: none;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  color: inherit;
  white-space: nowrap;
  cursor: pointer;
}
/* цель нажатия не уже 44 px — невидимым слоем по центру названия, а не шириной коробки: коробка по слову, и ▾ у
   короткого названия стоит так же близко, как у длинного («ИНН ▾» отъезжал на 8 px против 3 у «Сайт ▾» —
   min-width 44 px растягивал коробку, а ▾ прибит к её правому краю; приёмка «Поставщиков» 11.11) */
.rt-head::after { content: ''; position: absolute; top: 0; bottom: 0; left: 50%; width: max(100%, var(--tap)); transform: translateX(-50%); }
/* черта — металлом: фильтр или сортировка на колонке — состояние «включено», как метка «где я» */
.rt-head.is-on { color: var(--ink); font-weight: 500; text-decoration: underline; text-decoration-color: var(--metal); text-underline-offset: 4px; }
.rt-head-t { display: inline; }
/* у цифр название — по правому краю, как сами цифры */
.rt th.num .rt-head { justify-content: flex-end; width: 100%; }
/* стрелка сортировки — сразу за последним словом названия, на месте ▾, и ширины колонке не прибавляет (нулевая ширина,
   стрелка выходит вправо — в поле под ▾): колонки при сортировке не прыгают (UX 2.76, М4), и название в две-три строки
   её не отрывает. Черта под названием и стрелкой — одна: пробел перед стрелкой — текст под чертой, а не отступ, который
   черта пропускала (М5); черту стрелка рисует сама, той же толщины и на той же высоте */
.rt-arrow { display: inline-block; width: 0; white-space: nowrap; }
.rt-arrow::before { content: '\00a0'; }
.rt-head.is-on .rt-arrow { text-decoration: underline; text-decoration-color: var(--metal); text-underline-offset: 4px; }
.rt-arrow:empty { display: none; }
.rt-head:has(.rt-arrow:not(:empty)) .rt-caret { visibility: hidden; }
/* ▾ — у правого края названия: название переносится и по пробелам, и само по себе, значок всегда виден */
.rt-caret { position: absolute; top: 50%; right: 0; font-size: 10px; line-height: 1; transform: translateY(-50%); }

/* меню колонки: окно с тенью, без рамки (правило 13); поиск по значениям — над ними и на месте (UX 2.87). На компе
   значения — все, без своей прокрутки: длинный список листается страницей (Елена 03.11.2026: полос прокрутки нигде;
   в 240 px последнее значение «—» срезалось наполовину, и что список листается, видно не было) */
.rt-menu {
  position: absolute;
  z-index: 20;
  width: max-content;
  min-width: 240px;
  max-width: 320px;
  padding: 8px 0;
  border: 0;
  border-radius: var(--radius-btn);
  background: var(--paper);
  box-shadow: 0 8px 24px rgba(26, 26, 26, .08);
}
.rt-menu-item {
  display: block;
  width: 100%;
  min-height: 32px;
  padding: 6px 16px;
  border: 0;
  background: none;
  font: inherit;
  font-size: var(--t-nav);
  text-align: left;
  color: var(--ink);
  cursor: pointer;
}
.rt-menu-item.is-on { font-weight: 500; }
.rt-menu-item.is-on::after { content: ' ✓'; }
.rt-menu-search { padding: 4px 16px; }
.rt-vsearch {
  width: 100%;
  height: 40px;
  padding: 0;
  border: 0;
  border-bottom: 1px solid var(--line);
  border-radius: 0;
  background: none;
  font: 400 var(--field-font) var(--font);
  color: var(--ink);
}
.rt-vsearch:focus { outline: none; border-bottom-color: var(--ink); }
.rt-vsearch::-webkit-search-cancel-button { display: none; -webkit-appearance: none; appearance: none; }
.rt-menu-values {
  margin: 4px 0;
  padding: 4px 16px;
  border-top: 1px solid var(--line-soft);
  border-bottom: 1px solid var(--line-soft);
}
.rt-menu-values::-webkit-scrollbar, .rt-menu::-webkit-scrollbar { display: none; }
.rt-check { min-height: 32px; font-size: var(--t-nav); }
/* «Ничего не нашлось» — по краю таблицы, без высоты экрана-состояния */
.rt-nothing { margin-top: 8px; }
.rt-nothing .st { padding: 8px 0 0; text-align: left; }
.rt-nothing .st-title { font-size: var(--t-body); font-weight: 400; color: var(--ink-2); }
@media (max-width: 1023px) {
  .rt-check, .rt-menu-item { min-height: 44px; }
  .rt-vsearch { height: 44px; }
  /* меню — над нижней панелью во всю ширину: под колонкой у края экрана оно уходило под панель (UX 2.17). Значения
     занимают всю высоту над ней, листаются только они: сортировка сверху и «Сбросить» снизу на месте (UX 2.87: в 176 px
     «На складе», снятый по умолчанию, прятался) */
  .rt-menu-values { flex: 0 1 auto; min-height: 0; overflow-y: auto; scrollbar-width: none; }
  .rt-menu {
    display: flex;
    flex-direction: column;
    position: fixed;
    left: 20px;
    right: 20px;
    bottom: calc(var(--nav-h) + var(--safe-bottom) + 8px);
    width: auto;
    max-width: none;
    /* не выше 60 % экрана: над меню остаётся место нажать мимо и закрыть его (UX 2.87: у колонки на 25 значений меню
       вставало от шапки до панели, и касание «мимо» попадало в «По возрастанию») */
    max-height: min(60dvh, calc(100dvh - var(--nav-h) - var(--safe-bottom) - 80px));
    overflow-y: auto;
    scrollbar-width: none;
    box-shadow: 0 -8px 24px rgba(26, 26, 26, .12);
  }
  /* menuInline (карточка клиента): от края до края экрана над названием колонки, не над нижней панелью поверх таблицы;
     значения — до половины экрана (UX 2.86) */
  .rt-menu.rt-menu-inline {
    display: block;
    position: absolute;
    left: calc(-1 * var(--gutter));
    right: calc(-1 * var(--gutter));
    bottom: auto;
    max-height: none;
    box-shadow: 0 8px 24px rgba(26, 26, 26, .12);
  }
  .rt-menu-inline .rt-menu-values { max-height: 45dvh; overflow-y: auto; }
}

/* итоги над таблицей: сеткой с переносом, вбок не листаются; подписи — как .pair dt */
.rt-sum { display: flex; flex-wrap: wrap; gap: 16px 24px; margin: 0 0 12px; }
/* подпись над цифрой — кикер (чёрным 500), как над главной цифрой «Сводки» (аудит акцентов 10.11.2026) */
.rt-sum dt {
  margin-bottom: 4px;
  font-size: var(--t-label);
  font-weight: 500;
  letter-spacing: var(--caps);
  text-transform: uppercase;
  color: var(--kicker);
}
.rt-sum dd {
  margin: 0;
  font-size: var(--t-h1);
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
@media (min-width: 1024px) {
  .rt-sum { column-gap: 40px; }
}

/* --- акценты (аудит дизайна 10.11.2026: «всё серо слишком» — «расставь акценты по брендбуку») ---------------------
   Название блока экрана и карточки («Состав», «Даты», «Итог») — кикер: 11 px капсом, 500, чёрным (--kicker); одно на всё
   ERP (раньше — серым в одних разделах и чёрным в других). Металлом не делать: в 11 px на компе он рисуется серым (UX 10.11).
   Своего класса у кикера нет (.kicker никто не ставил — убран, хвосты ревью 10.11 № 84): разделы берут цвет --kicker */
/* Статус и этап — словом и цветом, без таблетки (таблетка — это выбранный чип фильтра, правило 12): ждёт нашего действия —
   чёрным плотнее, плохо (не оплачен, просрочен, ошибка) — красным, сделано и действует — зелёным, закрыто — серым.
   «Ждёт действия» не металлом: в 12 px на компе он серый и стал бы самым тихим словом строки (UX 10.11).
   Колонка таблицы — tone(r) (ui/table.js), в своей разметке — класс у слова */
.tone-act, .tone-bad, .tone-ok { font-weight: 500; }
.tone-act { color: var(--ink); }
.tone-bad { color: var(--bad-ink); }
.tone-ok { color: var(--ok-ink); }
.tone-off { color: var(--ink-3); }

/* --- раздел экрана (правило 18; комплексный дизайн 13.11.2026) ---------------------------------------------------
   Название раздела внутри экрана («Воронка», «Состав», «Статьи», «Документы») — одно на всё ERP и стол: 24 px обычными
   буквами, цвет --sec-ink, над ним линия того же цвета во всю ширину блока и воздух --sec-gap. Так раздел отделён от
   соседнего и не сливается с подписями и показателями (11 px капсом). Показатели («Выручка», «Пришло», итоги над
   таблицей) — не разделы: остаются подписями над цифрой. Со значками («+», скрепка) — в строке .head-row: линия и
   воздух у строки, значок 24 px — по росту названия (правило 15: ничто в блоке не крупнее его названия). В листе —
   18 px (заголовок листа тоже 18) тёмной гранью металла: светлый металл мельче 24 px не читается */
.sec-h, .head-row:has(> .sec-h) {
  margin: var(--sec-gap) 0 16px;
  padding-top: 20px;
  border-top: 1px solid var(--sec-ink);
}
.sec-h {
  font-size: var(--t-sec);
  line-height: 1.25;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  color: var(--sec-ink);
  overflow-wrap: break-word;
}
.head-row > .sec-h { margin: 0; padding: 0; border: 0; }
/* список пар сразу под названием — без своей верхней линии: линия раздела уже над названием, вторая делала полосу */
.sec-h + .pairs, .head-row:has(> .sec-h) + .pairs { border-top: 0; }
.head-row:has(> .sec-h) > .btn-icon { margin-top: -10px; margin-bottom: -10px; }
.head-row:has(> .sec-h) > .btn-icon .ico { width: 24px; height: 24px; }
.sheet .sec-h, .sheet .head-row:has(> .sec-h) { margin-top: 32px; padding-top: 16px; border-top-color: var(--sec-ink-sm); }
.sheet .sec-h { font-size: var(--t-title); color: var(--sec-ink-sm); }
.sheet .head-row > .sec-h { margin: 0; padding: 0; }

/* --- карточка объекта ------------------------------------------------------ */

.card { max-width: 720px; }
.card-head { margin: 0 0 16px; }
.card-title { font-size: var(--t-title); line-height: 1.3; }
.card-sub { margin-top: 2px; font-size: var(--t-btn); color: var(--ink-3); }
.pairs { margin: 0; border-top: 1px solid var(--line-soft); }
.pair {
  display: grid;
  grid-template-columns: minmax(104px, 34%) minmax(0, 1fr);
  gap: 16px;
  align-items: baseline;
  padding: 12px 0;
  border-bottom: 1px solid var(--line-soft);
}
.pair dt { font-size: var(--t-label); font-weight: 400; color: var(--ink-3); }
.pair dd { margin: 0; font-weight: 400; overflow-wrap: anywhere; }
.pair dd a { text-underline-offset: 3px; text-decoration-color: var(--link-line); }   /* телефон, почта, заказ — чертой металла */
.card-actions {
  position: sticky;
  bottom: calc(var(--nav-h) + var(--safe-bottom));
  display: flex;
  gap: 8px;
  margin-top: 24px;
  padding: 12px 0;
  background: var(--paper);
}
.card-actions .btn { flex: 1; }
.card-actions > .btn-icon:first-child { margin-left: -10px; }   /* рисунок значка — по краю текста карточки, не кнопки 44 px */
/* комп: кнопки по ширине слова — рядом через 24 px, иначе слова читаются одной фразой (брендбук ERP, разд. 5 «Кнопки») */
@media (min-width: 1024px) {
  .card-actions { bottom: 0; gap: 24px; }
  .card-actions .btn { flex: none; }
}

/* --- нижний лист ---------------------------------------------------------- */

.sheet-layer { position: fixed; inset: 0; z-index: 50; }
.sheet-scrim {
  position: absolute;
  inset: 0;
  background: var(--scrim);
  opacity: 0;
  transition: opacity var(--dur) var(--ease);
}
.sheet {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  max-height: calc(100dvh - var(--safe-top) - var(--bar-h));   /* край длинного листа — по линии шапки, не на логотипе */
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: none;          /* полос нет нигде: что лист листается, говорит растворённый низ (UX 2.76, М11) */
  padding: 8px max(var(--gutter), var(--safe-right)) calc(24px + var(--safe-bottom)) max(var(--gutter), var(--safe-left));
  border-radius: var(--radius-sheet) var(--radius-sheet) 0 0;
  background: var(--paper);
  box-shadow: var(--shadow-sheet);
  transform: translateY(100%);
  transition: transform 260ms var(--ease);
  outline: none;
}
.sheet::-webkit-scrollbar { display: none; }
.sheet-layer.is-open .sheet-scrim { opacity: 1; }
.sheet-layer.is-open .sheet { transform: none; }
/* z-index выше строки названий таблицы (2, прибитая колонка 3) и тени «есть ещё» (4), ниже меню колонки (20): заголовок
   листа в две строки выше 56 px — строка названий уходит под шапку, а не рисуется поверх заголовка (хвосты ревью 10.11) */
.sheet-head {
  position: sticky;
  top: -8px;
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  min-height: 56px;
  margin: -8px 0 8px;
  padding-top: 8px;
  background: var(--paper);
}
/* длинный лист (ui/sheet.js): список ушёл под шапку — линия под ней; есть что листать — низ растворяется.
   Растворение — слой, прибитый к низу видимой части (как шапка к верху: отступ минус поле листа), не маска:
   маска срезала бы тень листа и на iPhone перерисовывала бы прокрутку целиком */
.sheet.is-scrolled .sheet-head { box-shadow: 0 1px 0 var(--line); }
.sheet::after {
  content: '';
  position: sticky;
  bottom: calc(-24px - var(--safe-bottom));
  display: block;
  height: 40px;
  margin: -40px calc(-1 * max(var(--gutter), var(--safe-right))) 0 calc(-1 * max(var(--gutter), var(--safe-left)));
  background: linear-gradient(to bottom, rgba(255, 255, 255, 0), var(--paper));
  pointer-events: none;
  opacity: 0;
}
.sheet.has-more-below::after { opacity: 1; }
.sheet-title { font-size: var(--t-title); }
.sheet-head .btn-icon { margin-right: -12px; }
@media (min-width: 1024px) {
  .sheet {
    left: auto;
    top: 0;
    width: 420px;
    max-height: none;
    padding: 24px 40px;
    border-radius: 0;
    box-shadow: -8px 0 32px rgba(0, 0, 0, .06);
    transform: translateX(100%);
  }
  /* поле листа сверху здесь 24 px — шапка прибита к самому краю, иначе над ней просвечивал бы список */
  .sheet-head { top: -24px; }
}

/* лист «Ещё»: понятный список — раздел на строку во всю ширину, все строки через одну тонкую линию (группы — только
   порядком); не влезает — лист листается (Елена 02.11.2026: «понятный список с листалкой», две колонки читались как каша) */
.more-group + .more-group { border-top: 1px solid var(--line-soft); }
.more-item {
  position: relative;
  display: flex;
  align-items: center;
  min-height: 52px;
  font-size: var(--t-nav);
  line-height: 1.3;
  text-decoration: none;
}
.more-item + .more-item { border-top: 1px solid var(--line-soft); }
.more-item[aria-current] { padding-left: 18px; }
.more-item[aria-current]::before {
  content: '';
  position: absolute;
  left: 0;
  top: 50%;
  width: 10px;
  height: 2px;
  background: var(--metal);
}

/* подпункты раздела (sub в registry.js, ui/nav.js) — пунктами под открытым разделом, а не вкладками над экраном
   (Елена 02.11.2026, «Контент»: «это внутри контента вкладки в левом меню»); раздел с открытыми подпунктами — чёрный,
   метка «где я» — у подпункта, в 8 px от слова, как у раздела.
   Подпункт — кегль кнопок (12 px), отступ 10 px от слова раздела, и блок подпунктов берёт правое поле меню: так самый
   длинный («Расчёты с партнёрами», 164–181 px капсом при 12 px: Segoe UI — Arial — Verdana; места 185 px) встаёт одной
   строкой при меню 240 px — контент экрана не сужается (аудит дизайна 09.11 № 24, её «24 ок»; ширину меню не трогать —
   диспетчер 37: на 1024 она сужала контент и таблицы уходили вбок). От конца слова до линии меню — 29 px (Segoe UI),
   19 px (Arial), не меньше 12 px (Verdana); прокрутки вбок у меню нет (UX 10.11, три круга) */
.side-item[data-open], .more-item[data-open] { color: var(--ink); }
.side-sub { margin-right: -16px; }
.side-subitem { padding-left: 28px; font-size: var(--t-btn); }
.side-subitem[aria-current]::before { left: 10px; }
.more-sub .more-item { padding-left: 16px; border-top: 1px solid var(--line-soft); }
.more-sub .more-item[aria-current] { padding-left: 34px; }
.more-sub .more-item[aria-current]::before { left: 16px; }
.more-sub + .more-item { border-top: 1px solid var(--line-soft); }

/* профиль: заголовок — роль; имя и данные — с учётками 3.1; выход — только здесь.
   На компе — маленькое окно у правого верхнего угла, не панель во всю высоту */
.profile .btn { margin-top: 8px; }
/* уведомления в профиле (3.7): события — переключатели строками через тонкую линию, как пары профиля */
.profile-push { margin: 16px 0 8px; }
.profile-push .check { margin: 0; }
.profile-push .check + .check { border-top: 1px solid var(--line-soft); }
/* цифра у раздела (3.7): мои открытые задания — число без кружка и заливки (правила 11–13); в нижней панели — над
   строкой, ширину пункта не меняет */
.nav-count { margin-left: 6px; font-weight: 500; color: var(--ink); font-variant-numeric: tabular-nums; }
.tab-label .nav-count { position: absolute; margin-left: 2px; font-size: var(--t-label); line-height: 1; transform: translateY(-4px); }
@media (min-width: 1024px) {
  .sheet-pop .sheet-scrim { background: transparent; }
  .sheet-pop .sheet {
    top: var(--pop-top, 72px);
    right: var(--pop-right, 40px);
    bottom: auto;
    max-height: calc(100dvh - var(--pop-top, 72px) - 16px);   /* окно у угла не уходит за низ экрана */
    width: 288px;   /* «Установить приложение» в одну строку (243 px) */
    padding: 16px;
    border-radius: var(--radius-btn);
    box-shadow: var(--shadow-pop);   /* без рамки (правило 13) — край даёт тень */
    transform: translateY(-8px);
    opacity: 0;
    transition: transform var(--dur) var(--ease), opacity var(--dur) var(--ease);
  }
  .sheet-pop.is-open .sheet { transform: none; opacity: 1; }
  .sheet-pop .sheet::after { display: none; }   /* окно короткое; поля 16 px — слой шире окна дал бы прокрутку вбок */
  .sheet-pop .sheet-head { display: none; }
  .sheet-pop .profile .btn { margin-top: 0; justify-content: center; }   /* окно без заголовка — слова по центру */
  .sheet-pop .profile .btn + .btn { margin-top: 8px; }
}

/* --- календарь (ui/calendar.js): месяц со стрелками, неделя с понедельника; концы выбора — чёрные, дни между — серые --- */
.cal-head { display: flex; align-items: center; justify-content: space-between; margin: 0 -12px 8px; }
.cal-title { font-weight: 500; }
/* на узком телефоне сетка заходит в поля листа: 7 дней по 44 px — от 308 px; где места хватает (390 и шире) — по краю
   колонки, как поля над ней (от d2, 13.11: на 390 выходила за колонку) */
.cal-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr));
  margin: 0 max(calc(4px - var(--gutter)), min(0px, calc((100% - 308px) / 2))); }
.cal-wd {
  padding: 8px 0;
  font-size: var(--t-label);
  letter-spacing: var(--caps);
  text-transform: uppercase;
  text-align: center;
  color: var(--ink-3);
}
.cal-day {
  height: 44px;
  min-width: 44px;
  border: 0;
  border-radius: var(--radius-btn);
  background: none;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  cursor: pointer;
}
/* пустая клетка — высотой дня: строка из одних пустых (шестая неделя) не схлопывается */
.cal-gap { min-height: 44px; }
.cal-day.is-in { border-radius: 0; background: var(--mist); }
.cal-day.is-end { background: var(--ink); color: var(--paper); }
.cal-day.is-today { text-decoration: underline; text-decoration-color: var(--metal); text-decoration-thickness: 2px; text-underline-offset: 4px; }
.cal-day:disabled { color: var(--line); cursor: default; }
.cal-apply { margin-top: 24px; }
@media (min-width: 1024px) {
  .cal-grid { margin: 0; }
}

/* --- уведомления ---------------------------------------------------------- */

.toasts {
  position: fixed;
  left: max(16px, var(--safe-left));
  right: max(16px, var(--safe-right));
  bottom: calc(var(--nav-h) + var(--safe-bottom) + 12px);
  z-index: 60;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  pointer-events: none;
}
.toast {
  max-width: 440px;
  padding: 12px 18px;
  border-radius: var(--radius-btn);
  background: var(--paper);
  color: var(--ink);
  font-size: var(--t-body);
  box-shadow: var(--shadow-pop);   /* без рамки (правило 13) */
  opacity: 0;
  transform: translateY(8px);
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.toast-bad { color: var(--bad-ink); }
/* телефон: уведомление — сверху, под шапкой. Внизу у телефона кнопки — действия карточки, «Сохранить» листа и формы
   («Подключить» в «Банке», от 1e 13.11: тост ложился на кнопки); шапка на время уведомления ничего не теряет, нажатия
   уведомление пропускает (pointer-events: none). Возникает сверху вниз */
@media (max-width: 1023px) {
  .toasts { top: calc(var(--safe-top) + var(--bar-h) + 8px); bottom: auto; }
  .toast { transform: translateY(-8px); }
}
.toast.is-in { opacity: 1; transform: none; }
@media (min-width: 1024px) {
  .toasts { left: auto; right: 32px; bottom: 32px; align-items: flex-end; }
}

/* --- состояния экрана: как пустой блок кабинета ------------------------------------ */

.st { padding: 32px 0; text-align: center; }
.st-title { font-size: var(--t-title); font-weight: 500; margin-bottom: 16px; }
.st-title:last-child { margin-bottom: 0; }
/* «Повторить» — слово в коробке 48 px: без поправки до него от заголовка вышло бы ~38 px вместо 16 */
.st :is(.st-title, .st-text) + .btn-secondary { margin-top: -12px; }
.st-text { color: var(--ink-2); margin-bottom: 16px; }
.st-error .st-title { color: var(--bad-ink); }
/* заголовок со значком («Ничего не нашлось ×») — одной строкой, по тому же краю, что и заголовок без значка */
.st-head { justify-content: center; margin-bottom: 16px; }
.st-head:last-child { margin-bottom: 0; }
.st-head > .st-title { margin: 0; }
.rt-nothing .st-head, .st-loading .st-head { justify-content: flex-start; }
.st-loading { padding: 0; text-align: left; }
.sk-row { padding: 16px 0; border-bottom: 1px solid var(--line-soft); }
.sk {
  display: block;
  height: 12px;
  border-radius: 4px;
  background: linear-gradient(90deg, #f0f0f0 25%, #f8f8f8 50%, #f0f0f0 75%);
  background-size: 200% 100%;
  animation: shimmer 1.4s ease-in-out infinite;
}
.sk-line { width: 64%; }
.sk-short { width: 32%; margin-top: 8px; }
/* скелет реестра (states.loading({ table: true })): строка названий таблицы кита и строки по 44 px с линией сетки */
.sk-thead { height: var(--tap); background: var(--th-bg); border-bottom: 1px solid var(--th-rule); }
.sk-tr { display: flex; align-items: center; height: var(--tap); padding: 0 12px; border-bottom: 1px solid var(--line); }
.sk-tr .sk-line { width: 48%; }
/* на компе — по левому краю, как заголовок раздела и содержимое: по центру 1120 px состояние висело в пустоте */
@media (min-width: 1024px) {
  .st { text-align: left; }
  .st-head { justify-content: flex-start; }
}

/* старт до оболочки (загрузка; после тихих повторов — строка «Нет связи» и «Повторить») — в раскладке входа: логотип
   там же, где на входе, и не прыгает при переходе ко входу; строка и кнопка — на месте поля и «Войти». Крутилка —
   только если старт дольше 0,4 с */
p.boot { padding: calc(32px + var(--safe-top)) var(--gutter) 24px; }   /* <noscript> в index.html */
.boot .st { padding: 0; text-align: left; }
/* старт не прошёл и после тихих повторов (app.js, её «25»): одна строка на месте поля и «Повторить» — без заголовка */
.boot-line { margin: 0 0 8px; font-size: var(--t-body); color: var(--ink-2); }
.boot .btn { display: flex; width: 100%; }
/* «Повторить», «Выйти», «Назад» — слова (правило 13, «2 снять»): по левому краю, нажимается вся строка */
.boot .btn:is(.btn-secondary, .btn-quiet) { justify-content: flex-start; }
.boot .btn-quiet { margin-top: 0; }   /* два слова подряд — строки по 48 px без зазора */
.boot-spin {
  display: block;
  width: 24px;
  height: 24px;
  border: 1px solid var(--line);
  border-top-color: var(--ink);
  border-radius: 50%;
  opacity: 0;
  animation: spin .8s linear infinite, fade-in .2s ease .4s forwards;
}
@keyframes fade-in { to { opacity: 1; } }

/* раздел ещё в старой CRM */
.moved-text { margin-bottom: 16px; color: var(--ink-2); }
@media (max-width: 1023px) {
  .moved .btn { display: flex; width: 100%; }
}

/* --- вход: логотип, логин, пароль, кнопка ------------------------------------------- */

.login {
  display: grid;
  justify-items: center;
  align-content: start;
  min-height: 100dvh;
  padding: calc(clamp(48px, 22vh, 200px) + var(--safe-top)) var(--gutter) calc(24px + var(--safe-bottom));
}
.login-box { width: min(100%, 360px); }
.login-logo { width: 160px; margin-bottom: 40px; color: var(--ink); }
.login-notice { margin-bottom: 16px; font-size: var(--t-btn); color: var(--ink-2); }
.login-net { margin-top: 6px; font-size: var(--t-btn); color: var(--bad-ink); }
/* перед кнопкой формы — 24 px (брендбук ERP, разд. 4): с 8 px отступ схлопывался с 16 px поля и выходил 16 */
.login .btn-block { margin-top: 24px; }

/* --- витрина кита (/erp/_kit) ---------------------------------------------------- */

.kit-part { margin-bottom: 40px; }
.kit-mark { margin-bottom: 16px; font-size: var(--t-label); font-weight: 500; color: var(--kicker); }
.kit-row { display: flex; flex-wrap: wrap; gap: 8px 24px; margin-bottom: 8px; }
.kit-states { display: grid; gap: 16px; }
.kit-state { margin: 0; border-top: 1px solid var(--line-soft); }   /* без коробок (правило 11) — образцы делит линия */
.kit-caption { padding-top: 12px; font-size: var(--t-label); font-weight: 400; color: var(--ink-3); }
@media (min-width: 1024px) {
  .kit-states { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* наведение — только где есть мышь: на телефоне подсветка залипала после тапа.
   .is-fresh — кнопка встала на место нажатой («Повторить» снова не загрузилось) прямо под курсором: подсветки нет,
   пока мышь над ней не двинулась (ui/states.js), иначе «Повторить» стояла бы с чертой, будто её уже навели */
@media (hover: hover) {
  .side-item:not([aria-current]):hover, .more-item:hover, .tabs-item:hover, .bar-profile:hover { color: var(--ink); }
  /* логотип (открывает «Сводку») отвечает на мышь, как пункты меню, — та же пара тонов, только наоборот: он и так чёрный */
  .side-logo:hover, .bar-logo:hover { color: var(--nav-ink); }
  .btn-primary:not(:disabled):not(.is-fresh):hover { background: var(--ink-hover); }
  .btn-secondary:not(:disabled):not(.is-fresh):hover, .btn-danger:not(:disabled):not(.is-fresh):hover {
    text-decoration: underline;
    text-underline-offset: 4px;
  }
  .btn-quiet:not(.is-fresh):hover { color: var(--ink); }
  .btn-icon:not(:disabled):hover { background: var(--mist); }
  .chip input:not(:checked) + span:hover { color: var(--ink); }
  .tbl tbody tr:hover { background: var(--card); }
  .rt tbody tr.is-link:hover td { background: var(--mist-2); }
  .rt-menu-item:hover { background: var(--mist); }
}

/* --- движение ------------------------------------------------------------- */

@keyframes spin { to { transform: rotate(360deg); } }
@keyframes shimmer { from { background-position: 100% 0; } to { background-position: -100% 0; } }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}
