/* Слой 3. Компоненты.
   ==========================================================================

   Здесь нет ни одного цветового литерала — только переменные из `tokens.css`.
   Это не стилистическое требование: арендатор перекрашивается сменой
   `--brand`, и любой захардкоженный цвет остаётся от предыдущего арендатора
   на его экране. Проверяется поиском: `grep -E '#[0-9a-fA-F]{3,8}' ui.css`
   должен молчать.

   Структура экранов — как у Everflow: полоса плиток показателей сверху,
   приветственная строка, сортируемые таблицы с пагинацией, период в топбаре.
   Визуальный язык — портал заказчика: светлый холст, белые карточки, светлый
   двухуровневый сайдбар, чёрная основная кнопка, пилюли-вкладки.

   Словарь классов и правила настройки — `docs/design/DESIGN_SYSTEM.md`.
   ========================================================================== */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  /* Мобильный Safari увеличивает шрифт при повороте экрана, если это не
     выключить: колонки таблицы, посчитанные для портрета, в ландшафте
     переставали помещаться. */
  -webkit-text-size-adjust: 100%;
  /* База шкалы. Была браузерная (16px), и рабочий текст выходил 13.7–14.9px —
     измерено на боевой странице 9 сентября. На настольном экране это мелко:
     «почему всё так мелко, у тебя же полно места на экране». Все размеры
     шрифта заданы в rem от этой строки, поэтому шкала кита сохраняется
     целиком, меняется только её основание. Отступы заданы в px и не растут:
     плотность таблиц держится на них. */
  font-size: 17px;
}

/* `!important` здесь не небрежность, а необходимость. Правило браузера
   `[hidden] { display: none }` имеет ту же специфичность, что и любой класс,
   и проигрывает объявленному позже. Блок «Остальные суммы» — это `.grid` с
   `display: grid`, и спрятанный в «Настроить экран» он оставался на экране:
   галочка снята, плитки на месте. Ловится только нажатием. */
[hidden] {
  display: none !important;
}

body {
  margin: 0;
  /* `clip`, а не `hidden`: hidden превратил бы body в контейнер прокрутки и
     сломал бы липкий топбар. Нужно ровно отсечь то, что выдвинуто за правый
     край (панель «Настроить экран» в закрытом виде), иначе на телефоне
     страница получала горизонтальную прокрутку на ширину этой панели.
     Найдено измерением на 375, а не чтением. */
  overflow-x: clip;
  background: var(--ground);
  color: var(--ink);
  font: 400 15px/1.45 var(--font-text);
  font-feature-settings: "tnum" 1, "lnum" 1;
  -webkit-font-smoothing: antialiased;
  /* lnum/tnum включены в самом ките. Для денежных колонок табличные цифры —
     не украшение: без них «4 372 ₽» и «11 100 ₽» в столбце пляшут по
     горизонтали, и сравнить их взглядом нельзя. */
  font-feature-settings: "lnum" 1, "tnum" 1;
}

h1,
h2,
h3 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 700;
  text-wrap: balance;
}
h1 {
  font-size: var(--fs-5);
  letter-spacing: -0.024em;
  line-height: 1.15;
}
h2 {
  font-size: var(--fs-3);
  letter-spacing: -0.012em;
}
h3 {
  font-size: var(--fs-2);
  letter-spacing: -0.01em;
}
p {
  margin: 0;
}
a {
  color: var(--link);
}
/* Плейсхолдер — единственный текст, которому положен gray_2 кита. */
::placeholder {
  color: var(--placeholder);
  opacity: 1;
}

/* Фокус виден всегда и одинаково. Убрать его дешевле всего и дороже всего:
   без него интерфейс перестаёт работать с клавиатуры, а заметит это тот, кто
   иначе работать не может. */
:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
  border-radius: 5px;
}

