/* FinKontur 2 — базовые стили приложения (T20).
   Цвет, шрифт, отступы и тема — ЕДИНСТВЕННЫЙ источник:
   src/finkontur/app/static/tokens.css (I13, T90), подключённый в base.html
   раньше этого файла. Здесь — только структура и компоненты на семантических
   именах токенов; собственных цветов и переключения темы файл больше не несёт.
   Ручной переключатель темы (app.js) работает поверх tokens.css: без выбора —
   следует системной теме, data-theme="light"/"dark" на <html> — переопределяет. */

* { box-sizing: border-box; }

/* T128 (находка 1, отчёты T127/T132: «шапка шире экрана» на 768/360).
   `overflow-x: hidden` только на `body` не работает так, как кажется: по правилу
   распространения overflow с BODY на корень (CSS2.1 §11.1.1) браузер СЧИТАЕТ, что
   обрезает по горизонтали именно `html`, а `body` из этого правила становится
   `overflow: visible`. На страницах, которые скроллятся по вертикали, это путает
   вычисление containing block для `position: fixed; left:0; right:0` (нижняя панель,
   §см. `.bottom-nav` ниже) — их измеренная ширина оказывается на 10-15px больше
   реального вьюпорта, и именно эта ширина утекает в `document.documentElement.
   scrollWidth`, отчего кажется, что «поехала шапка». Правило нужно на ОБОИХ
   уровнях — `html` и `body` — чтобы браузеру не приходилось ничего домысливать. */
html { overflow-x: hidden; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: var(--fs-body)/var(--lh-body) var(--font-sans);
  -webkit-font-smoothing: antialiased;
  /* T56: строка не должна раздвигать страницу по горизонтали на телефоне — широкое
     содержимое (таблицы, графики, календарь) прокручивается ВНУТРИ своего контейнера
     (.table-scroll/.table-wrap/.tablewrap/.plot), сама страница — никогда. */
  overflow-x: hidden;
}

/* T92: каркас — шапка (topbar) во всю ширину сверху, ниже боковое меню (240px,
   .nav-menu) и содержимое рядом (docs/design/02-САЙТ-И-ЭКРАНЫ.md §1). Раньше
   .wrap был контейнером всей страницы (шапка+меню+контент), теперь это .app-shell,
   а .wrap — только паддинг содержимого (см. ниже, у main). */
.app-shell { display: flex; flex-direction: column; min-height: 100vh; }

.topbar {
  flex: none; height: var(--header-h); display: flex; align-items: center; gap: var(--space-4);
  padding: 0 var(--space-5); border-bottom: var(--border-w) solid var(--border);
  background: var(--surface); position: sticky; top: 0; z-index: var(--z-header);
}
.brand { display: flex; align-items: center; gap: var(--space-3); text-decoration: none; color: inherit; flex: none; }
.brand-mark {
  display: flex; align-items: center; justify-content: center; width: 32px; height: 32px;
  border-radius: var(--radius-md); background: var(--model); color: var(--on-brand);
  font-weight: var(--fw-semibold); font-size: var(--fs-body); flex: none;
}
.brand-text { display: flex; flex-direction: column; line-height: 1.2; }
.brand-name { font-size: var(--fs-small); font-weight: var(--fw-semibold); }
.brand-text .sub { color: var(--text-muted); font-size: var(--fs-caption); }

.topbar-actions { margin-left: auto; display: flex; align-items: center; gap: var(--space-2); }

.topbar-chip, .icon-btn {
  display: flex; align-items: center; gap: var(--space-1);
  height: var(--control-h); padding: 0 var(--space-3); border-radius: var(--radius-md);
  border: var(--border-w) solid var(--border); background: var(--surface); color: var(--text);
  text-decoration: none; cursor: pointer; font: inherit; font-size: var(--fs-small);
}
.icon-btn { width: var(--control-h); padding: 0; justify-content: center; }
.topbar-chip:hover, .icon-btn:hover { border-color: var(--brand); }

/* T56: гамбургер — скрытый чекбокс + подпись-кнопка. Видимы только на узком экране
   (см. @media 767px ниже, T94 — было 480px); на 1280px не участвуют в раскладке. Чекбокс — сосед
   .app-shell (см. base.html), а не потомок — раскрывает .nav-menu общим селектором
   без единой строки JS (":checked ~ .app-shell .nav-menu" ниже). */
/* T128 (сквозная проверка, Tab с самого начала страницы на 1440/1024): чекбокс
   гамбургера раньше оставался в порядке табуляции и на широком экране, где его
   кнопка-лейбл `display: none` — первый же Tab уводил фокус на невидимый 0×0
   элемент без всякого визуального следа. `display: none` здесь и `display: block`
   в паре с `.nav-toggle-btn { display: flex }` внутри мобильного `@media` ниже
   убирают чекбокс из табуляции ровно там, где не видна и сама кнопка. */
.nav-toggle-checkbox { position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none; display: none; }
.nav-toggle-btn {
  display: none; width: var(--control-h); height: var(--control-h); border-radius: var(--radius-md);
  border: var(--border-w) solid var(--border); background: var(--surface); color: var(--text);
  cursor: pointer; align-items: center; justify-content: center; flex: none;
}
.nav-toggle-btn:hover { border-color: var(--brand); }

/* Меню пользователя и переключатель компании (topbar-chip выше) — без JS:
   <details>/<summary>, клавиатура и Esc — нативное поведение браузера. */