.mono {
  font-family: var(--font-mono);
  font-size: 0.88em;
}
/* Число в колонке: табличные цифры и без переносов. */
.num {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.muted {
  color: var(--ink-3);
}
/* Единственная утилита отступа. Больше их не заводим: набор утилит на все
   случаи — это второй способ верстать, и он всегда расходится с первым. */
.gap-top {
  margin-top: var(--s-4);
}
.sr {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* Иконки — один инлайновый спрайт (`_icons.html`), никаких шрифтов и никакой
   загрузки со стороны: `stroke: currentColor` красит иконку тем же цветом,
   что и текст рядом, а значит нечему разъехаться при смене акцента. */
.ic {
  width: 18px;
  height: 18px;
  flex: none;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.ic.s {
  width: 14px;
  height: 14px;
  stroke-width: 2;
}

/* ══ Оболочка ═════════════════════════════════════════════════════════════
   Три колонки: разделы, подразделы, полотно. Вторая колонка есть только там,
   где экран объявил `subnav`; без неё сетка сжимается до двух. */

.shell {
  display: grid;
  grid-template-columns: var(--rail-w) minmax(0, 1fr);
  min-height: 100vh;
}
.shell[data-has-sub="1"] {
  grid-template-columns: var(--rail-w) var(--sub-w) minmax(0, 1fr);
}
[data-sidebar="collapsed"] {
  --rail-w: 64px;
}

/* ── Столбец 1: разделы ───────────────────────────────────────────────── */
.rail {
  background: var(--rail);
  color: var(--ink);
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow: hidden;
  border-right: 1px solid var(--rail-line);
}
.rail-me {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 12px 10px 14px;
  min-height: var(--top-h);
}
/* Карточка пользователя кита: тёмный круг 32 с инициалами SemiBold 12,
   имя Body S Strong 13/20, под ним Meta 12 серым. */
.rail-me .av.solid {
  background: var(--dark);
  color: var(--white);
}
.rail-me .who-name {
  min-width: 0;
  flex: 1;
}
.who-name b {
  display: block;
  font-size: var(--fs-2);
  font-weight: 600;
  line-height: 1.35;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.who-name span {
  display: block;
  font-size: var(--fs-1);
  line-height: 1.3;
  color: var(--ink-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.rail-collapse {
  border: 0;
  background: none;
  color: var(--icon-mute);
  width: 28px;
  height: 28px;
  border-radius: var(--r-1);
  display: grid;
  place-items: center;
  cursor: pointer;
  flex: none;
  transition: background 140ms ease-out, color 140ms ease-out;
}
.rail-collapse:hover {
  background: var(--rail-hover);
  color: var(--ink);
}
[data-sidebar="collapsed"] .rail-collapse .ic {
  transform: rotate(180deg);
}

/* Пилюли областей — «Портал / CRM» у заказчика. У нас области две: кабинет
   партнёра и админка компании; недоступная человеку остаётся видимой, но
   выключенной — так понятно, что это одна система с двумя входами. */
.rail-pills {
  display: flex;
  gap: 4px;
  margin: 0 12px 10px;
  padding: 4px;
  background: var(--well);
  border-radius: var(--r-2);
}
/* Tabs сайдбара кита («Портал • / CRM •», доска Компоненты · Sidebar):
   серая дорожка `gray_5` радиусом 10, активная — белая пилюля радиусом 8 с
   тенью TabChip, иконка 16 слева, текст Body S 13, активный — Strong. Точка
   состояния — в правом верхнем углу. Неактивный текст — `--ink-2`, а не
   gray_2 кита: на серой дорожке gray_2 даёт 3,1:1. */
.pill-tab {
  flex: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 5px 8px;
  min-height: 30px;
  border-radius: var(--r-1);
  font-size: var(--fs-2);
  line-height: 20px;
  font-weight: 500;
  color: var(--ink-2);
  text-decoration: none;
  white-space: nowrap;
  position: relative;
}
.pill-tab .ic {
  width: 16px;
  height: 16px;
  color: var(--ink-2);
}
.pill-tab[aria-current="page"] {
  background: var(--card);
  color: var(--ink);
  font-weight: 600;
  box-shadow: var(--sh-chip);
}
.pill-tab[aria-current="page"] .ic {
  color: var(--ink);
}
/* Выключенная область не красится gray_3 кита: «Кабинет» рядом с «Админкой»
   стоит на каждом экране сотрудника, и 1,7:1 на gray_5 (посчитано по
   отрисованной странице) читается как дыра в планке, а не как подпись.
   `ink-3` даёт 4,7:1; что область недоступна, говорят вес, отсутствие
   белой подложки и курсор. */
.pill-tab[aria-disabled="true"] {
  color: var(--ink-3);
  font-weight: 400;
  cursor: default;
}
.pill-tab[aria-disabled="true"] .ic {
  color: var(--ink-3);
}
.pill-tab .dot {
  width: 6px;
  height: 6px;
  border-radius: var(--r-pill);
  background: var(--accent);
  position: absolute;
  top: 6px;
  right: 7px;
}

.rail-scroll {
  flex: 1;
  overflow-y: auto;
  padding: 4px 10px 8px;
}
.rail-scroll::-webkit-scrollbar {
  width: 5px;
}
.rail-scroll::-webkit-scrollbar-thumb {
  background: var(--line);
  border-radius: var(--r-pill);
}

/* Label Category кита: Medium 11/14, uppercase, разрядка 6%, `gray_2`. */
.nav-cap {
  font-size: 0.786rem;
  line-height: 14px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-2);
  font-weight: 500;
  padding: 14px 10px 6px;
}
.nav-cap:first-child {
  padding-top: 6px;
}
.nav-item {
  display: flex;
  align-items: center;
  gap: 11px;
  width: 100%;
  text-align: left;
  border: 0;
  background: none;
  color: var(--rail-ink);
  padding: 8px 10px;
  min-height: 36px;
  border-radius: var(--r-1);
  cursor: pointer;
  font: inherit;
  font-size: var(--fs-3);
  line-height: 20px;
  font-weight: 400;
  text-decoration: none;
  position: relative;
  transition: background 140ms ease-out, color 140ms ease-out;
}
/* NavItem кита: Default — тёмный текст без фона; Hover — `gray_5`;
   Active — `blue_bg` и синий текст с синей иконкой; Active-Hover —
   `blue_stroke`. Жирность не меняется: активность несёт цвет, а не вес,
   иначе пункты прыгают по ширине при переключении. Подпись активного
   пункта — `--accent-ink` (тот же синий, дотянутый до 4,5:1), иконка —
   `blue_1` кита как есть. */
.nav-item:hover {
  background: var(--rail-hover);
  color: var(--ink);
}
.nav-item[aria-current="page"] {
  background: var(--rail-active);
  color: var(--rail-active-ink);
}
.nav-item[aria-current="page"]:hover {
  background: var(--accent-bg-hover);
}
.nav-item[aria-current="page"] .ic {
  color: var(--accent);
}
.nav-item .ic {
  width: 18px;
  height: 18px;
  color: var(--ink-2);
  flex: none;
}
.nav-item .lbl {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Badge кита: 16px высоты, радиус 8, SemiBold 10 белым. Синий — обычный
   счётчик, красный — «требует внимания», серый — нейтральный. Заливки —
   `--badge` и `--hot` (см. tokens.css: белые цифры на blue_1 и red_1 кита не
   читаются, 2,9:1 и 3,5:1). */
.cnt {
  margin-left: auto;
  font-size: var(--fs-0);
  line-height: 12px;
  font-weight: 600;
  background: var(--badge);
  color: var(--white);
  min-width: 18px;
  height: 16px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 6px;
  border-radius: 8px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.cnt.hot {
  background: var(--hot);
  color: var(--white);
}
.cnt.plain {
  background: var(--gray-4);
  color: var(--ink);
}

/* Свёрнутый режим. Подписи прячутся, иконки центрируются, название остаётся
   в `title`: свёрнутая планка без подсказки — это ряд ребусов. Второй
   столбец в свёрнутом режиме тоже уходит: он подписан пунктами первого. */
[data-sidebar="collapsed"] .nav-item {
  justify-content: center;
  padding: 10px 0;
}
[data-sidebar="collapsed"] .nav-item .lbl,
[data-sidebar="collapsed"] .nav-item .cnt,
[data-sidebar="collapsed"] .nav-cap,
[data-sidebar="collapsed"] .rail-pills,
[data-sidebar="collapsed"] .rail-me .who-name,
[data-sidebar="collapsed"] .rail-foot .who-name,
[data-sidebar="collapsed"] .rail-foot .signout .lbl,
[data-sidebar="collapsed"] .subrail {
  display: none;
}
/* Колонка подразделов сворачивается отдельно от главного меню: они нужны
   человеку по отдельности, и одна кнопка на обе заставляла прятать нужное
   вместе с лишним. Свёрнутая колонка исчезает целиком, а не сжимается в
   полоску: полоска занимает место и не показывает ни одного названия. */
[data-sub="collapsed"] .subrail {
  display: none;
}
[data-sub="collapsed"] .shell[data-has-sub="1"] {
  grid-template-columns: var(--rail-w) minmax(0, 1fr);
}
/* Кнопка живёт в самой колонке и уезжает вместе с ней; вернуть колонку можно
   тем же переключателем в панели «Настроить экран». */
.sub-collapse {
  position: absolute;
  top: 10px;
  right: 8px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--ink-3);
  cursor: pointer;
}
.sub-collapse:hover {
  background: var(--accent-bg);
  color: var(--accent-ink);
}
.subrail {
  position: relative;
}
[data-sidebar="collapsed"] .shell[data-has-sub="1"] {
  grid-template-columns: var(--rail-w) minmax(0, 1fr);
}
[data-sidebar="collapsed"] .rail-me {
  flex-direction: column;
  padding: 12px 0 8px;
  gap: 6px;
}
[data-sidebar="collapsed"] .rail-foot {
  padding: 10px 8px;
}
[data-sidebar="collapsed"] .rail-brand {
  justify-content: center;
}

/* Подвал столбца: чья это программа и выход. Выход отделён от навигации
   намеренно: случайный выход из очереди начислений стоит потерянной работы. */
.rail-foot {
  border-top: 1px solid var(--rail-line);
  padding: 12px;
  display: grid;
  gap: 8px;
}
/* Плашка-пин кита (LeadExchangePin, «Биржа клиентов»): фон `blue_bg`,
   обводка `blue_stroke`, радиус 10, отступы 10/12, логотип 36×36 с радиусом 9,
   название 14/20 весом 600 цветом Text/Primary, подпись 12/16 цветом
   Text/Secondary — не `gray_2`: на голубом фоне он не дотягивал до 4,5:1
   и читался плохо. Текст переносится, а не обрезается: ширина колонки 232,
   «Партнёрская программа» в одну строку не помещается. */
.rail-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  padding: 10px 12px;
  background: var(--accent-bg);
  border: 1px solid var(--accent-bg-hover);
  border-radius: var(--r-2);
}
.rail-brand .who-name {
  display: grid;
  gap: 2px;
  min-width: 0;
}
.rail-brand .who-name b {
  font-weight: 600;
  font-size: var(--fs-3);
  line-height: 20px;
  color: var(--ink);
  white-space: normal;
  overflow-wrap: anywhere;
}
.rail-brand .who-name span {
  font-size: var(--fs-1);
  line-height: 16px;
  color: var(--ink-2);
  white-space: normal;
  overflow-wrap: anywhere;
}
.mark {
  width: 36px;
  height: 36px;
  border-radius: 9px;
  background: linear-gradient(180deg, var(--blue-1), var(--blue-2));
  color: var(--white);
  flex: none;
  display: grid;
  place-items: center;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-3);
}
.rail-foot form {
  margin: 0;
}
/* «Выйти» кита — красная строка с иконкой, без рамки. */
/* «Выйти» — красным, как в сайдбаре кита, но текстовым оттенком семейства:
   red_2 на белом даёт 4,1:1 (посчитано по отрисованной странице). */
.signout {
  width: 100%;
  border: 0;
  background: none;
  color: var(--bad-ink);
  border-radius: var(--r-1);
  padding: 7px 10px;
  font: inherit;
  font-size: var(--fs-2);
  justify-content: flex-start;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  transition: color 140ms ease-out, border-color 140ms ease-out;
}
.signout:hover {
  color: var(--red-2);
  background: var(--red-bg);
}

/* Кружок с инициалами. Цвет берётся из акцента, а не из имени: «цвет по
   хешу имени» даёт неотличимые оттенки на соседних строках.

   Буква — тёмная на светлой подложке акцента, а не акцентом по подложке:
   мятный кита (`mint_1`) на своей же подложке даёт 2.6:1, то есть буквы на
   экране, которые часть людей просто не прочтёт. Принадлежность к бренду
   несёт подложка, читаемость — тёмный текст. */
.av {
  width: 32px;
  height: 32px;
  border-radius: var(--r-pill);
  flex: none;
  display: grid;
  place-items: center;
  font-size: var(--fs-1);
  font-weight: 600;
  color: var(--ink);
  background: var(--brand-bg);
}
/* Заливка акцентом — только там, где рядом стоит полное имя и буква ничего
   не сообщает сверх него. */
.av.solid {
  color: var(--on-brand);
  background: var(--brand);
}

/* ── Столбец 2: подразделы ────────────────────────────────────────────── */
.subrail {
  background: var(--rail);
  border-right: 1px solid var(--rail-line);
  position: sticky;
  top: 0;
  height: 100vh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
/* Field chip кита (Field chip / Icon, Size M): пилюля 32 с обводкой
   `stroke`, иконка 18 цветом gray_2, текст 14 Text/Primary, отступ 12,
   зазор 6; hover — обводка gray_3. Поле поиска — тот же чип с вводом
   внутри: одна форма у фильтра и у поиска, как в примерах доски. */
.chip-field,
.sub-search {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 0 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--card);
  color: var(--ink);
  min-height: 32px;
  transition: border-color 140ms ease-out, box-shadow 140ms ease-out;
}
.sub-search {
  margin: 12px 12px 8px;
}
.chip-field .ic,
.sub-search .ic {
  width: 16px;
  height: 16px;
  color: var(--placeholder);
  flex: none;
}
.chip-field:hover,
.sub-search:hover {
  border-color: var(--gray-3);
}
.chip-field input,
.sub-search input {
  flex: 1;
  min-width: 0;
  border: 0;
  background: none;
  font: inherit;
  font-size: var(--fs-2);
  line-height: 20px;
  color: var(--ink);
  padding: 5px 0;
}
.chip-field:focus-within,
.sub-search:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-bg);
}
.sub-search input:focus {
  outline: 0;
}
.sub-body {
  flex: 1;
  overflow-y: auto;
  padding: 4px 12px 16px;
}
.sub-group {
  margin-bottom: 6px;
}
.sub-cap {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.786rem;
  line-height: 14px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-weight: 500;
  color: var(--ink-2);
  padding: 12px 10px 6px;
}
.sub-cap i {
  display: none;
}
/* SubItem кита: Body S 13/20, Default — тёмный без фона, Active — синий
   текст на `blue_bg`, Active-Hover — `blue_stroke`. */
.sub-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 10px;
  border-radius: var(--r-1);
  color: var(--ink);
  text-decoration: none;
  font-size: var(--fs-2);
  line-height: 20px;
  transition: background 130ms ease-out, color 130ms ease-out;
}
.sub-item .n {
  width: 14px;
  font-size: var(--fs-0);
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
  flex: none;
  text-align: right;
}
/* Название подраздела переносится, а не обрезается: у версий программы и
   у партнёров имена длиннее 232px бывают, и «Версия 3 — с 01.10.20…» без
   подсказки ничего не говорит. */
.sub-item .lbl {
  flex: 1;
  min-width: 0;
  overflow-wrap: anywhere;
}
.sub-item:hover {
  background: var(--rail-hover);
  color: var(--ink);
}
.sub-item[aria-current="page"] {
  background: var(--rail-active);
  color: var(--rail-active-ink);
}
.sub-item[aria-current="page"]:hover {
  background: var(--accent-bg-hover);
}
.sub-item.nested {
  padding-left: 30px;
}
.sub-item .cnt {
  background: var(--badge);
  color: var(--white);
}
.sub-item .st {
  margin-left: auto;
}
.sub-empty {
  padding: 14px 10px;
  font-size: var(--fs-1);
  color: var(--ink-3);
}

/* ── Верхняя панель ───────────────────────────────────────────────────── */
.main {
  min-width: 0;
  display: flex;
  flex-direction: column;
}
/* Header кита: 48px, белый, нижняя обводка `stroke`; слева крошки
   «Раздел / Подраздел» с иконкой раздела синим, справа иконки 32×32 без
   рамок. */
.top {
  position: sticky;
  top: 0;
  z-index: 9;
  background: var(--card);
  border-bottom: 1px solid var(--line);
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 0 16px;
  min-height: var(--top-h);
}
.crumbs {
  font-size: var(--fs-2);
  color: var(--ink-2);
  display: flex;
  align-items: center;
  gap: 8px;
  /* Крошки сжимаются первыми: они говорят, где человек находится, а он это и
     так знает, — а вот кнопки справа обязаны остаться нажимаемыми. */
  min-width: 0;
  flex: 0 1 auto;
  overflow: hidden;
}
.crumbs b {
  color: var(--ink);
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Родительская крошка — Text/Secondary, как «Раздел /» в шапке кита. */
.crumbs a {
  color: var(--ink-2);
  text-decoration: none;
}
.crumbs a:hover {
  color: var(--ink);
}
.top-right {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  flex: 0 0 auto;
}
/* Период — в топбаре, как у Everflow: он относится ко всем плиткам экрана
   сразу, а не к одной карточке. */
/* Период — Field chip кита с выпадающим списком внутри: иконка календаря,
   значение, шеврон системного select. */
.period {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: 1px solid var(--line);
  background: var(--card);
  border-radius: var(--r-pill);
  padding: 0 6px 0 12px;
  color: var(--placeholder);
  margin: 0;
  min-height: 32px;
}
.period:hover {
  border-color: var(--gray-3);
}
.period select {
  border: 0;
  background: none;
  font: inherit;
  font-size: var(--fs-2);
  line-height: 20px;
  font-weight: 500;
  color: var(--ink);
  padding: 5px 4px;
  cursor: pointer;
}
.period select:focus {
  outline: 0;
}
.period:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-bg);
}
/* Поиск в шапке — Field chip M кита (см. .chip-field): пилюля 32 с иконкой
   16 слева. */