.user-menu { position: relative; }
.user-summary {
  display: flex; align-items: center; gap: var(--space-2); list-style: none; cursor: pointer;
  height: var(--control-h); padding: 0 var(--space-2) 0 0; border-radius: var(--radius-md);
}
.user-summary::-webkit-details-marker { display: none; }
.user-summary:hover { background: var(--surface-2); }
.user-avatar {
  display: flex; align-items: center; justify-content: center; width: 28px; height: 28px;
  border-radius: 50%; background: var(--surface-2); color: var(--text); font-size: var(--fs-small);
  font-weight: var(--fw-semibold); border: 2px solid var(--text-muted); flex: none;
}
/* Кольцо цвета по уровню доступа (докс §2): оператор — модель, руководитель
   компании — бренд, руководитель отдела — зелёный, исполнитель — приглушённый.
   Роль всегда подписана словом рядом (.user-menu-role) — кольцо вспомогательное. */
.nav-role-operator { border-color: var(--model); }
.nav-role-management { border-color: var(--brand); }
.nav-role-supervisor { border-color: var(--c-green-500); }
.nav-role-executor { border-color: var(--text-muted); }
.user-name { font-size: var(--fs-small); font-weight: var(--fw-medium); white-space: nowrap; }
.user-menu-panel {
  position: absolute; right: 0; top: calc(100% + var(--space-2)); min-width: 220px;
  background: var(--surface); border: var(--border-w) solid var(--border); border-radius: var(--radius-md);
  box-shadow: var(--shadow-2); padding: var(--space-3); z-index: var(--z-sticky);
}
.user-menu-role { font-size: var(--fs-small); color: var(--text-muted); margin-bottom: var(--space-2); }
.user-menu-logout {
  display: flex; align-items: center; gap: var(--space-2); width: 100%;
  font: inherit; font-size: var(--fs-small); color: var(--text); background: none;
  border: var(--border-w) solid var(--border); border-radius: var(--radius-sm); padding: var(--space-2) var(--space-3);
  cursor: pointer;
}
.user-menu-logout:hover { border-color: var(--neg); color: var(--neg); }
.nav-logout-form { margin: 0; }

/* Боковое меню — 240px (--sidebar-w, LG/XL), группы в фиксированном порядке
   «Смотреть → Вносить → Обмен → Платформа» (§3). До 768px (XS/SM) сворачивается
   целиком за гамбургер, на 768–1023 (MD) — сжимается в иконки (T94, media ниже). */
.nav-menu {
  display: block; flex: none; width: var(--sidebar-w);
  border-right: var(--border-w) solid var(--border); background: var(--surface);
}
.sidebar { display: flex; flex-direction: column; gap: var(--nav-group-gap); padding: var(--space-4) var(--space-3); }
.sidebar-group { display: flex; flex-direction: column; gap: 2px; }
.sidebar-group-title {
  font-size: var(--fs-caption); font-weight: var(--fw-medium); color: var(--text-faint);
  text-transform: uppercase; letter-spacing: .04em; padding: 0 var(--space-2); margin-bottom: 2px;
}
.sidebar-link {
  display: flex; align-items: center; gap: var(--space-2); height: var(--nav-item-h);
  padding: 0 var(--space-2); border-radius: var(--nav-item-radius); color: var(--nav-item-color);
  text-decoration: none; font-size: var(--fs-small);
}
.sidebar-link:hover { background: var(--surface-2); color: var(--text); }
.sidebar-link-active { background: var(--nav-item-bg-active); color: var(--nav-item-color-active); font-weight: var(--fw-medium); }
/* §5/§2.1 «заблокировано состоянием»: пункт остаётся на месте, но выключен и
   называет причину (title) — не путать с «роли нет», когда пункта нет вовсе. */
.sidebar-link-disabled { opacity: .55; cursor: not-allowed; }
.sidebar-status { padding: var(--space-3); border-top: var(--border-w) solid var(--border); font-size: var(--fs-caption); color: var(--text-muted); }
.sidebar-status-day { display: flex; align-items: center; gap: var(--space-1); }

/* T126 (§11.1/§11.2, 01/02): раскрывающаяся группа «Направления» в боковом меню —
   `<details open>` без JS, сворачивается вручную при большом числе направлений. */
.sidebar-directions { display: flex; flex-direction: column; }
.sidebar-directions > summary {
  list-style: none; cursor: pointer; height: var(--nav-item-h);
  display: flex; align-items: center; padding: 0 var(--space-2);
  font-size: var(--fs-caption); font-weight: var(--fw-medium); color: var(--text-faint);
  text-transform: uppercase; letter-spacing: .04em; border-radius: var(--nav-item-radius);
}
.sidebar-directions > summary::-webkit-details-marker { display: none; }
.sidebar-directions > summary:hover { background: var(--surface-2); }
.sidebar-directions-list { display: flex; flex-direction: column; gap: 2px; }
.sidebar-separator { border: none; border-top: var(--border-w) solid var(--border); margin: var(--space-2) var(--space-2); }

/* T94: нижняя панель — XS/SM (§8 адаптива, до 767px). Скрыта по умолчанию (LG/XL,
   MD), включается ровно там же, где боковое меню уходит за гамбургер (см. media
   ниже) — на этих ширинах постоянного меню нет вовсе, а не два меню разом.
   Состав и порядок — nav.NavResult.flat_items(), первые пять + «Ещё» (base.html). */