.top-search {
  position: relative;
  width: min(280px, 26vw);
  margin: 0;
}
.top-search .ic {
  position: absolute;
  left: 12px;
  top: 50%;
  transform: translateY(-50%);
  width: 16px;
  height: 16px;
  color: var(--placeholder);
  pointer-events: none;
}
.top-search input {
  width: 100%;
  padding: 5px 14px 5px 34px;
  min-height: 32px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--card);
  font: inherit;
  font-size: var(--fs-2);
  line-height: 20px;
  color: var(--ink);
  transition: border-color 140ms ease-out, box-shadow 140ms ease-out;
}
.top-search input:hover {
  border-color: var(--gray-3);
}
.top-search input:focus {
  outline: 0;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-bg);
}
.top-btn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  border: 1px solid transparent;
  background: none;
  border-radius: var(--r-1);
  padding: 6px 10px;
  font: inherit;
  font-size: var(--fs-2);
  color: var(--ink);
  cursor: pointer;
  white-space: nowrap;
  text-decoration: none;
  transition: background 140ms ease-out, color 140ms ease-out;
}
.top-btn:hover {
  background: var(--gray-5);
  color: var(--ink);
}
/* Иконка без подписи — 32×32, как в шапке кита; на телефоне цель нажатия
   растёт до 40 (медиазапрос ниже). */
.top-btn.icon-only {
  padding: 6px;
  position: relative;
  min-width: 32px;
  min-height: 32px;
  justify-content: center;
}
.top-btn .dot {
  position: absolute;
  top: 4px;
  right: 4px;
  width: 7px;
  height: 7px;
  border-radius: var(--r-pill);
  background: var(--hot);
  border: 1.5px solid var(--card);
}
/* Бренд в шапке — только на телефоне: логотип 24 и название в две строки
   Bold 10 uppercase, как «ДОСТУПНОЕ ПРАВО» в мобильной шапке кита. */
.top-brand {
  display: none;
  align-items: center;
  gap: 8px;
  min-width: 0;
}
.top-brand .mark {
  width: 24px;
  height: 24px;
  border-radius: 6px;
  font-size: var(--fs-1);
}
/* Название в две строки, как «ДОСТУПНОЕ / ПРАВО» в мобильной шапке кита;
   переносится по словам, не обрезается. */
.top-brand b {
  font-size: var(--fs-0);
  line-height: 12px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--ink);
  max-width: 130px;
  overflow-wrap: anywhere;
}
.top-menu {
  display: none;
}
/* Карточка пользователя живёт в сайдбаре, как в ките; в шапке — только
   иконки. Блок остаётся в разметке ради выхода на телефоне, но не виден:
   выезжающее меню несёт и имя, и «Выйти». */
.me {
  display: none;
}
.me .who-name b {
  max-width: 160px;
}
/* Выход в топбаре появляется только на узком экране, где подвал планки
   спрятан. Правило стоит ЗДЕСЬ, до медиазапроса, а не после него: с равной
   специфичностью выигрывает последнее, и объявленное ниже `display: none`
   гасило кнопку на всех ширинах — на телефоне выйти было нечем. */
.mobile-out {
  display: none;
  margin: 0;
}

/* ── Полотно ──────────────────────────────────────────────────────────── */
.body {
  padding: 20px 20px 90px;
  min-width: 0;
}
.page-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 18px;
  flex-wrap: wrap;
  margin-bottom: var(--s-5);
}
.page-head .sub {
  font-size: 0.87rem;
  color: var(--ink-2);
  margin-top: 6px;
  /* Ограничение меры чтения: строка длиннее ~70 знаков теряется при переходе
     на следующую, а объяснения на этих экранах читают целиком. */
  max-width: 70ch;
}
.acts {
  display: flex;
  gap: var(--s-2);
  flex-wrap: wrap;
  align-items: center;
}

/* Приветственная строка. Числа в ней посчитало ядро; здесь они только
   склоняются и получают ссылку туда, где с ними работают. */
.hello {
  font-size: 0.95rem;
  color: var(--ink-2);
  margin: -4px 0 18px;
  line-height: 1.55;
  max-width: 90ch;
}
.hello b {
  color: var(--ink);
  font-weight: 700;
}
.hello a {
  color: var(--ink);
  font-weight: 600;
  text-decoration: underline;
  text-decoration-color: var(--brand);
  text-underline-offset: 3px;
  text-decoration-thickness: 2px;
}
.hello a:hover {
  color: var(--brand);
}

/* ══ Блок — модуль экрана ═════════════════════════════════════════════════
   Единица, из которой собран экран, и единица, которую человек прячет или
   двигает в «Настроить экран». Поэтому у каждого свой `data-block`. */

.block {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-2);
  box-shadow: none;
  margin-bottom: var(--gap-grid);
  scroll-margin-top: calc(var(--top-h) + 12px);
}
.block-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: var(--pad-head);
  border-bottom: 1px solid var(--line-soft);
  flex-wrap: wrap;
}
.block-head .hint {
  font-size: var(--fs-1);
  color: var(--ink-3);
}
.block-body {
  padding: var(--pad-card);
}
/* Блок из одной таблицы: у таблицы свои отступы в ячейках, внешние были бы
   вторым полем вокруг первого. */
.block-body.flush {
  padding: 0;
}
.block[hidden] {
  display: none;
}

.grid {
  display: grid;
  gap: var(--gap-grid);
  margin-bottom: var(--gap-grid);
}
.grid .block {
  margin-bottom: 0;
}
/* `min(…, 100%)` в первом аргументе minmax — не украшение: без него на экране
   уже 196px колонка остаётся 196-пиксельной, страница получает горизонтальную
   прокрутку, и с телефона половина плиток оказывается за краем. Поймано
   прогоном на 390px, а не чтением: на широком мониторе это невидимо. */
.k4 {
  grid-template-columns: repeat(auto-fit, minmax(min(196px, 100%), 1fr));
}
.k3 {
  grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
}
.k2 {
  grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr));
}
.split {
  grid-template-columns: minmax(0, 1.85fr) minmax(0, 1fr);
}
@media (max-width: 1000px) {
  .split {
    grid-template-columns: 1fr;
  }
}

/* ══ Полоса плиток показателей ═══════════════════════════════════════════
   Одна плитка — одна величина в трёх срезах и спарклайн по дням. Все числа
   приходят из `core/cabinet/periods.py` готовыми строками; разметка ничего
   не складывает и не делит. */

.pulse {
  display: grid;
  /* 168px — чтобы пять плиток вставали в ряд на 1440 при двух столбцах
     сайдбара; при 212px пятая уезжала на отдельную строку и читалась как
     отдельный блок, а не как часть полосы. */
  grid-template-columns: repeat(auto-fit, minmax(min(168px, 100%), 1fr));
  gap: var(--gap-grid);
  margin-bottom: var(--gap-grid);
  scroll-margin-top: calc(var(--top-h) + 12px);
}
.pulse .block {
  margin-bottom: 0;
}
.tile {
  padding: 14px 16px 12px;
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.tile-h {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  font-size: var(--fs-1);
  font-weight: 600;
  color: var(--ink-2);
  margin-bottom: 8px;
}
.tile-h .tile-hint {
  color: var(--icon-mute);
  display: grid;
  cursor: help;
}
.tile-main {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 10px;
  min-height: 40px;
}
.tile-v {
  flex-shrink: 0;
  font-family: var(--font-display);
  font-weight: 700;
  /* Сумма не переносится посреди разрядов: «16 91 / 0 ₽» читалось как две
     разные цифры. Вместо переноса кегль ужимается, а спарклайн уступает
     ширину — число в плитке главнее графика. */
  font-size: clamp(1.15rem, 1.3vw, 1.6rem);
  letter-spacing: -0.03em;
  line-height: 1.05;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  min-width: 0;
}
/* Спарклайн стоит там, где у заказчика в карточке финансов иконка графика:
   на том же месте, но настоящий — по дням выбранного месяца. */
.spark {
  width: 92px;
  height: 32px;
  flex: 0 1 92px;
  min-width: 48px;
  overflow: visible;
  color: var(--brand);
}
.spark path {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linejoin: round;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}
.tile-rows {
  margin: 12px 0 0;
  padding-top: 10px;
  border-top: 1px solid var(--line-soft);
  display: grid;
  gap: 5px;
}
.tile-rows > div {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: baseline;
  gap: 10px;
  font-size: var(--fs-1);
}
.tile-rows dt {
  margin: 0;
  color: var(--ink-3);
  white-space: nowrap;
}
.tile-rows dd {
  margin: 0 0 0 auto;
  color: var(--ink);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
}
/* Дельта — разность двух посчитанных ядром срезов. Процента здесь нет и не
   будет: деление денег вне ядра и без оракула нам не нужно. */
.delta {
  display: inline-flex;
  align-items: center;
  font-weight: 700;
  font-size: 0.68rem;
  padding: 1px 6px;
  border-radius: var(--r-1);
  background: var(--mute);
  color: var(--mute-ink);
}
.delta.up {
  background: var(--ok-bg);
  color: var(--ok-ink);
}
.delta.down {
  background: var(--bad-bg);
  color: var(--bad-ink);
}

/* Малые плитки прежнего вида остаются для карточки партнёра и настроек. */
.kpi {
  padding: 16px 18px 15px;
}
.kpi .t {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  font-size: var(--fs-1);
  color: var(--ink-3);
  font-weight: 600;
  margin-bottom: 10px;
}
.kpi .t .ic {
  width: 15px;
  height: 15px;
}
.kpi .v {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.6rem;
  letter-spacing: -0.03em;
  line-height: 1.05;
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}
.kpi .v i {
  font-style: normal;
  font-size: 0.58em;
  color: var(--ink-3);
  margin-left: 4px;
  font-weight: 500;
}
.kpi .f {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  margin-top: 9px;
  font-size: 0.76rem;
  color: var(--ink-3);
}

/* ── Главная цифра ────────────────────────────────────────────────────── */
/* Одна на экран. Ради неё партнёр и заходит; вторая такая же превращает
   экран в выбор между двумя одинаково громкими числами. Янтарный (--money)
   здесь и только здесь — на иконке рядом с подписью: как только им покрашено
   что-то кроме денег, он перестаёт работать указателем на деньги. Сама
   сумма — тёмная (`--money-ink`): orange_2 на белом даёт 2,3:1. */
.hero {
  padding: 22px 24px;
}
.hero .t {
  font-size: 0.84rem;
  color: var(--ink-2);
  margin-bottom: var(--s-2);
  display: flex;
  align-items: center;
  gap: var(--s-2);
  font-weight: 600;
}
.hero .t .ic {
  color: var(--money);
}
.hero .v {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--fs-6);
  letter-spacing: -0.035em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--money-ink);
  overflow-wrap: anywhere;
}
.hero .note {
  margin: 14px 0 0;
  padding-top: 14px;
  border: 0;
  border-top: 1px solid var(--line-soft);
  border-radius: 0;
  background: none;
  display: block;
  font-size: 0.84rem;
  color: var(--ink-2);
}

/* ══ Таблица ══════════════════════════════════════════════════════════════ */

/* Прокрутка живёт в своей коробке. Иначе на телефоне уезжает вся страница,
   и человек теряет из виду навигацию, пытаясь досмотреть колонку суммы.

   `position: relative` — не косметика. В заголовке колонки действий лежит
   подпись для экранного чтеца (`.sr`, `position: absolute`), и без
   позиционированного предка её содержащим блоком становилась страница: она
   вставала на своё статическое место внутри 620-пиксельной таблицы, то есть
   ЗА правым краем экрана, и раздвигала документ до ширины таблицы — уже мимо
   коробки прокрутки. На 375 px документ был 620 px, страница прокручивалась
   целиком (дефект №138). Найдено поэлементным выключением в браузере, а не
   чтением CSS: по коду таблица была «в коробке». */
.table-wrap {
  position: relative;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
table {
  width: 100%;
  border-collapse: collapse;
}
.table-wrap table {
  min-width: 620px;
}
/* Заголовок таблицы кита: Meta 12 `gray_2`, обычный вес, на холсте. */
th {
  text-align: left;
  font-size: var(--fs-1);
  color: var(--ink-2);
  font-weight: 400;
  padding: 10px 14px;
  background: var(--gray-bg-1);
  border-bottom: 1px solid var(--line-soft);
  white-space: nowrap;
}
th.sort {
  cursor: pointer;
  user-select: none;
}
th.sort:hover {
  color: var(--ink);
}
/* Стрелки сортировки — двойные, как у заказчика; активное направление
   подсвечивается акцентом. */
th.sort .ic {
  width: 12px;
  height: 12px;
  margin-left: 5px;
  vertical-align: -2px;
  opacity: 0.5;
  stroke-width: 2.4;
}
th[aria-sort] {
  color: var(--ink);
}
th[aria-sort] .ic {
  opacity: 1;
  color: var(--accent);
}
th.r,
td.r {
  text-align: right;
}
th.act,
td.act {
  /* Ширина под кнопки, а не под три точки: действия строки теперь видны, а не
     спрятаны в меню. `1%` заставляет колонку взять ровно своё содержимое. */
  white-space: nowrap;
  width: 1%;
  text-align: right;
  padding-left: 0;
}
td.act .btn + .btn {
  margin-left: 6px;
}
/* Строка таблицы кита — 40px (`--row-h`; у таблицы height работает как
   минимум). Отступ ячейки 6 сверху и снизу: и одна строка текста 13/20, и
   чип состояния 28 дают ровно 40; две строки — 48. */
th {
  height: var(--row-h);
}
td {
  padding: var(--pad-cell);
  height: var(--row-h);
  border-bottom: 1px solid var(--line-soft);
  vertical-align: middle;
  font-size: var(--fs-2);
  line-height: 20px;
}
tbody tr:last-child td {
  border-bottom: 0;
}
tbody tr {
  transition: background 120ms ease-out;
}
tbody tr:hover td {
  background: var(--hover);
}
/* Сумма в колонке: табличные цифры и без переноса. Перенос суммы на вторую
   строку сдвигает всю колонку и делает столбец нечитаемым сверху вниз. */
td.r {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  white-space: nowrap;
}
/* Вторая строка ячейки — Meta 12/16 Text/Tertiary. */
td .s {
  font-size: var(--fs-1);
  line-height: 16px;
  color: var(--ink-3);
  font-weight: 400;
}
/* Публичный код партнёра — длинный неразрывный идентификатор, и без явного
   разрешения переноса он вылезает из колонки и наезжает на соседнюю. Видно
   это только на настоящих данных: на выдуманном «PARTNER1» помещается всё. */
.wrap-any {
  overflow-wrap: anywhere;
  white-space: normal;
}
/* Список партнёров: колонке имени положено не меньше 200px. Без этого
   авторазметка на 1440 отдавала её под чип «приглашён, кабинет ещё не
   открыт» и даты, и «Партнёр Первый» с кодом ложились в четыре строки при
   пустом месте справа (измерено на стенде: 100px имени при 919 таблицы). */
#list td:first-child {
  min-width: 200px;
}
/* Клиенты: колонке партнёра то же правило — иначе имя и код с переносом
   `anywhere` ужимаются до одной буквы в строке, когда таблица тесная. */