.bottom-nav {
  display: none;
  position: fixed; left: 0; right: 0; bottom: 0; z-index: var(--z-sticky);
  height: var(--bottom-nav-h);
  align-items: stretch; justify-content: space-around;
  /* T128 (сквозная проверка, найдено на 360 при 6 пунктах панели): без зазора
     подписи соседних пунктов ellipsis-обрезаются вплотную друг к другу и читаются
     слитно («МагазинГруми...») — узкий зазор токеном разводит подписи и не ломает
     распределение space-around. */
  gap: var(--space-1);
  background: var(--surface); border-top: var(--border-w) solid var(--border);
  padding-bottom: env(safe-area-inset-bottom);
}
.bottom-nav-item {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 2px; flex: 1 1 0; min-width: 0; min-height: 44px;
  color: var(--nav-item-color); text-decoration: none; font-size: var(--fs-caption);
  padding: var(--space-1) 0; border: none; background: none; font: inherit; cursor: pointer;
}
.bottom-nav-item span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bottom-nav-item:hover, .bottom-nav-item:focus-visible { color: var(--text); background: var(--surface-2); }
.bottom-nav-item-active { color: var(--nav-item-color-active); }
.bottom-nav-item-disabled { opacity: .55; cursor: not-allowed; }
.bottom-nav-more { position: relative; flex: 1 1 0; min-width: 0; }
.bottom-nav-more > summary { list-style: none; }
.bottom-nav-more > summary::-webkit-details-marker { display: none; }
.bottom-nav-more-panel {
  position: absolute; right: 0; bottom: calc(100% + var(--space-2)); min-width: 220px;
  max-height: 60vh; overflow-y: auto; display: flex; flex-direction: column; gap: 2px;
  background: var(--surface-raised); border: var(--border-w) solid var(--border);
  border-radius: var(--radius-md); box-shadow: var(--shadow-2); padding: var(--space-2);
}
.bottom-nav-more-link {
  display: flex; align-items: center; gap: var(--space-2); min-height: 44px;
  padding: 0 var(--space-2); border-radius: var(--radius-sm); color: var(--text);
  text-decoration: none; font-size: var(--fs-small);
}
.bottom-nav-more-link:hover, .bottom-nav-more-link:focus-visible { background: var(--surface-2); }
.bottom-nav-more-link-active { background: var(--nav-item-bg-active); color: var(--nav-item-color-active); font-weight: var(--fw-medium); }
.bottom-nav-more-link-disabled { opacity: .55; cursor: not-allowed; }

/* Ряд «боковое меню + содержимое» под шапкой — .app-shell сам колонка (шапка
   сверху), а этот ряд внутри неё раскладывает .nav-menu и .shell-main рядом,
   а не друг под другом (была ошибка первой версии, найдено визуальной
   проверкой T92 — см. отчёт). */
.shell-body { display: flex; flex: 1 1 auto; align-items: stretch; min-height: 0; }
.shell-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }

.breadcrumbs { padding: var(--space-3) var(--space-6) 0; font-size: var(--fs-small); color: var(--text-muted); }
.breadcrumbs:empty { display: none; padding: 0; }
.breadcrumbs a { color: inherit; }

.page-header {
  display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-4);
  padding: var(--space-4) var(--space-6) 0;
}
/* Пусто, пока страница не объявит свой блок page_title — экраны переносятся сюда
   постепенно (T95/T96), до тех пор всей области не должно быть видно. */
.page-header:has(.page-title:empty) { display: none; }
.page-title { font-size: var(--fs-h1); line-height: var(--lh-h1); font-weight: var(--fw-semibold); margin: 0; }
.page-subtitle { color: var(--text-muted); font-size: var(--fs-small); margin-top: var(--space-1); }
.page-actions { display: flex; gap: var(--space-3); flex: none; }

/* T128 (сквозная проверка, §8 правило 1 — страница не прокручивается по
   горизонтали ни на одном экране): `overflow-x: hidden` здесь — не раскладка
   конкретного экрана, а страховка самого правила. Найдена конкретная причина
   (крупный ползунок периода §6.13 на 05 «Взаиморасчёты»: невидимая тап-цель
   ручки `--slider-hit` 44px шире видимой ручки `--slider-handle` и высовывалась
   за край на узких экранах без обёртки-карточки) — чинить только её было бы
   починкой одного экрана, а не правила; внутренние прокручиваемые ряды
   (`.dir-tabs`, `.dt-scroll`, `.ch-seg`, `.manual-chips` — у каждого свой
   `overflow-x: auto`) продолжают прокручиваться сами, это их не касается. */
.wrap { max-width: none; margin: 0 auto; padding: var(--space-6); width: 100%; overflow-x: hidden; }

main { flex: 1; }

.card {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-md);
  padding: 22px var(--space-5); margin-bottom: 18px; max-width: 640px;
}
.card h2 { font-size: var(--fs-h3); margin: var(--space-2) 0 var(--space-2); letter-spacing: -.01em; }
.card .hint { color: var(--text-muted); font-size: var(--fs-small); margin: 0 0 14px; }
.card a { color: var(--series-fact); text-decoration: none; }
.card a:hover { text-decoration: underline; }
.card-error { border-color: var(--neg); }
.hint-spaced { margin-top: 14px; }

/* Вкладки «Настройки» (T93, дополнены T132) — партиал templates/settings/_tabs.html
   поверх экранов настройки (компания, направления, источники, потоки данных, сигналы,
   пользователи, подписка, пароль; вкладка Telegram снесена T155). T132: один ряд —
   на узком экране полоса прокручивается сама (§6.10 01-ДИЗАЙН-СИСТЕМА.md), страница
   по горизонтали не прокручивается никогда (02-САЙТ-И-ЭКРАНЫ.md §8, правило 1). */