.col-partner {
  min-width: 190px;
}
/* Номер лида короткий и один: колонка берёт ровно свою ширину, иначе
   авторазметка раздаёт ей лишнее, а «Состояние» уезжает за край. */
#list td.col-client,
.col-client {
  width: 1%;
  min-width: 0;
  white-space: nowrap;
}
/* В ячейке таблицы у переносимого текста есть пол ширины: `anywhere` входит
   в минимальную ширину колонки, и авторазметка на 360px отдавала колонке
   партнёра ширину в одну букву — «Мар / ия / Леб…» (измерено в браузере).
   `break-word` вместо `anywhere` не подходит: он в минимум не входит вовсе,
   и код партнёра растянул таблицу на 1440px до 1073px в обёртке 919. Пол в
   12 символов держит имя словами, а код — тремя строками. Только на узком
   экране: на 1440 те же 12ch у кода и чипа состояния в сумме дают 942 в
   обёртке 919, и у таблицы появляется прокрутка на ровном месте. */
@media (max-width: 900px) {
  td .wrap-any {
    min-width: 12ch;
  }
}
.who2 {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}
.who2 .n {
  min-width: 0;
}
tr.linked td a.cell {
  color: inherit;
  text-decoration: none;
  display: block;
}
tr.linked:hover td a.cell {
  color: var(--link);
}
/* Строка с решением раскрывается под строкой очереди: формы подтверждения и
   отклонения живут рядом с суммой, о которой идёт речь, а не этажом ниже. */
tr.decide > td {
  background: var(--gray-bg-1);
  padding: 14px 16px 16px;
}
tr.decide .decide-grid {
  display: grid;
  gap: 10px;
}
tr.decide[hidden] {
  display: none;
}
tbody tr.open td {
  background: var(--hover);
}

/* Подвал таблицы: «N всего · ‹ 1 2 ›». Страницы режутся на клиенте из уже
   показанных строк — это помощь глазу, а не серверная выборка, и подпись
   честно говорит «всего», а не «найдено на сервере». */
.table-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 11px 16px;
  border-top: 1px solid var(--line-soft);
  font-size: var(--fs-1);
  color: var(--ink-3);
  flex-wrap: wrap;
}
.pager {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
/* Страницы — Button Tabs Dark кита (ViennaChipsItem, размер S, узел
   8199:14275): 30px, радиус 8, текст 13; Default — `gray_5`, Default_Hover —
   `gray_bg_3`, Pressed — `dark` с белым текстом, Disabled — `gray_bg_1` с
   `gray_3`. */
.pager button {
  border: 0;
  background: var(--gray-5);
  min-width: 30px;
  height: 30px;
  border-radius: var(--r-1);
  font: inherit;
  font-size: var(--fs-2);
  color: var(--ink);
  cursor: pointer;
  display: grid;
  place-items: center;
  padding: 0 8px;
  transition: background 130ms ease-out, color 130ms ease-out;
}
.pager button[aria-current="page"] {
  background: var(--primary);
  color: var(--on-primary);
  font-weight: 600;
}
.pager button[aria-current="page"]:hover {
  background: var(--primary-hover);
}
.pager button[disabled] {
  background: var(--gray-bg-1);
  color: var(--disabled-ink);
  cursor: default;
}
.pager button:hover:not([disabled]):not([aria-current="page"]) {
  background: var(--gray-bg-3);
}

/* Меню строки «⋮». `<details>` вместо скрипта: открывается и закрывается
   без JS, закрывается по клику вне (ui.js) и по Escape. */
/* Действие в строке таблицы — видимая кнопка, а не три точки. Всплывающее
   меню обрезалось горизонтальной прокруткой таблицы: человек нажимал и не
   видел ничего (замечание Данила 9 сентября). Там, где действие требует
   ввода — например причины отзыва доступа, — форма раскрывается ВНУТРИ
   строки: она никуда не всплывает, а значит и обрезать её нечему. */
.rowform {
  display: inline-block;
  text-align: left;
}
.rowform summary {
  list-style: none;
  cursor: pointer;
}
.rowform summary::-webkit-details-marker {
  display: none;
}
.rowform form {
  margin-top: 8px;
}

/* ── Список «строка — значение» ───────────────────────────────────────── */
.rows > div {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--s-5);
  padding: var(--pad-row);
  border-bottom: 1px solid var(--line-soft);
  font-size: var(--fs-2);
}
.rows > div:last-child {
  border-bottom: 0;
}
.rows dl,
.rows dt,
.rows dd {
  margin: 0;
}
/* Подпись строки переносится по словам, а не «где придётся»: `anywhere`
   разрывал «Состояния» посередине там, где слово целиком помещалось на
   следующей строке. Идентификаторы, которые действительно надо рвать,
   помечаются классом `.wrap-any` поимённо. */
.rows dt,
.rows .l {
  color: var(--ink-2);
  flex: 1 1 0;
  /* Подписи гарантированы 40 % строки: в узкой карточке «Откуда эта сумма»
     (288px содержимого) значение в половину строки оставляло подписи 110px,
     и «администратором» в пояснении ломалось на «администраторо / м». */
  min-width: 40%;
  overflow-wrap: break-word;
}
/* Значение не ужимается ради подписи: во flex оба столбца сжимаются
   пропорционально своей ширине, и длинное пояснение под подписью отбирало
   место у «5 000 ₽» и «WS32B72A», ломая их посимвольно. Значение держит
   свою ширину до половины строки, дальше переносится по словам. */
.rows dd,
.rows .v {
  flex: 0 0 auto;
  max-width: 50%;
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  white-space: nowrap;
}
/* `.wrap-any` обязан побеждать `nowrap` выше и здесь: у `.rows dd`
   специфичность выше, чем у одного класса, и «Вы привели этого клиента» в
   объяснении суммы на 1024 px уезжало за край страницы на 13 px (дефект
   №138, измерено, а не прочитано). */
.rows dd.wrap-any,
.rows .v.wrap-any {
  white-space: normal;
}
.rows .s {
  font-size: var(--fs-1);
  line-height: 16px;
  color: var(--ink-3);
  font-weight: 400;
  margin-top: 2px;
  white-space: normal;
  text-align: left;
}
/* Итоговая строка прижата заливкой: она не «ещё одна строка», а результат
   перечисленных выше. */
.rows .sum {
  background: var(--gray-bg-1);
  margin: var(--s-2) 0 0;
  padding: 14px var(--pad-card-x);
  border-radius: var(--r-2);
  border-bottom: 0;
}
/* Под нижний край карточки итог выезжает только тогда, когда он и есть
   последнее на карточке. Иначе заливка «до края» обрывалась посреди
   карточки — на реестре выплат под ней стоят пояснение и кнопка. */
.block-body > .rows:last-child > .sum:last-child {
  margin: var(--s-2) calc(-1 * var(--pad-card-x)) calc(-1 * var(--pad-card-y));
  border-radius: 0 0 var(--r-4) var(--r-4);
}
.rows .sum dt,
.rows .sum .l {
  color: var(--ink);
  font-weight: 700;
}
.rows .sum dd,
.rows .sum .v {
  font-family: var(--font-display);
  font-size: 1.28rem;
  letter-spacing: -0.03em;
}

/* ══ Состояния ════════════════════════════════════════════════════════════
   Словарь, а не палитра. Один класс на положение дел, четыре цвета кита на
   все состояния сразу. Спор и возврат намеренно НЕ красятся как ошибка
   системы: это не поломка, а положение дел, о котором надо знать. */

/* Чип кита, размер S (доска Chips, узлы 587:74 green / 5239:5862 blue,
   рамка 98×28): пилюля 28px, текст Body S 13/20 цветом `dark`, отступ 4/12,
   обводка 1px цветом семейства, заливка — подложка семейства (Pressed).
   Текст тёмный, как у самого кита: цвет несут заливка, обводка и точка. Так
   и «удержание» на orange_bg читается 8,9:1, тогда как оранжевый текст не
   дотянул бы и до 3:1. Семейства — четыре состояния кита: success, problem,
   error, info; серый — «Active» кита (gray_5 без обводки). */