.settings-tabs {
  display: flex; flex-wrap: nowrap; overflow-x: auto; gap: var(--space-1); margin-bottom: 18px;
  border-bottom: 1px solid var(--border);
}
.settings-tab {
  padding: var(--space-2) var(--space-3); color: var(--text-muted); text-decoration: none;
  border-bottom: 2px solid transparent; margin-bottom: -1px; white-space: nowrap; flex: none;
}
.settings-tab:hover { color: var(--text); }
.settings-tab-active { color: var(--series-fact); border-bottom-color: var(--series-fact); font-weight: 600; }

.pill {
  display: inline-block; padding: 3px 10px; border-radius: var(--radius-full); font-size: var(--fs-caption);
  border: 1px solid var(--border); color: var(--text-muted); margin: 0 0 10px;
}
.pill-ok { color: var(--pos); border-color: var(--pos); }
.pill-warn { color: var(--neg); border-color: var(--neg); }
.pill-info { color: var(--series-fact); border-color: var(--series-fact); }

/* T55: строка просроченного платежа в реестре «Предстоящие платежи». */
tr.row-danger { background: color-mix(in srgb, var(--neg) 10%, transparent); }

footer {
  color: var(--text-muted); font-size: var(--fs-caption); margin-top: 28px; padding-top: var(--space-4);
  border-top: 1px solid var(--border); padding-left: var(--space-6); padding-right: var(--space-6);
}

/* Формы (вход, компании, приглашение, смена пароля — T21). */
.stack-form { display: flex; flex-direction: column; gap: 14px; max-width: 360px; }
.field { display: flex; flex-direction: column; gap: 6px; font-size: var(--fs-small); color: var(--text-muted); }
.field input {
  font: inherit; font-size: var(--fs-body); color: var(--text); background: var(--bg);
  border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 9px var(--space-3);
}
/* T128 (находка 2, отчёты T127/T132): `outline: none` здесь снимал кольцо фокуса
   §5 не только с этого поля, но и глобально перебивал `:focus-visible` из
   tokens.css (та же специфичность, этот файл подключён позже) — фокус клавиатурой
   переставал быть видимым на ВСЕХ полях и чекбоксах сайта. Кольцо снимать нельзя;
   меняем только рамку, чтобы поле выглядело активным и без фокуса с мыши. */
.field input:focus { border-color: var(--series-fact); }
.btn {
  font: inherit; font-size: var(--fs-small); color: var(--text); background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius-md); padding: 9px var(--space-4); cursor: pointer;
}
.btn:hover { border-color: var(--series-fact); }
.btn-primary { color: var(--c-white); background: var(--model); border-color: var(--model); }
.btn-primary:hover { opacity: .92; border-color: var(--model); }
.form-error {
  color: var(--neg); background: var(--series-gap); border: 1px solid var(--neg);
  border-radius: var(--radius-md); padding: 10px 14px; font-size: var(--fs-small); margin: 0 0 14px;
}

.company-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.company-row {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  padding: var(--space-3) var(--space-4); border: 1px solid var(--border); border-radius: var(--radius-md);
}
.company-row-current { border-color: var(--series-fact); }
.company-row .hint { display: block; margin: 2px 0 0; }

/* Журнал операций (T22b): список, карточка операции, фильтры, модалка сторно. */
.card-wide { max-width: none; }

.filter-form {
  display: flex; flex-wrap: wrap; gap: var(--space-3) var(--space-4); align-items: flex-end; margin-bottom: 18px;
}
.field-inline { min-width: 140px; }
.field-inline input, .field-inline select {
  font: inherit; font-size: var(--fs-small); color: var(--text); background: var(--bg);
  border: 1px solid var(--border); border-radius: var(--radius-sm); padding: var(--space-2) 10px; width: 100%;
}

/* T102: селектор колонок журнала — тот же приём <details>/<summary> без JS, что
   у .user-menu (клавиатура и Esc — поведение браузера). */
.columns-picker { position: relative; margin-bottom: 18px; }
.columns-picker > summary { list-style: none; }
.columns-picker > summary::-webkit-details-marker { display: none; }
.columns-picker-panel {
  position: absolute; left: 0; top: calc(100% + var(--space-2)); min-width: 280px; max-width: 420px;
  background: var(--surface); border: var(--border-w) solid var(--border); border-radius: var(--radius-md);
  box-shadow: var(--shadow-2); padding: var(--space-3); z-index: var(--z-sticky);
}
.columns-picker-grid {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-2) var(--space-3);
  margin-bottom: var(--space-3);
}
.columns-picker-panel .field-checkbox { font-size: var(--fs-small); }

.table-scroll { overflow-x: auto; }
/* T102: журнал широкий — колонок может быть под два десятка, страница выше "Найдено"
   уже не помещается на экран целиком. Вертикальная прокрутка своя (не страницы, I13
   §8 правило 1), поэтому липкая шапка (`thead th { position: sticky }`) стоит
   относительно СВОЕГО контейнера, не топбара — офсет считать не нужно. */
.table-scroll-sticky { max-height: 70vh; overflow-y: auto; }
.table-scroll-sticky thead th { position: sticky; top: 0; z-index: 1; }
.journal-table { width: 100%; border-collapse: collapse; font-size: var(--fs-small); white-space: nowrap; }
.journal-table th, .journal-table td { padding: 9px var(--space-3); border-bottom: 1px solid var(--border); text-align: left; }
.journal-table th { color: var(--text-muted); font-weight: 600; font-size: var(--fs-caption); text-transform: uppercase; letter-spacing: .02em; background: var(--surface); }
.journal-table th.num { text-align: right; }
.journal-table tbody tr:hover { background: var(--series-gap); }
.journal-table td.num { text-align: right; font-variant-numeric: tabular-nums; }
.journal-table a { color: var(--text); text-decoration: none; font-weight: 600; }
.journal-table a:hover { color: var(--series-fact); text-decoration: underline; }