.st {
  --st-line: var(--mute-line);
  --st-dot: var(--gray-2);
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--fs-2);
  line-height: 20px;
  font-weight: 400;
  padding: 3px 12px 3px 10px;
  border: 1px solid var(--st-line);
  border-radius: var(--r-pill);
  white-space: nowrap;
  background: var(--mute);
  color: var(--ink);
}
/* Точка — второй, не-цветовой признак состояния. Без неё «подтверждено» и
   «отклонено» различаются только оттенком, а один мужчина из двенадцати
   этого оттенка не видит. */
.st i {
  width: 6px;
  height: 6px;
  border-radius: var(--r-pill);
  background: var(--st-dot);
  flex: none;
}
/* Тег состояния кита (Status, доска Компоненты · Sidebar): Badge Status
   11/14 SemiBold, 22px, радиус 6 — для подразделов и других мест, где
   28px чип не помещается. */
.st.xs,
.sub-item .st {
  font-size: 0.786rem;
  line-height: 14px;
  font-weight: 600;
  padding: 3px 8px 3px 7px;
  border-radius: 6px;
  gap: 5px;
}

/* Начисление: ждёт решения → подтверждено → выплачено. */
.st-pending,
.st-draft,
.st-hold {
  --st-line: var(--wait);
  --st-dot: var(--orange-2);
  background: var(--wait-bg);
}
.st-approved,
.st-published,
.st-active,
.st-paid_external,
.st-paid {
  --st-line: var(--ok);
  --st-dot: var(--positive-2);
  background: var(--ok-bg);
}
.st-rejected,
.st-reversed,
.st-archived,
.st-cancelled {
  --st-line: var(--mute-line);
  --st-dot: var(--gray-2);
  background: var(--mute);
}
/* Возврат и спор — тревожное, но не «сломалось»: деньги придётся вернуть или
   решение принимает человек. */
.st-recovery_open,
.st-disputed,
.st-conflict {
  --st-line: var(--bad);
  --st-dot: var(--red-2);
  background: var(--bad-bg);
}
.st-info {
  --st-line: var(--info);
  --st-dot: var(--blue-1);
  background: var(--info-bg);
}

/* ══ Кнопки ═══════════════════════════════════════════════════════════════
   Кнопки кита: высота 32, радиус 6, текст 13 Medium. Стандартная — тёмная
   (`dark` → hover `dark_hover`); белая с обводкой — вторичная; зелёная
   (`green_1` → `green_hover`) — исключение для главного действия панели
   инструментов, и кит прямо запрещает красить ею всё остальное. Акцент
   арендатора кнопке не достаётся: он отвечает за «где я», а не за «нажми». */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  border: 1px solid var(--primary);
  background: var(--primary);
  color: var(--on-primary);
  font: inherit;
  font-size: var(--fs-2);
  font-weight: 500;
  padding: 5px 14px;
  /* Кнопка кита — 32: 20 строки + 5 + 5 + обводка. Без явного line-height
     наследовалось 1.55 и выходило 33,6. */
  line-height: 20px;
  border-radius: var(--r-btn);
  cursor: pointer;
  white-space: nowrap;
  text-decoration: none;
  min-height: 32px;
  transition:
    transform 130ms var(--ease),
    background 130ms ease-out,
    border-color 130ms ease-out,
    color 130ms ease-out;
}
.btn:hover {
  background: var(--primary-hover);
  border-color: var(--primary-hover);
}
.btn:active {
  transform: scale(0.975);
}
.btn[disabled] {
  opacity: 0.45;
  cursor: default;
  transform: none;
}
/* Вторичная не спорит с главной: одинаковые вес и размер заставляли глаз
   выбирать между двумя равно громкими кнопками. */
.btn.secondary {
  background: var(--card);
  color: var(--ink);
  border-color: var(--line);
}
.btn.secondary:hover {
  border-color: var(--gray-3);
  background: var(--card);
}
.btn.ghost {
  background: none;
  color: var(--ink-2);
  border-color: transparent;
}
.btn.ghost:hover {
  color: var(--ink);
  background: var(--well);
  border-color: transparent;
}
.btn.danger {
  background: var(--card);
  color: var(--bad-ink);
  border-color: var(--line);
}
.btn.danger:hover {
  border-color: var(--bad);
  background: var(--card);
}
.btn.accent,
.btn.cta {
  background: var(--cta);
  border-color: var(--cta);
  color: var(--white);
}
.btn.accent:hover,
.btn.cta:hover {
  background: var(--cta-hover);
  border-color: var(--cta-hover);
}
.btn.sm {
  padding: 3px 10px;
  font-size: var(--fs-1);
  border-radius: var(--r-btn);
  min-height: 28px;
}
.btn.lg {
  min-height: 40px;
  padding: 8px 18px;
  font-size: var(--fs-3);
}
.btn.wide {
  width: 100%;
}

/* Ссылка, ведущая назад. Отдельно от кнопок: это не действие. */
.back {
  font-size: var(--fs-1);
  color: var(--ink-3);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-bottom: 14px;
}
.back:hover {
  color: var(--ink);
}

/* ══ Формы ════════════════════════════════════════════════════════════════ */

.field {
  display: block;
  margin-bottom: 15px;
}
.field .l,
label.l {
  display: block;
  font-size: var(--fs-1);
  color: var(--ink-2);
  margin-bottom: 6px;
  font-weight: 600;
}
.field .s {
  display: block;
  font-size: 0.76rem;
  color: var(--ink-3);
  margin-top: 5px;
}
.field input,
.field select,
.field textarea,
.inp {
  width: 100%;
  font: inherit;
  font-size: 0.87rem;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-2);
  background: var(--card);
  color: var(--ink);
}
/* 16px на телефоне: поле с меньшим шрифтом iOS увеличивает при фокусе, и
   страница уезжает вбок посреди ввода. */
@media (max-width: 640px) {
  .field input,
  .field select,
  .field textarea,
  .inp {
    font-size: 16px;
  }
}
.field input:focus,
.field select:focus,
.field textarea:focus,
.inp:focus {
  outline: 0;
  border-color: var(--brand);
  box-shadow: 0 0 0 3px var(--brand-bg);
}
.field textarea {
  min-height: 80px;
  resize: vertical;
}
.field input[type="file"] {
  padding: 8px 10px;
  font-size: var(--fs-1);
}
input[type="checkbox"] {
  width: 15px;
  height: 15px;
  accent-color: var(--brand);
  margin: 0;
  cursor: pointer;
}
/* Поле кода: шесть цифр читаются группой, а не сплошным числом. */
.code-input {
  font-family: var(--font-mono);
  font-size: 1.5rem;
  letter-spacing: 0.28em;
  text-align: center;
  padding: 12px;
}
.check {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: var(--fs-1);
  color: var(--ink-2);
  margin: 0;
  cursor: pointer;
}
.check input {
  width: auto;
}

/* Форма в две колонки на широком экране и в одну на узком. Полей много, и в
   один столбец они превращаются в анкету. */
.form-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0 var(--s-4);
}
.form-grid .full {
  grid-column: 1 / -1;
}
@media (max-width: 640px) {
  .form-grid {
    grid-template-columns: 1fr;
  }
}

/* Решение принимается там же, где набирается его причина: форма в одну
   строку, а не поле сверху и кнопка этажом ниже. */
.form-inline {
  display: flex;
  gap: var(--s-2);
  align-items: center;
  flex-wrap: wrap;
  margin: 0;
}
.form-inline .inp {
  flex: 1;
  min-width: 200px;
  width: auto;
}
.form-inline + .form-inline {
  margin-top: 10px;
}

/* ══ Вкладки и переключатель ═════════════════════════════════════════════
   TabChip кита, «White Cell» (доска Chips/Tabs, узел 1117:1323 —
   единственный, чьи значения отдал коннектор Figma): дорожка `gray_bg_2`
   радиусом 30 с отступом 5; пункт — отступ 4/20, радиус 30, Exo 2 SemiBold
   14/20; активный (Pressed) — белая пилюля с тенью 0 5px 5px
   rgba(73,106,72,.12) и текстом `dark`, остальные — на дорожке. Размер M:
   пункт 28, дорожка 38. Неактивный текст — `--ink-2`, а не gray_2 кита:
   gray_2 на gray_bg_2 даёт 3,1:1. Счётчик внутри — бейдж кита 16px. */