.pagination { display: flex; gap: 10px; margin-top: var(--space-4); }

.op-meta { display: grid; grid-template-columns: max-content 1fr; gap: 6px var(--space-4); margin: 14px 0; font-size: var(--fs-small); }
.op-meta dt { color: var(--text-muted); }
.op-meta dd { margin: 0; }

.line-table { width: 100%; border-collapse: collapse; font-size: var(--fs-small); margin: 10px 0 18px; }
.line-table th, .line-table td { padding: 7px 10px; border-bottom: 1px solid var(--border); text-align: left; }
.line-table td.num { text-align: right; font-variant-numeric: tabular-nums; }
.line-table th { color: var(--text-muted); font-weight: 600; font-size: var(--fs-caption); }

.op-actions { display: flex; flex-wrap: wrap; gap: 10px; margin: 18px 0 6px; }
.btn-danger { color: var(--c-white); background: var(--neg); border-color: var(--neg); }
.btn-danger:hover { opacity: .9; }

dialog {
  border: 1px solid var(--border); border-radius: var(--radius-lg); padding: 22px var(--space-5);
  background: var(--surface); color: var(--text); max-width: 420px; width: 90vw;
}
dialog::backdrop { background: var(--overlay); }
dialog h3 { margin: 0 0 14px; font-size: var(--fs-h3); }
dialog textarea {
  font: inherit; font-size: var(--fs-small); color: var(--text); background: var(--bg);
  border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 9px var(--space-3); resize: vertical; min-height: 70px;
}
.dialog-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: var(--space-1); }

/* Баннер подписки (T61) — под шапкой, на каждой странице (base.html). Нейтральный
   вид для «пробный период скоро закончится», тревожный — для read_only. */
.subscription-banner {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  flex-wrap: wrap; padding: 10px 18px; margin: -8px 0 20px; border-radius: var(--radius-md);
  background: var(--series-gap); color: var(--text); font-size: var(--fs-small);
  border: 1px solid var(--series-fact);
}
.subscription-banner a { color: inherit; font-weight: 600; white-space: nowrap; }
.subscription-banner-danger {
  background: color-mix(in srgb, var(--neg) 12%, transparent);
  border-color: var(--neg);
}

/* Список подписок оператора и карточка подписки клиента (T61). */
.subscription-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 14px; }
.subscription-row {
  border: 1px solid var(--border); border-radius: var(--radius-md); padding: 14px 18px;
}
.subscription-row-head {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  flex-wrap: wrap; margin-bottom: var(--space-2);
}
.subscription-row-head h3 { margin: 0; font-size: var(--fs-h3); }
.subscription-facts { color: var(--text-muted); font-size: var(--fs-small); margin: 0 0 10px; }
.subscription-actions { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-4); align-items: flex-end; }
.mini-form {
  display: flex; align-items: flex-end; gap: 6px; flex-wrap: wrap;
  padding: var(--space-2) 10px; border: 1px dashed var(--border); border-radius: var(--radius-sm);
}
.mini-form .field { gap: 3px; }
.mini-form .field input, .mini-form .field select {
  font: inherit; font-size: var(--fs-small); color: var(--text); background: var(--bg);
  border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 6px var(--space-2); width: 130px;
}
.mini-form .btn { padding: 6px var(--space-3); font-size: var(--fs-small); }

.data-table { width: 100%; border-collapse: collapse; font-size: var(--fs-small); margin: var(--space-2) 0; }
.data-table th, .data-table td { text-align: left; padding: 7px 10px; border-bottom: 1px solid var(--border); }
.data-table th { color: var(--text-muted); font-weight: 600; font-size: var(--fs-caption); text-transform: uppercase; letter-spacing: .03em; }

/* ============================================================
   T94: пять точек перелома (docs/design/02-САЙТ-И-ЭКРАНЫ.md §8).

     XS  ≤479          — одна колонка, нижняя панель вместо бокового меню,
                          таблицы → карточки, поля на всю ширину.
     SM  480–767        — тот же каркас, что XS (бокового меню ещё нет —
                          ему просто нет места до 768px), плюс отдельные
                          послабления шапки/карточек, общие для XS и SM.
     MD  768–1023       — боковое меню остаётся, но сжимается в 56px
                          иконок с подписью по наведению/фокусу.
     LG  1024–1439      — база файла без media ниже: полный каркас §1,
                          меню 240px. Ничего не переопределяется — карточка
                          прямо требует «на 1280 — как раньше».
     XL  ≥1440          — содержимое области 5 ограничено 1440px и
                          центрируется, ширина бокового меню не меняется.

   Общие для XS+SM правила — первым блоком (max-width: 767px), из него
   гамбургер сворачивает .nav-menu целиком (постоянного меню ещё нет) и
   включается нижняя панель. Правила, специфичные только для XS
   (одна колонка, таблицы-карточки), — вторым блоком (max-width: 479px). */
@media (max-width: 767px) {
  .topbar { flex-wrap: wrap; height: auto; padding: var(--space-2) var(--space-4); }
  .brand-text .sub { display: none; }
  .topbar-chip span { display: none; }
  /* T128 (сквозная проверка): полное имя + роль в одной строке без переноса
     (`.user-name`, ФИО демо-данных длиннее «Кузьмин Артём» — несёт ещё и роль
     через запятую) раздвигало .topbar-actions за 360px на любом экране —
     роль и так подписана в открытой панели (.user-menu-role), прячем то же
     самое, что и подпись .topbar-chip выше. */
  .user-name { display: none; }
  .filter-form { flex-direction: column; align-items: stretch; }
  .subscription-banner { margin-top: 0; }

  /* T126 (находка T130a, §11.4): .page-actions { flex: none } не давал действиям
     сжаться — на 360px переключатель периода и главная кнопка вылезали за край
     экрана. Заголовок переносится, действия уходят под него во всю ширину и
     сами переносятся (§8 правило 1 — страница не прокручивается по горизонтали). */
  .page-header { flex-wrap: wrap; }
  .page-actions { flex: 1 1 100%; flex-wrap: wrap; }

  /* T102: на XS/SM таблица уже стала карточками (thead скрыт вторым блоком
     ниже) — своя вертикальная прокрутка внутри 70vh неуместна, страница
     обязана прокручиваться целиком, как остальной контент. */
  .table-scroll-sticky { max-height: none; overflow-y: visible; }

  .nav-toggle-checkbox { display: block; }
  .nav-toggle-btn { display: flex; }
  .nav-menu {
    display: none; width: 100%; border-right: none;
    position: fixed; top: var(--header-h); left: 0; right: 0; bottom: 0;
    z-index: var(--z-sticky); overflow-y: auto;
  }
  .nav-toggle-checkbox:checked ~ .app-shell .nav-menu { display: block; }
  .sidebar-link { height: auto; padding: var(--space-3) var(--space-2); }

  /* T94, §8 правило 5: постоянного бокового меню на этой ширине нет —
     нижняя панель встаёт на его место (не поверх), первые пять пунктов
     nav.NavResult.flat_items(), остальное — «Ещё» (base.html). */
  .bottom-nav { display: flex; }
  .wrap { padding-bottom: calc(var(--bottom-nav-h) + var(--space-4)); }

  .card, .card-wide { padding: 14px; }
  .stack-form, .stack-form.stack-form-wide { max-width: 100%; }
  .field-row { flex-direction: column; gap: 10px; }
  .mini-form .field input, .mini-form .field select { width: 100%; }

  .op-meta, dl.def-list { grid-template-columns: 1fr; }
  .op-meta dt { margin-top: 6px; }

  .wizard-layout { flex-direction: column; }
  .wizard-nav { flex-direction: row; flex-wrap: wrap; min-width: 0; }

  dialog { padding: var(--space-4); }

  /* T94, §8 правило 2/4: липкая панель действий формы (сейчас единственная —
     журнал/операция, .op-actions) прижата к низу видимой области над нижней
     панелью, а не под ней; sticky (не fixed) — при открытой клавиатуре
     мобильный браузер продолжает считать её частью потока страницы, а не
     элементом, который надо прятать вместе со сдвинутым вьюпортом. */
  .op-actions {
    position: sticky; bottom: var(--bottom-nav-h); z-index: var(--z-sticky);
    background: var(--surface); border-top: var(--border-w) solid var(--border);
    margin: var(--space-4) -14px 0; padding: var(--space-3) 14px;
  }
}

/* XS (≤479) — то, что специфично именно для одной колонки: плитки и таблицы. */
@media (max-width: 479px) {
  .wrap { padding-left: var(--space-3); padding-right: var(--space-3); }
  .topbar { padding: 0 var(--space-3); gap: var(--space-2); }

  /* Плитки (пульт, «Где деньги») и карточки справочников — в столбик, а не
     auto-fit «на удачу». */
  .ref-grid { grid-template-columns: 1fr; }
  /* T102: селектор колонок — в столбик и во всю доступную ширину, не 280px. */
  .columns-picker-grid { grid-template-columns: 1fr; }
  .columns-picker-panel { min-width: 0; max-width: none; width: 100%; }

  /* T94, §8 правило 6: таблица → карточки. Строка становится карточкой:
     первая колонка — заголовок (жирным, без подписи), остальные — парами
     «подпись: значение» через data-label (registers/*.html — заведён;
     .journal-table используют и registers/*, и templates/journal/_table.html
     — у второго data-label появится вместе с переводом на компоненты §6,
     T95/docs/design/02-САЙТ-И-ЭКРАНЫ.md §10; без атрибута строка всё равно
     складывается в карточку, просто без подписи перед значением, не ломаясь. */
  .journal-table, .data-table, table.ref-table, .line-table { display: block; width: 100%; }
  .journal-table thead, .data-table thead, table.ref-table thead, .line-table thead { display: none; }
  .journal-table tbody, .data-table tbody, table.ref-table tbody, .line-table tbody { display: block; }
  .journal-table tr, .data-table tr, table.ref-table tr, .line-table tr {
    display: block; border: var(--border-w) solid var(--border); border-radius: var(--radius-md);
    padding: var(--space-3); margin-bottom: var(--space-3); background: var(--surface);
  }
  .journal-table td, .data-table td, table.ref-table td, .line-table td {
    display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-3);
    padding: var(--space-1) 0; border-bottom: none; white-space: normal; text-align: left;
  }
  .journal-table td.num, .data-table td.num, table.ref-table td.num, .line-table td.num { text-align: right; }
  .journal-table td:first-child, .data-table td:first-child,
  table.ref-table td:first-child, .line-table td:first-child {
    font-weight: var(--fw-semibold); font-size: var(--fs-body); color: var(--text);
    justify-content: flex-start;
  }
  .journal-table td[data-label]::before, .data-table td[data-label]::before,
  table.ref-table td[data-label]::before, .line-table td[data-label]::before {
    content: attr(data-label); color: var(--text-muted); font-weight: var(--fw-regular); flex: none;
  }
  table.ref-table td.ref-row-actions { justify-content: flex-end; margin-top: var(--space-2); }
}