.tabs {
  display: inline-flex;
  gap: 0;
  padding: 5px;
  background: var(--gray-bg-2);
  border-radius: var(--r-chip);
  margin: 0;
  max-width: 100%;
  overflow-x: auto;
}
.tabs a,
.tabs button {
  border: 0;
  background: none;
  padding: 4px 20px;
  min-height: 28px;
  font: inherit;
  font-size: var(--fs-3);
  line-height: 20px;
  font-weight: 600;
  color: var(--ink-2);
  cursor: pointer;
  border-radius: var(--r-chip);
  text-decoration: none;
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  transition: color 130ms ease-out, background 130ms ease-out, box-shadow 130ms ease-out;
}
.tabs a:hover,
.tabs button:hover {
  color: var(--ink);
}
.tabs [aria-selected="true"],
.tabs [aria-current="page"] {
  color: var(--ink);
  background: var(--card);
  box-shadow: var(--sh-chip);
}
.tabs .cnt {
  margin: 0;
}
/* Размер S кита (узел 1117:1334: пункт 24, дорожка 34, текст 13). */
.tabs.s a,
.tabs.s button {
  padding: 2px 16px;
  min-height: 24px;
  font-size: var(--fs-2);
}
/* Вкладки в шапке блока: дорожка 38 выше строки заголовка, и отступ шапки
   ужимается, чтобы блок не вырастал на лишние 8px. */
.block-head .tabs {
  margin: -4px 0;
}

/* Switch кита (узел 7697:3108, размер M, Color=Blue): дорожка 40×22 с
   радиусом во всю высоту, кружок 18 с отступом 2 и тенью; Pressed —
   `blue_1`, Not_pressed — `gray_bg_3`, Disabled_pressed — `blue_3` без тени,
   Disabled_not_pressed — `gray_5`. Кнопка с role=switch: состояние читает и
   экранный чтец, и CSS. */
.switch {
  width: 40px;
  height: 22px;
  border-radius: var(--r-pill);
  border: 0;
  padding: 0;
  background: var(--gray-bg-3);
  position: relative;
  cursor: pointer;
  flex: none;
  transition: background 170ms ease-out;
}
.switch::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 18px;
  height: 18px;
  border-radius: var(--r-pill);
  background: var(--white);
  box-shadow: 0 1px 2px rgba(66, 66, 73, 0.2);
  transition: transform 190ms var(--ease);
}
.switch[aria-checked="true"] {
  background: var(--accent);
}
.switch[aria-checked="true"]::after {
  transform: translateX(18px);
}
.switch[disabled] {
  background: var(--gray-5);
  cursor: default;
}
.switch[disabled]::after {
  box-shadow: none;
}
.switch[disabled][aria-checked="true"] {
  background: var(--blue-3);
}
/* Строка «подпись — тумблер», как в примерах доски Toggle: подпись 14/20
   слева, тумблер справа; у выключенного подпись gray_2. */
.sw {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
  padding: 9px 0;
  border-bottom: 1px solid var(--line-soft);
  font-size: var(--fs-2);
  line-height: 20px;
}
.sw:last-child {
  border-bottom: 0;
}
.sw .t {
  font-weight: 500;
}
.sw .s {
  font-size: var(--fs-1);
  line-height: 16px;
  color: var(--ink-3);
  margin-top: 2px;
  max-width: 56ch;
}
.sw:has(.switch[disabled]) .t {
  color: var(--ink-2);
}
/* Тумблер-индикатор в списке «строка — значение»: слово рядом обязательно,
   положение тумблера не единственный носитель смысла. */
.sw-ro {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

/* ══ Замечания, пустые состояния, копирование ════════════════════════════ */

/* Замечание — рамка с цветным ребром, а не заливка во всю ширину: заливка
   спорит с состоянием строки в таблице под ним. */
.note {
  display: flex;
  gap: 11px;
  align-items: flex-start;
  border: 1px solid var(--line-soft);
  border-left: 3px solid var(--ink-3);
  border-radius: var(--r-3);
  padding: 12px 15px;
  font-size: 0.83rem;
  color: var(--ink-2);
  background: var(--card);
  margin-bottom: var(--gap-grid);
}
.note .ic {
  color: var(--ink-2);
  margin-top: 1px;
}
.note b {
  color: var(--ink);
}
.note.warn {
  border-left-color: var(--wait);
  background: var(--wait-bg);
}
.note.warn .ic {
  color: var(--wait-ink);
}
.note.stop {
  border-left-color: var(--bad);
  background: var(--bad-bg);
}
.note.stop .ic {
  color: var(--bad-ink);
}
.note.ask {
  border-left-color: var(--info);
  background: var(--info-bg);
}
.note.ask .ic {
  color: var(--info-ink);
}
.note.ok {
  border-left-color: var(--ok);
  background: var(--ok-bg);
}
.note.ok .ic {
  color: var(--ok-ink);
}

/* Пустое состояние объясняет, что делать, а не сообщает о пустоте. */
.empty {
  text-align: center;
  padding: 34px 20px;
  color: var(--ink-3);
  font-size: var(--fs-2);
}
.empty .ic {
  width: 26px;
  height: 26px;
  color: var(--icon-mute);
  margin-bottom: 10px;
}
.empty b {
  display: block;
  color: var(--ink-2);
  font-weight: 600;
  margin-bottom: 4px;
}

/* Ссылку выделяют и копируют вручную; кнопка «скопировать» есть, но она
   украшение поверх работающего текста, а не единственный путь к нему. */
.copy {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  border: 1px dashed var(--gray-3);
  border-radius: var(--r-3);
  padding: 11px 14px;
  background: var(--gray-bg-1);
}
.copy .mono {
  color: var(--ink-2);
  overflow-wrap: anywhere;
  min-width: 0;
}

.pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--fs-1);
  color: var(--ink-2);
  background: var(--well);
  border-radius: var(--r-pill);
  padding: 5px 10px;
}
.tag {
  font-size: 0.62rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-3);
  border: 1px solid var(--line);
  padding: 2px 7px;
  border-radius: var(--r-pill);
  font-weight: 700;
  white-space: nowrap;
}

/* ══ Уведомления ══════════════════════════════════════════════════════════
   Четыре вида тостера кита. Тостер не крадёт фокус и объявляется
   `aria-live="polite"`: иначе он существует только для зрячих. */

.toasts {
  position: fixed;
  left: 50%;
  bottom: 26px;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  z-index: 30;
  pointer-events: none;
  max-width: min(430px, 90vw);
}
.toast {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  background: var(--primary);
  color: var(--on-primary);
  padding: 12px 16px;
  border-radius: var(--r-3);
  font-size: 0.84rem;
  line-height: 1.45;
  box-shadow: var(--sh-2);
  border-left: 3px solid var(--ink-3);
  animation: toast-in 220ms var(--ease);
}
.toast.success {
  border-left-color: var(--positive-1);
}
.toast.error {
  border-left-color: var(--critical-1);
}
.toast.problem {
  border-left-color: var(--orange-1);
}
.toast.info {
  border-left-color: var(--blue-1);
}
@keyframes toast-in {
  from {
    opacity: 0;
    transform: translateY(14px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* ══ «Настроить экран» ════════════════════════════════════════════════════
   Косметические предпочтения одного человека: плотность, свёрнутая планка,
   какие блоки показывать и в каком порядке. Держатся в localStorage — на
   сервере им пока негде жить, шов описан в `ui.js`. */

.setup {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  width: min(340px, 92vw);
  background: var(--card);
  border-left: 1px solid var(--line);
  box-shadow: var(--sh-2);
  z-index: 40;
  display: flex;
  flex-direction: column;
  transform: translateX(100%);
  /* Закрытая панель невидима и для Tab: иначе фокус уходил в выдвинутую за
     край панель, и с клавиатуры страница «пропадала». */
  visibility: hidden;
  transition:
    transform 220ms var(--ease),
    visibility 0s 220ms;
}
.setup[aria-hidden="false"] {
  transform: none;
  visibility: visible;
  transition: transform 220ms var(--ease);
}
.setup-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 15px 18px;
  border-bottom: 1px solid var(--line);
}
.setup-body {
  overflow-y: auto;
  padding: var(--s-4) 18px 24px;
}
/* Label Category кита: Medium 11/14, uppercase, разрядка 6 %. */
.setup-cap {
  font-size: 0.786rem;
  line-height: 14px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-2);
  font-weight: 500;
  margin: var(--s-5) 0 var(--s-2);
}
.setup-cap:first-child {
  margin-top: 0;
}
/* Строка блока: тумблер кита слева, подпись, стрелки порядка справа. */
.setup-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 0;
  border-bottom: 1px solid var(--line-soft);
  font-size: var(--fs-2);
  line-height: 20px;
}
.setup-item .n {
  flex: 1;
  min-width: 0;
  overflow-wrap: anywhere;
}
.setup-item .mv {
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--ink-2);
  width: 28px;
  height: 28px;
  border-radius: var(--r-1);
  cursor: pointer;
  display: grid;
  place-items: center;
  padding: 0;
}
.setup-item .mv:hover {
  border-color: var(--gray-3);
  color: var(--ink);
}
.setup-item .mv[disabled] {
  opacity: 0.35;
  cursor: default;
}
.scrim {
  position: fixed;
  inset: 0;
  background: var(--scrim);
  z-index: 39;
}
.scrim[hidden] {
  display: none;
}
/* Образцы акцента. Кружок цвета плюс подпись: различать выбранный вариант
   только цветом нельзя — это и есть тот случай, когда цвет единственный
   носитель смысла. */