/* MD (768–1023) — боковое меню сжимается в иконки; подпись — тем же текстом,
   что и на LG (span в разметке не дублируется), всплывает по наведению или
   фокусу клавиатурой, а не пропадает из DOM (доступна читалке экрана всегда). */
@media (min-width: 768px) and (max-width: 1023px) {
  .nav-menu { width: var(--sidebar-w-md); }
  .sidebar { padding: var(--space-4) var(--space-1); align-items: center; }
  .sidebar-group-title, .sidebar-directions-summary { display: none; }
  .sidebar-link {
    position: relative; justify-content: center; width: 44px; height: 44px;
    padding: 0; margin: 0 auto;
  }
  .sidebar-link span {
    position: absolute; left: calc(100% + var(--space-2)); top: 50%; transform: translateY(-50%);
    background: var(--surface-raised); color: var(--text); border: var(--border-w) solid var(--border);
    border-radius: var(--radius-sm); padding: var(--space-1) var(--space-2);
    font-size: var(--fs-small); white-space: nowrap; box-shadow: var(--shadow-2);
    opacity: 0; visibility: hidden; pointer-events: none;
    transition: opacity var(--dur-fast) var(--ease-out); z-index: var(--z-sticky);
  }
  .sidebar-link:hover span, .sidebar-link:focus-visible span { opacity: 1; visibility: visible; }
  .sidebar-status { display: flex; flex-direction: column; align-items: center; gap: var(--space-1); padding: var(--space-2); }
  .sidebar-status-day span { display: none; }
}

/* XL (≥1440) — содержимое области 5 не растёт дальше 1440px и центрируется;
   ширина бокового меню (LG-база выше) не меняется, свободное место уходит
   по бокам от таблиц/графиков, а не в поля форм (у форм свой max-width). */
@media (min-width: 1440px) {
  .wrap, .breadcrumbs, .page-header, footer {
    max-width: var(--content-max); margin-left: auto; margin-right: auto;
  }
}

/* Справочники (T25) — обзорные карточки, тулбар списка, таблицы, инлайн-формы. */
.ref-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 14px; max-width: none;
}
.ref-tile {
  display: block; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-md);
  padding: var(--space-4) 18px; text-decoration: none; color: inherit;
}
.ref-tile:hover { border-color: var(--series-fact); }
.ref-tile .ref-tile-count { font-size: var(--fs-kpi); font-weight: 700; letter-spacing: -.02em; }
.ref-tile .ref-tile-title { color: var(--text-muted); font-size: var(--fs-small); margin-top: 2px; }

.ref-toolbar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-bottom: 14px;
}
.ref-toolbar input[type="search"] {
  font: inherit; font-size: var(--fs-small); color: var(--text); background: var(--bg);
  border: 1px solid var(--border); border-radius: var(--radius-sm); padding: var(--space-2) var(--space-3); min-width: 220px; flex: 1;
}
.ref-toolbar label.ref-toggle {
  display: flex; align-items: center; gap: 6px; font-size: var(--fs-small); color: var(--text-muted);
  white-space: nowrap;
}
.ref-toolbar .ref-spacer { flex: 1 1 auto; }

.table-wrap { overflow-x: auto; border: 1px solid var(--border); border-radius: var(--radius-md); }
table.ref-table { width: 100%; border-collapse: collapse; font-size: var(--fs-small); white-space: nowrap; }
table.ref-table th, table.ref-table td {
  padding: 9px 14px; text-align: left; border-bottom: 1px solid var(--border);
}
table.ref-table th { color: var(--text-muted); font-weight: 600; font-size: var(--fs-caption); }
table.ref-table tbody tr:last-child td { border-bottom: none; }
table.ref-table tbody tr:hover { background: var(--series-gap); }
table.ref-table td.ref-row-actions { text-align: right; white-space: nowrap; }
table.ref-table .btn { padding: 5px 10px; font-size: var(--fs-small); }

.ref-inactive-row { opacity: .6; }
.ref-empty { padding: 22px; text-align: center; color: var(--text-muted); }

.ref-form-panel { margin-top: 14px; max-width: 520px; }
.ref-form-panel:empty { margin-top: 0; }

/* v0.27.1: широкие карточки — на всю ширину страницы (правило 760px из T25 отменено). */
.card-wide { max-width: none; }
.stack-form.stack-form-wide { max-width: 100%; }
.field-row { display: flex; gap: 14px; flex-wrap: wrap; }
.field-row > .field { flex: 1 1 200px; }
.field-checkbox { flex-direction: row !important; align-items: center; gap: var(--space-2) !important; }
.field-checkbox input { width: auto; }

.recipe-lines-table input[type="number"] { width: 100px; }
.recipe-lines-table select { min-width: 200px; }

.detail-actions { display: flex; gap: var(--space-2); margin: 14px 0; flex-wrap: wrap; }
dl.def-list { display: grid; grid-template-columns: max-content 1fr; gap: 6px var(--space-4); margin: 0; }
dl.def-list dt { color: var(--text-muted); font-size: var(--fs-small); }
dl.def-list dd { margin: 0; }

/* Формы операций (T30a): выбор типа, шапка, строки, подсказки, ошибки по строкам.
   .field select/textarea не были стилизованы раньше (T20/T25 форм со select внутри
   .field почти не имели) — здесь их много, дополняем правило .field input. */
.field select, .field textarea {
  font: inherit; font-size: var(--fs-body); color: var(--text); background: var(--bg);
  border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 9px var(--space-3);
}
.field select:focus, .field textarea:focus { border-color: var(--series-fact); }

.error-list { margin: 6px 0 0; padding-left: 20px; }
.error-list li { margin: 2px 0; }

.lines-editable select { min-width: 190px; font-size: var(--fs-small); }
.lines-editable .num-input { width: 110px; }
.lines-editable .unit-input { width: 80px; }
.lines-editable td { vertical-align: top; }
.line-remove-cell { width: 1%; white-space: nowrap; }
.line-remove { padding: 5px 10px; line-height: 1; }
.line-add-btn { margin: var(--space-1) 0 20px; }
tr.row-error td {
  color: var(--neg); font-size: var(--fs-small); padding: var(--space-1) 10px 10px; border-bottom: 1px solid var(--border);
}

.field-hint { margin-top: var(--space-1); }
.field-hint-text { display: inline-block; font-size: var(--fs-caption); color: var(--text-muted); }

.type-group h3 { margin-top: 0; }

/* T31: мастер запуска компании — боковая навигация по шагам + панель содержимого. */
.wizard-layout { display: flex; gap: var(--space-5); align-items: flex-start; }
.wizard-nav { display: flex; flex-direction: column; gap: 2px; min-width: 200px; flex: none; }
.wizard-step {
  padding: var(--space-2) 10px; border-radius: var(--radius-sm); font-size: var(--fs-small); text-decoration: none; color: var(--text-muted);
}
a.wizard-step:hover { background: var(--series-gap); }
.wizard-current { background: var(--series-gap); color: var(--text); font-weight: 600; }
.wizard-done { color: var(--pos); }
.wizard-locked { color: var(--text-muted); opacity: .5; }
.wizard-content { flex: 1 1 auto; min-width: 0; }
.wizard-hint-box {
  background: var(--series-gap); border: 1px solid var(--border); border-radius: var(--radius-md);
  padding: var(--space-3) 14px; font-size: var(--fs-small); color: var(--text-muted); margin: 10px 0 var(--space-4);
}
@media (max-width: 760px) {
  .wizard-layout { flex-direction: column; }
  .wizard-nav { flex-direction: row; flex-wrap: wrap; min-width: 0; }
}

/* T32a: импорт из Excel/CSV — плитки шаблонов, сводка состояний, длинные подсказки. */
.import-tile-hint { color: var(--text-muted); font-size: var(--fs-caption); margin-top: var(--space-1); }

.import-totals {
  list-style: none; display: flex; flex-wrap: wrap; gap: var(--space-2) 18px;
  margin: var(--space-3) 0 var(--space-1); padding: 0; font-size: var(--fs-small);
}
.import-totals li { color: var(--text-muted); }
.import-totals strong { color: var(--text); font-size: var(--fs-body); }
.import-ok strong { color: var(--pos); }
.import-missing strong, .import-broken strong { color: var(--neg); }
.import-duplicate strong { color: var(--series-fact); }

/* Претензии к строке и подсказки к колонке — длинный текст, ему нужна ширина и перенос. */
.import-hint-cell {
  color: var(--text-muted); font-size: var(--fs-caption); max-width: 380px; white-space: normal;
}
.import-hint-cell div + div { margin-top: 3px; }

/* T42: календарь «Полнота данных и закрытие дня» — сетка недель, ячейка дня. */
.cal-nav { display: flex; align-items: center; gap: 14px; margin: var(--space-1) 0 14px; flex-wrap: wrap; }
.cal-month-label { font-weight: 600; font-size: var(--fs-body); min-width: 90px; text-align: center; }
.cal-legend { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 14px; }
.cal-grid { display: flex; flex-direction: column; gap: 6px; }
.cal-row { display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px; }
.cal-row-head { color: var(--text-muted); font-size: var(--fs-caption); text-transform: uppercase; letter-spacing: .03em; }
.cal-cell-head { text-align: center; padding: var(--space-1) 0; }
.cal-cell {
  border: 1px solid var(--border); border-radius: var(--radius-md); padding: var(--space-2); min-height: 96px;
  display: flex; flex-direction: column; gap: var(--space-1); background: var(--surface);
}
.cal-cell-outside { opacity: .35; background: transparent; }
.cal-cell-today { border-color: var(--series-fact); }
.cal-day-num { font-weight: 600; font-size: var(--fs-small); }
.cal-day-detail { font-size: var(--fs-caption); color: var(--text); }
.cal-day-detail-muted { color: var(--text-muted); }
.cal-force-btn { font-size: var(--fs-caption); padding: 3px var(--space-2); margin-top: 2px; align-self: flex-start; }
@media (max-width: 720px) {
  .cal-row { grid-template-columns: repeat(7, minmax(64px, 1fr)); overflow-x: auto; }
  .cal-grid { overflow-x: auto; }
}
/* T43: /status — «проверка связи» и «ошибки за сутки», строка = пилюля + текст. */
.status-connectivity {
  list-style: none; margin: 0 0 18px; padding: 0;
  display: flex; flex-direction: column; gap: var(--space-2); font-size: var(--fs-small);
}
.status-connectivity li { display: flex; align-items: center; gap: var(--space-2); }