.swatches {
  display: flex;
  gap: var(--s-2);
  flex-wrap: wrap;
}
.swatch {
  border: 1px solid var(--line);
  background: var(--card);
  border-radius: var(--r-2);
  padding: 7px 10px 6px;
  cursor: pointer;
  font: inherit;
  font-size: 0.72rem;
  color: var(--ink-2);
  display: grid;
  gap: 5px;
  justify-items: center;
  min-width: 58px;
}
.swatch i {
  width: 100%;
  height: 12px;
  border-radius: 4px;
  background: var(--brand);
}
/* Каждый образец красится своим семейством, а не текущим `--brand`. Иначе на
   экране настроек, где предпросмотр переопределяет `--brand` на всю карточку,
   все пять образцов становились одного цвета — и выбрать было не из чего. */
.swatch[data-preview-accent="mint"] i,
.swatch[data-set-accent="mint"] i {
  background: var(--mint-1);
}
.swatch[data-preview-accent="green"] i,
.swatch[data-set-accent="green"] i {
  background: var(--green-1);
}
.swatch[data-preview-accent="blue"] i,
.swatch[data-set-accent="blue"] i {
  background: var(--blue-2);
}
.swatch[data-preview-accent="purple"] i,
.swatch[data-set-accent="purple"] i {
  background: var(--purple-2);
}
.swatch[data-preview-accent="orange"] i,
.swatch[data-set-accent="orange"] i {
  background: var(--orange-2);
}
.swatch[aria-pressed="true"] {
  border-color: var(--ink);
  color: var(--ink);
  font-weight: 600;
}

/* ══ Экраны входа ═════════════════════════════════════════════════════════
   Без планки и топбара: до входа показывать разделы нечего, а пустая планка
   рядом с формой обещает разделы, которых человек ещё не получил. */

.gate {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: var(--s-6) var(--s-4);
  background: var(--ground);
}
.gate-card {
  width: min(440px, 100%);
}
.gate-brand {
  display: flex;
  align-items: center;
  gap: 11px;
  margin-bottom: 22px;
}
.gate-brand .mark {
  width: 38px;
  height: 38px;
  border-radius: var(--r-3);
  font-size: 0.95rem;
}
.gate-brand b {
  display: block;
  font-family: var(--font-display);
  font-size: 1rem;
  font-weight: 700;
}
.gate-brand span {
  display: block;
  font-size: 0.76rem;
  color: var(--ink-3);
}
.gate .block-body {
  padding: 28px;
}
.gate h1 {
  margin-bottom: 4px;
}
.gate .lead {
  color: var(--ink-2);
  font-size: 0.88rem;
  margin: 0 0 20px;
}
.gate .foot {
  font-size: var(--fs-1);
  color: var(--ink-3);
  margin-top: 18px;
  line-height: 1.55;
}
.gate .foot a {
  color: var(--ink);
  font-weight: 600;
}

/* ══ Узкий экран ══════════════════════════════════════════════════════════
   Кабинет партнёра открывают с телефона (B6-01). Первый столбец уезжает вниз
   и становится панелью из трёх-пяти пунктов, второй прячется: подразделы
   есть в самой странице. Полотно получает отступ снизу, чтобы последняя
   строка не пряталась под панелью. */

@media (max-width: 1180px) {
  .me .who-name {
    display: none;
  }
  .me {
    padding-left: 8px;
  }
  .top-search {
    width: 170px;
  }
}

@media (max-width: 900px) {
  .shell,
  .shell[data-has-sub="1"],
  [data-sidebar="collapsed"] .shell,
  [data-sidebar="collapsed"] .shell[data-has-sub="1"] {
    grid-template-columns: 1fr;
  }
  .subrail {
    display: none;
  }
  /* Меню кита на телефоне: та же планка, но выезжает слева по гамбургеру
     и закрывается по затемнению. Ширина — как экран «Меню» кита на 360px,
     но не шире 320: полотно за ней должно оставаться видимым краем. */
  .rail {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    height: 100vh;
    height: 100dvh;
    width: min(320px, 88vw);
    z-index: 40;
    border-right: 1px solid var(--line);
    box-shadow: var(--sh-2);
    transform: translateX(-100%);
    visibility: hidden;
    transition:
      transform 220ms var(--ease),
      visibility 0s 220ms;
    padding-bottom: env(safe-area-inset-bottom, 0);
  }
  [data-menu="open"] .rail {
    transform: none;
    visibility: visible;
    transition: transform 220ms var(--ease);
  }
  [data-sidebar="collapsed"] .rail-me .who-name,
  [data-sidebar="collapsed"] .rail-pills,
  [data-sidebar="collapsed"] .nav-cap,
  [data-sidebar="collapsed"] .nav-item .lbl,
  [data-sidebar="collapsed"] .nav-item .cnt,
  [data-sidebar="collapsed"] .rail-foot .who-name,
  [data-sidebar="collapsed"] .rail-foot .signout .lbl {
    display: block;
  }
  [data-sidebar="collapsed"] .nav-item {
    justify-content: flex-start;
    padding: 8px 10px;
  }
  [data-sidebar="collapsed"] .nav-item .cnt {
    display: inline-flex;
  }
  [data-sidebar="collapsed"] .rail-me {
    flex-direction: row;
    padding: 12px 12px 10px 14px;
  }
  .rail-collapse {
    display: none;
  }
  .menu-scrim {
    position: fixed;
    inset: 0;
    background: var(--scrim);
    z-index: 39;
  }
  .menu-scrim[hidden] {
    display: none;
  }
  /* Шапка кита на телефоне: одна строка 60px — гамбургер, логотип с
     названием, иконки справа. Поиск и период, если они есть у экрана,
     занимают вторую строку целиком: в одну строку с иконками на 360px они
     не помещаются, а резать их нельзя. `display: contents` у правой группы
     нужен именно для этого переноса: иначе вся группа уезжала бы на вторую
     строку вместе с иконками. */
  .top {
    min-height: 60px;
    flex-wrap: wrap;
    padding: 8px 12px;
    gap: 6px;
  }
  .top-right {
    display: contents;
  }
  .top-menu {
    display: inline-flex;
    order: -3;
    min-width: 40px;
    min-height: 40px;
  }
  .top-brand {
    display: inline-flex;
    order: -2;
    margin-right: auto;
  }
  .crumbs,
  .me,
  .mobile-out {
    display: none;
  }
  .top-search {
    order: 9;
    flex-basis: 100%;
    width: auto;
  }
  .period {
    order: 10;
    flex-basis: 100%;
    justify-content: space-between;
  }
  .body {
    padding: 16px 14px 100px;
  }
  .top {
    padding: 0 14px;
    gap: 8px;
  }
  /* Подписи кнопок топбара уходят: на 375px «Настроить экран» рядом с
     колокольчиком, периодом и крошками не помещается, и лишнее уезжает за
     правый край вместе со всей страницей. Смысл кнопки остаётся в `title`
     и `aria-label`. */
  .top-btn .lbl {
    display: none;
  }
  .top-btn {
    padding: 8px;
    min-width: 40px;
    min-height: 40px;
    justify-content: center;
  }
  /* Кружок с инициалом на телефоне уступает место кнопке выхода: имя всё
     равно спрятано, и буква без имени ничего не сообщает. */
  .me .av {
    display: none;
  }
  .me {
    padding-left: 8px;
    border-left: 0;
  }
  /* Плитки — лентой с прокруткой и привязкой, как на телефоне у Everflow:
     четыре плитки столбиком отодвигают таблицу на второй экран, а таблица —
     то, ради чего человек открыл кабинет. */
  .pulse {
    display: flex;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    gap: 10px;
    margin: 0 -14px var(--gap-grid);
    padding: 0 14px 6px;
    -webkit-overflow-scrolling: touch;
  }
  .pulse .tile {
    flex: 0 0 min(78vw, 300px);
    scroll-snap-align: start;
  }
  .hello {
    font-size: 0.9rem;
  }
}

@media (max-width: 560px) {
  .k4 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .kpi {
    padding: 13px 14px 12px;
  }
  .kpi .v {
    font-size: 1.35rem;
  }
  .page-head {
    margin-bottom: 16px;
  }
  .crumbs .crumb-tail {
    display: none;
  }
  .rows > div {
    gap: 12px;
  }
  .form-inline .inp {
    min-width: 0;
    flex-basis: 100%;
  }
  .form-inline .btn {
    flex: 1;
  }
  .top-search {
    width: 100%;
  }
  .hero {
    padding: 18px;
  }
  .table-foot {
    justify-content: center;
  }
}

/* Уважение к настройке «меньше движения»: анимация здесь нигде не несёт
   смысла, который потерялся бы без неё. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 1ms !important;
    transition-duration: 1ms !important;
  }
}

/* Печать: планка, топбар и панель настройки на бумаге не нужны. Реестр
   выплат печатают — это единственный экран, который выносят из системы. */
@media print {
  .rail,
  .subrail,
  .top,
  .setup,
  .scrim,
  .toasts,
  .table-foot,
  .rowform,
  .act {
    display: none !important;
  }
  .shell,
  .shell[data-has-sub="1"] {
    grid-template-columns: 1fr;
  }
  .body {
    padding: 0;
  }
  .block {
    box-shadow: none;
    break-inside: avoid;
  }
}
