/* Плотный, лёгкий UI: системные шрифты, без веб-шрифтов/градиентов, для старых браузеров. */

* {
    box-sizing: border-box;
}

/* [hidden] всегда прячет (правило C5): класс с собственным display (flex/grid/inline-grid)
   больше не перебивает скрытие атрибутом — точечные дубли (.mk[hidden], .chip[hidden],
   .pos-btn[hidden]…) сняты этим одним правилом. */
[hidden] {
    display: none !important;
}

html {
    font-size: 14px;
}

body {
    margin: 0;
    /* Шрифтовой стек концепта (там он начинается с -apple-system; на Windows
       фактически резолвится в Segoe UI — как и наш прежний system-ui). */
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    font-size: 13px;  /* базовый кегль концепта */
    color: var(--c-text);
    background: var(--c-bg);
}

/* ── Дизайн-токены: единый источник палитры и типовых размеров ──────────────
   Тексты/серые подобраны так, чтобы вспомогательный текст держал контраст ≥ 4.5:1
   на белом (WCAG AA). Меняем значение здесь — меняется по всему приложению. */
:root {
    /* СВЕТЛАЯ ТЕМА (дефолт). База — палитра концепта `docs/ui-concepts.html`
       (перенос 18.07.2026, замером из :root концепта). Поверх неё 24.07.2026
       ВПАЯНЫ читаемостные дельты бывшей темы «Контрастная»: вспомогательные
       тексты подняты до AA+, границы/разделители плотнее, слои фона разведены,
       --c-ok дотянут до AA. Решение пользователя (24.07.2026): оставить только
       ДВЕ темы — контрастная стала светлой (эти значения), прежнюю «мягкую»
       светлую и отдельную тему «Контрастная» убрали. Чистые значения концепта
       и удалённая тема — в истории git.
       Ещё живой осознанный компромисс: --c-warn = 4.50:1 на своей подложке —
       выбор в пользу макета, а НЕ недосмотр; не «чинить» обратно без разговора.
       Прежняя палитра «refresh» (акцент #2b5394, радиусы 3/2px, ok #1f7a30) —
       в истории git и в docs/design-rollout.md. */

    /* Шрифтовой стек = body. Токен из концепта: без него все `font: ... var(--font)`
       (чипы роли пикера, бейдж «новое» и т.п.) МОЛЧА становились unset — шорткат с
       неопределённой var() инвалиден целиком, и кегль/жирность наследовались от родителя. */
    --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    /* Моноширинный стек (kbd, сообщения журнала сервера) — токен концепта `--mono`. До 25.09.2026
       каталог его обещал, а site.css писал стек литералом в трёх местах. */
    --mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;

    --c-text: #15181c;        /* основной */
    --c-text-soft: #2c353f;   /* пункт меню, кнопка (читаемостная дельта, было #3c4553) */
    --c-muted: #545d6a;       /* подписи, шапки таблиц, мета (было #68717d) */
    --c-faint: #636c78;       /* плейсхолдеры, счётчики, пустые состояния (было #98a1ac; теперь держит AA) */
    /* Границы — плотнее hairline прежней «мягкой» светлой */
    --c-border: #b7bfca;      /* рамки полей/кнопок/карточек (было #d3d8de) */
    --c-border-soft: #ccd2da; /* было #e4e7eb */
    --c-line: #d3d9e0;        /* разделители строк и секций (было #e4e7eb) */
    --c-line-row: #dfe4ea;    /* разделитель строки таблицы — легче обычного (было #eef0f3) */
    /* Фоны — слои разведены сильнее прежней светлой (белый --c-bg тот же) */
    --c-bg: #fff;             /* концепт: --surface */
    --c-bg-alt: #f2f5f8;      /* холст рельса, шапка таблицы, подвал (было #fafbfc) */
    --c-bg-panel: #e7ebf1;    /* плашки, пилюли счётчиков (было #f0f2f5) */
    --c-bg-page: #eaeef3;     /* холст страницы (было #f4f6f8) */
    --c-bg-hover: #eef3f9;    /* ховер строки — ступень видимее (было #fafbfc) */
    --c-bg-active: #eaf0ff;   /* выбранная строка = accent-soft (+ метка слева) */
    --c-zebra: #f2f5f8;       /* было #fafbfc */
    --c-anchor: #384754;      /* тёмного якоря в вёрстке нет; токен для совместимости */
    --c-th-bg: var(--c-bg-alt);
    --c-th-fg: var(--c-muted);
    /* Акцент */
    --c-accent: #2f5fe0;
    --c-accent-dark: #2149b8;
    --c-accent-bg: #eaf0ff;   /* концепт: --accent-soft */
    --c-accent-border: #c3d3fb; /* концепт: --accent-line */
    /* Статусы — тройки «текст / подложка / рамка», значения концепта */
    --c-ok: #0a7350;          /* дотянут до AA (было #0e8a5f, 4.36:1) */
    --c-ok-bg: #e6f5ee;
    --c-ok-border: #a8ddc4;
    --c-warn: #9c6410;
    --c-warn-bg: #fdf2df;
    --c-warn-border: #e8c99a;
    --c-danger: #c5342c;
    --c-danger-bg: #fdecea;
    --c-danger-border: #f0b5b0;
    /* Текст на залитых акцентом/статусом элементах. НЕ --c-bg: в тёмной теме фон
       темнеет, а текст на синей кнопке остаётся белым. */
    --c-on-accent: #fff;
    --c-on-accent-veil: rgba(255, 255, 255, .18);  /* подложка kbd на залитой кнопке */
    --c-on-accent-line: rgba(255, 255, 255, .3);   /* рамка kbd на залитой кнопке */
    --c-accent-bg-hover: #dfe8ff;   /* ховер акцент-контурных кнопок (.wh-1/.filters .btn-primary) */
    /* «Чернильный» текст на цветных подложках — значения концепта (calc/banner.warn) */
    --c-accent-ink: #2b3a52;        /* текст на --c-accent-bg (.field-hint) */
    --c-accent-ink-soft: #5a6b85;   /* вторичный текст на --c-accent-bg (пояснение в плашке) */
    --c-warn-ink: #5c4210;          /* текст на --c-warn-bg (.banner.warn) */
    /* Подложка модалки */
    --c-scrim: rgba(19, 26, 42, .44);
    /* Подсветка совпадения поиска в пикере (mark) — значение концепта */
    --c-mark: #fff2b8;
    /* Аватары/чипы людей — значения концепта: нейтральный и фиолет сотрудника */
    --c-av-bg: #dfe4ea;
    --c-av-fg: #4a5462;
    --c-emp-av-bg: #e7e2f5;
    --c-emp-chip-bg: #efe9fb;
    --c-emp-fg: #5b47a0;
    /* Групповой прыжок (манифест /Loads): цвет по слоту группы, палитра — validated
       categorical (dataviz); слоты blue/green/red пропущены — заняты смыслом в UI
       (акцент/ок-допуск/удаление), пересекаться с ними не должны. */
    --c-group-0: #1baf7a;
    --c-group-1: #eda100;
    --c-group-2: #4a3aa7;
    --c-group-3: #e87ba4;
    --c-group-4: #eb6834;
    /* Песочная панель оператора тандема (/Loads) */
    --c-sand-bg: #fbf7f3;
    --c-sand-border: #eadfd6;
    --c-sand-accent: #c08a5f;
    --c-sand-text: #b0603a;
    --c-sand-muted: #8a6d55;
    /* Тени концепта */
    --shadow: 0 1px 2px rgba(16, 24, 40, .06), 0 10px 30px -14px rgba(16, 24, 40, .25);
    --shadow-lg: 0 2px 6px rgba(16, 24, 40, .08), 0 24px 60px -20px rgba(16, 24, 40, .35);
    --shadow-panel: -8px 0 24px -12px rgba(16, 24, 40, .30);
    --shadow-sm: 0 1px 2px rgba(16, 24, 40, .1);      /* лёгкий отрыв карточки/кнопки */
    --shadow-pop: 0 8px 24px rgba(20, 24, 30, .18);   /* попапы (календарь dz-date) */
    /* Типографика подписей */
    --fs-label: 12px;
    /* Скругления концепта. --r-sm сравнялся с --r намеренно: в концепте у полей,
       кнопок и карточек один радиус, отдельного «мелкого» скругления там нет. */
    --r: 6px;
    --r-sm: 6px;
    --r-lg: 10px;
    /* Типовые высоты концепта: строка таблицы и высота контрола (кнопка/поле/пункт меню). */
    --row: 34px;
    --ctl: 30px;
    /* Нативные контролы (скроллбары, чекбоксы, календарь) рисуются светлыми */
    color-scheme: light;
}

/* ── Тёмная тема ─────────────────────────────────────────────────────────────
   Второй набор значений ТЕХ ЖЕ токенов; включается атрибутом data-theme="dark"
   на <html> (его рендерит сервер из cookie dz-theme, переключатель — в топбаре).
   Селектор :root[data-theme="dark"] (0-2-0) намеренно специфичнее :root (0-1-0) —
   иначе победителя решал бы порядок в файле (см. pitfalls.md про специфичность).
   Правило то же, что у светлой: значения подобраны по контрасту (цифры замеров —
   design-system.md §Темы), менять — только с пересчётом. */
:root[data-theme="dark"] {
    /* Текст */
    --c-text: #e7eaf0;
    --c-text-soft: #c4cbd6;
    --c-muted: #98a2b0;
    /* Поднят 25.09.2026 с #67707d (3.23:1 на --c-bg, 2.84 на --c-bg-panel — ниже AA), тем же
       оттенком: им набраны не только плейсхолдеры, но и .cell-sub, подписи плиток, счётчики.
       Теперь 5.15 на --c-bg, 5.39 на --c-bg-alt, 4.54 на --c-bg-panel; ступень до --c-muted
       (6.26) сохранена. На выбранной строке (--c-bg-active) — 4.0: выше не поднять, не слив
       с --c-muted. */
    --c-faint: #8a929e;
    /* Границы */
    --c-border: #3b4452;
    --c-border-soft: #2d3542;
    --c-line: #2d3542;
    --c-line-row: #272e39;
    /* Фоны: «поверхность» светлее «холста», как и в светлой теме, но инверсно */
    --c-bg: #1c2129;
    --c-bg-alt: #181d24;
    --c-bg-panel: #242b36;
    --c-bg-page: #14181e;
    --c-bg-hover: #222936;
    --c-bg-active: #24334f;
    --c-zebra: #20252e;
    --c-anchor: #cfd6df;
    /* Акцент: на тёмном «тёмный-активный» = более светлый */
    --c-accent: #6b90f0;
    --c-accent-dark: #8fadf5;
    --c-accent-bg: #223251;
    --c-accent-border: #3a5385;
    --c-accent-bg-hover: #2a3d63;
    --c-accent-ink: #c8d6f2;
    --c-accent-ink-soft: #93a7c9;
    /* Статусы */
    --c-ok: #43c08e;
    --c-ok-bg: #17352a;
    --c-ok-border: #2c5a45;
    --c-warn: #d9a34e;
    --c-warn-bg: #382e17;
    --c-warn-border: #64512a;
    --c-warn-ink: #e4c98f;
    --c-danger: #e36f66;
    --c-danger-bg: #3c2220;
    --c-danger-border: #6b3431;
    /* На залитых кнопках — ТЁМНЫЙ текст: акцент в тёмной теме осветлён, и белый
       на нём проваливается до 3.06:1 (замерено); тёмная «чернильная» надпись
       на светлой заливке даёт 5.3:1+ и на акценте, и на ok/danger-заливках. */
    --c-on-accent: #131824;
    --c-on-accent-veil: rgba(16, 20, 30, .14);
    --c-on-accent-line: rgba(16, 20, 30, .3);
    --c-scrim: rgba(0, 0, 0, .55);
    --c-mark: #6b5d1f;
    /* Аватары/фиолет сотрудника */
    --c-av-bg: #333c48;
    --c-av-fg: #b8c2cf;
    --c-emp-av-bg: #372f52;
    --c-emp-chip-bg: #3d3170;
    --c-emp-fg: #b3a4e6;
    /* Группы манифеста — те же hue, светлее под тёмный фон */
    --c-group-0: #22c98d;
    --c-group-1: #f0ac1a;
    --c-group-2: #7a68d6;
    --c-group-3: #ef92b5;
    --c-group-4: #f07c4c;
    /* Песочная панель оператора */
    --c-sand-bg: #2e2823;
    --c-sand-border: #4a3d31;
    --c-sand-accent: #d09668;
    --c-sand-text: #d5906b;
    --c-sand-muted: #a08a76;
    /* Тени на тёмном тонут — непрозрачность выше */
    --shadow: 0 1px 2px rgba(0, 0, 0, .25), 0 10px 30px -14px rgba(0, 0, 0, .6);
    --shadow-lg: 0 2px 6px rgba(0, 0, 0, .3), 0 24px 60px -20px rgba(0, 0, 0, .7);
    --shadow-panel: -8px 0 24px -12px rgba(0, 0, 0, .65);
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, .3);
    --shadow-pop: 0 8px 24px rgba(0, 0, 0, .45);
    /* Нативные контролы — тёмные */
    color-scheme: dark;
}

a {
    color: var(--c-accent);
    text-decoration: none;
}

a:hover {
    text-decoration: underline;
}

input, select, textarea, button {
    font-family: inherit;
    font-size: 1rem;
}

button {
    cursor: pointer;
    background: var(--c-bg-alt);
    border: 1px solid var(--c-border);
    border-radius: var(--r-sm);
    padding: 6px 14px;
}

button:hover {
    background: var(--c-bg-panel);
}

/* Плотные таблицы (журнал, манифест, матрица прав) */
table.dense {
    border-collapse: collapse;
    width: 100%;
}

table.dense th, table.dense td {
    border: 1px solid var(--c-border);
    padding: 5px 9px;
    text-align: left;
}

table.dense th {
    background: var(--c-bg-panel);
    font-size: 12px;
    color: var(--c-text-soft);
    white-space: nowrap;
}

table.dense td:not(:first-child) {
    text-align: center;
}

.status-message {
    color: var(--c-ok);
    border: 1px solid var(--c-ok);
    padding: 8px;
    margin-bottom: 12px;
    max-width: 460px;
}

/* Ошибка формы/доменного правила (в стиле .auth-error) */
/* Плашка ошибки — та же форма, что у выпадашки подсказок (скругление --r, полная рамка),
   но в «тройке» --c-danger. Без полосы слева и хардкод-цветов — приведено к .auth-error/.field-hint. */
.error-message {
    border: 1px solid var(--c-danger-border);
    border-radius: var(--r);
    background: var(--c-danger-bg);
    color: var(--c-danger);
    padding: 9px 11px;
    font-size: 12.5px;
    margin: 12px 18px;
    flex: none;
}

/* В модалке/панели плашка выравнивается с полями (горизонтальный отступ держит padding тела,
   вертикальный — gap контейнера), а не инсетится своим margin. */
.dz-panel-body .error-message {
    margin: 0;
}

/* Сообщение над списком или полотном (прямой потомок .work-wrap, между шапкой и телом) —
   отступы по эталону /PosItems (25.09.2026). До этого каждая страница писала их инлайном,
   и в одной группе реестров жили два варианта: 10px 16px 0 на восьми страницах (ошибка
   вплотную к линии списка) и 10px 16px 12px на семи. Итог импорта физлиц стоит в том же
   слоте — тот же отступ. */
.work-wrap > .error-message,
.work-wrap > .import-result {
    margin: 10px 16px 12px;
}

/* ── Каркас приложения — перенесён 1:1 с концепта `docs/ui-concepts.html` ──────
   Соответствие классов: .app-topbar = .topbar, .app-brand = .brand, .app-nav = .rail,
   .app-nav-group = .rail-group, .app-nav-item = .nav-i, .app-main = .work.
   ОТСТУПЛЕНИЕ ОТ БУКВЫ: в концепте всё приложение обёрнуто в .app — карточку с рамкой,
   скруглением и height:620px. Это рамка МОКАПА (макет вложен в страницу-документ),
   а не элемент интерфейса: настоящая оболочка занимает окно целиком. */
.app-body {
    height: 100vh;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    font-size: 13px;
    line-height: 1.45;
}

.app-topbar {
    display: flex;
    align-items: center;
    gap: 14px;
    height: 46px;
    flex: none;
    padding: 0 12px 0 0;   /* слева отступа нет: марка-блок сам держит свои 190px */
    border-bottom: 1px solid var(--c-line);
    background: var(--c-bg);
}

/* Бренд: плитка-марка + название дропзоны. Ширина РОВНО как у рельса меню (190px) плюс
   правая граница (решение 01.08.2026): вертикаль «правая граница меню» продолжается вверх
   через шапку одной линией, и всё, что правее неё, читается как зона страницы — крошка,
   заголовок. Раньше граница отсутствовала (в концепте бренд был просто первым элементом),
   и шапка выглядела набором плиток без структуры. Менять 190px — только вместе с .app-nav. */
.app-brand {
    width: 190px;
    height: 100%;
    flex: none;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 0 12px;
    border-right: 1px solid var(--c-line);
    font-weight: 600;
    font-size: 13px;
    color: var(--c-text);
}

.app-brand:hover {
    text-decoration: none;
}

.app-brand-mark {
    width: 22px;
    height: 22px;
    flex: none;
    border-radius: 5px;
    background: var(--c-accent);
    color: var(--c-on-accent);
    display: grid;
    place-items: center;
    font-size: 10px;
    font-weight: 700;
}

.app-brand-name {
    font-weight: 600;
    font-size: 13px;
}

/* Поле «Поиск по людям» (.app-omnibox) УДАЛЕНО 01.08.2026 по решению пользователя: вход
   в реестр физлиц есть пунктом меню, а поле занимало правую зону шапки, куда переехал
   контекст смены. Возвращать — только вместе со СКВОЗНЫМ поиском (не ссылкой на реестр). */

/* Аватар пользователя (концепт: .avatar) — инициалы в кружке */
.app-avatar {
    width: 26px;
    height: 26px;
    flex: none;
    border-radius: 50%;
    background: var(--c-av-bg);
    color: var(--c-av-fg);
    display: grid;
    place-items: center;
    font-size: 10.5px;
    font-weight: 600;
}

/* Стрелок истории в приложении нет вовсе (02.08.2026): .app-history* убраны 20.07.2026
   при переносе в бар, .ab-arrow — вместе с самими стрелками. «Назад» даёт браузер. */

/* Контекст смены в топбаре (концепт, вкладка «Навигация»: «Смена 18.07 · открыта в 08:12»).
   Домен держит одну смену на дату, поэтому «текущая смена» — глобальное состояние. */
.app-shift {
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 0 9px;
    height: var(--ctl);
    border: 1px solid var(--c-border);
    border-radius: var(--r);
    background: var(--c-bg-alt);
    font-size: 12.5px;
}

.app-shift-label {
    color: var(--c-muted);
}

.app-shift-date {
    font-weight: 600;
    color: var(--c-text);
    font-variant-numeric: tabular-nums;
}

.app-spacer {
    flex: 1;
}

.app-logout {
    height: var(--ctl);   /* одна высота со всеми контролами: было 26 против 30 */
    display: inline-flex;
    align-items: center;
    border: 1px solid var(--c-border);
    border-radius: var(--r);
    background: var(--c-bg);
    padding: 0 11px;
    color: var(--c-text-soft);
    font-size: 12.5px;
    font-family: inherit;
}

.app-logout:hover {
    background: var(--c-bg-alt);
}

/* Переключатель темы: квадратная ghost-кнопка в метрике контролов топбара.
   Иконку выбирает CSS по data-theme на <html>: в светлой — солнце, в тёмной —
   луна (иконка = ТЕКУЩАЯ тема). Обе иконки лежат в DOM (_Layout). */
.app-theme {
    width: var(--ctl);
    height: var(--ctl);
    flex: none;
    display: inline-grid;
    place-items: center;
    padding: 0;
    border: 1px solid var(--c-border);
    border-radius: var(--r);
    background: var(--c-bg);
    color: var(--c-text-soft);
    cursor: pointer;
}

.app-theme:hover {
    background: var(--c-bg-alt);
}

/* Иконка = ТЕКУЩАЯ тема (клик переключает свет ↔ тьму). Два глифа в DOM,
   видимый выбирает CSS по data-theme на <html>. */
.app-theme svg { display: none; }
:root[data-theme="light"] .app-theme .app-theme-sun { display: block; }
:root[data-theme="dark"] .app-theme .app-theme-moon { display: block; }

/* ── Контекст страницы в топбаре (решение 01.08.2026, пилот — карточка взлёта) ──
   Якорь навигации (_ActionNav, в топбаре — БЕЗ стрелок, только крошка) + заголовок
   страницы поднимаются в топбар, когда страница ставит ViewData["TopHead"]=true.
   Смысл — вертикаль: на экране клиента (1366×768 с вкладками браузера ≈ 620px
   вьюпорта) полоса .wh-1 стоила 46px, а заголовок и крошка прекрасно живут в уже
   существующей верхней полосе. Заголовок здесь 15px (не 17px, как в .wh-1): рядом
   марка 13px, и 17px спорил бы с ней за первый взгляд. Зона страницы начинается
   СРАЗУ за границей марки-блока — той самой, что продолжает границу меню вверх;
   глобальное (смена, аватар, тема, выход) прижато вправо. */
.app-topbar .ab-nav {
    flex: none;
}

.app-page-title {
    margin: 0;
    font-size: 15px;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}

/* Счётчик раздела рядом с заголовком («217», «5 взлётов») — тот же вид, что был у счётчика в строке действий
   в строке действий: приглушённый, на полкегля мельче заголовка. Страница задаёт строкой
   ViewData["HeadCount"] — считает и склоняет она сама, топбар только показывает. */
.app-page-count {
    flex: none;
    color: var(--c-faint);
    font-size: 13px;
    font-weight: 500;
    white-space: nowrap;
    margin-left: -6px;   /* съедает половину gap: счётчик — хвост заголовка, а не сосед */
}

/* Состояние документа в топбаре — слот-секция TopStatus, сразу правее крошки и заголовка
   (решение 01.08.2026). Кегль 12.5px: рядом заголовок 15px, и состояние не должно спорить
   с именем документа за первый взгляд; шаг до него держит gap топбара (14px), своих
   отступов не добавляем. Потолок ширины — чтобы длинная ошибка сохранения не распирала
   шапку и не жала правый кластер; причина целиком остаётся в title (её пишет site.js).
   text-overflow тут НЕ ставим: у flex-контейнера голый текст живёт в анонимном flex-элементе,
   и многоточие к нему не применяется — это было бы правило-обманка. */
.app-topbar .saveind {
    flex: none;
    max-width: 320px;
    overflow: hidden;
    white-space: nowrap;
    font-size: 12.5px;
}

.app-workspace {
    display: flex;
    flex: 1;
    min-height: 0;
}

/* Рельс навигации (концепт: .rail) */
.app-nav {
    width: 190px;
    flex: none;
    border-right: 1px solid var(--c-line);
    background: var(--c-bg-alt);
    overflow: auto;
    padding: 9px 8px;
    display: flex;
    flex-direction: column;
    gap: 1px;
}

/* Высота пункта фиксирована (28px), поэтому подпись обязана быть в одну строку:
   длинный текст иначе НЕ растягивает коробку, а вылезает за неё — коробочный замер
   этого не видит, поймано через Range («Отчёт по инструктажам»: коробка 28, текст 34).
   Подписи меню держим короткими, а троеточие — страховка от следующей длинной. */
.app-nav-item {
    display: flex;
    align-items: center;
    gap: 9px;
    height: 28px;
    flex: none;
    padding: 0 8px;
    border-radius: var(--r);
    color: var(--c-text-soft);
    font-size: 12.5px;
    background: transparent;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Иконки меню — inline SVG с хардкод-stroke в разметке; CSS-свойство stroke
   перебивает презентационный атрибут, поэтому цвет иконок правится здесь.
   В концепте это текстовые глифы с opacity .75 — оставляем SVG (правило системы:
   иконки только inline SVG), но приглушаем так же. */
.app-nav-item svg {
    stroke: var(--c-text-soft);
    opacity: .75;
    flex: none;
}

.app-nav-item:hover {
    background: var(--c-bg-panel);
    text-decoration: none;
}

/* Выбранный пункт — заливка accent-soft, БЕЗ левой полосы: в концепте метки нет,
   состояние держат фон, цвет текста и вес. */
.app-nav-item.active {
    background: var(--c-accent-bg);
    color: var(--c-accent-dark);
    font-weight: 600;
}

.app-nav-item.active svg {
    stroke: var(--c-accent-dark);
    opacity: 1;
}

/* Заголовок группы меню — КАПСОМ (концепт: .rail-group, text-transform: uppercase).
   Прежнее правило «капса нет нигде» отменено решением 18.07.2026 в пользу
   переноса концепта 1:1; здесь капс безопасен — это короткие слова в свободной
   по ширине колонке, а не подписи полей в узких ячейках таблицы. */
.app-nav-group {
    padding: 11px 8px 4px;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--c-faint);
    user-select: none;
}

.app-nav-group:first-child {
    padding-top: 2px;
}

.app-main {
    flex: 1;
    min-height: 0;
    overflow: auto;
    background: var(--c-bg);
    display: flex;
    flex-direction: column;
}

/* Полоса заголовка .app-main-head УДАЛЕНА 20.07.2026: _Layout теперь рисует всем
   не-OwnHead страницам строку действий .wh-1 (якорь навигации + заголовок), а не
   старую полосу. Строку действий видят все экраны, а не только переведённые. */

.app-content {
    padding: 18px;
}

/* Пустое состояние раздела */
.app-empty {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 40px 18px;
}

.app-empty-inner {
    text-align: center;
    color: var(--c-faint);
    max-width: 340px;
}

.app-empty-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 56px;
    height: 56px;
    border: 1px solid var(--c-border);
    border-radius: var(--r);
    background: var(--c-bg-alt);
    color: var(--c-faint); /* stroke="currentColor" у svg внутри */
    margin-bottom: 14px;
}

.app-empty-title {
    font-size: 15px;
    font-weight: 600;
    color: var(--c-muted);
    margin-bottom: 5px;
}

.app-empty-text {
    font-size: 13px;
}

/* ── Страница входа (перенесена на токены концепта 19.07.2026) ──────────────
   Высоты: поля (роль-combo и пароль) 32px — метрика поля формы, как в панели;
   кнопка 30px — --ctl, обязателен любому интерактивному элементу. */
.auth-body {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    font-size: 13px;
    line-height: 1.45;
    background: var(--c-bg-page);
}

.auth-center {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 32px 16px;
}

.auth-card {
    width: 380px;
    max-width: 100%;
    background: var(--c-bg);
    border: 1px solid var(--c-border);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow);
    overflow: hidden;   /* подвал на --c-bg-alt должен обрезаться по скруглению карточки */
}

.auth-head {
    padding: 18px 20px 16px;
    border-bottom: 1px solid var(--c-line);
}

/* Марка — та же плитка, что в топбаре (.app-brand-mark): символ входа в приложение
   у приложения уже есть, второй (парашют в своём цвете) был лишней сущностью. */
.auth-brand {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 13px;
}

.auth-brand-name {
    font-weight: 600;
    font-size: 13px;
}

.auth-title {
    font-size: 17px;
    font-weight: 600;
}

.auth-form {
    padding: 16px 20px 18px;
    display: flex;
    flex-direction: column;
    gap: 13px;
}

.auth-field {
    display: flex;
    flex-direction: column;
    gap: 5px;
}

.auth-label {
    color: var(--c-muted);
    font-size: 11.5px;
    font-weight: 500;
}

/* Поле выбора роли (dz-select) — по высоте поля формы (32px), как пароль рядом:
   иначе в карточке стояли бы 30px у роли и 32px у пароля — две группы в гистограмме. */
.auth-form .dzs-btn {
    height: 32px;
}

.auth-form input[type="password"] {
    height: 32px;
    padding: 0 9px;
    border: 1px solid var(--c-border);
    border-radius: var(--r);
    background: var(--c-bg);
    color: var(--c-text);
    width: 100%;
    font-size: 13px;
}

.auth-form input[type="password"]:focus {
    outline: none;
    border-color: var(--c-accent);
}

.auth-form input[type="password"]::placeholder {
    color: var(--c-faint);
}

/* Ошибка — тройка --c-danger, полная рамка со скруглением. Полосы слева нет:
   вид плашек приведён к .field-hint решением 18.07.2026. */
.auth-error {
    border: 1px solid var(--c-danger-border);
    border-radius: var(--r);
    background: var(--c-danger-bg);
    color: var(--c-danger);
    padding: 9px 11px;
    font-size: 12.5px;
}

.auth-remember {
    display: flex;
    align-items: center;
    gap: 8px;
    color: var(--c-text-soft);
    font-size: 12.5px;
    cursor: pointer;
    user-select: none;
}

.auth-remember input {
    width: 15px;
    height: 15px;
    accent-color: var(--c-accent);
    cursor: pointer;
}

/* Кнопка входа — .btn-primary во всю ширину; здесь только раскладка. */
.auth-button {
    margin-top: 2px;
    width: 100%;
    justify-content: center;
}

.auth-foot {
    padding: 10px 20px;
    border-top: 1px solid var(--c-line);
    background: var(--c-bg-alt);
    color: var(--c-faint);
    font-size: 11.5px;
}

.auth-foot b {
    color: var(--c-text-soft);
    font-weight: 600;
}

.auth-footer {
    flex: none;
    padding: 14px;
    text-align: center;
    color: var(--c-faint);
    font-size: 11.5px;
}

/* ── Взлёты и манифест (по дизайну loads.dc) ── */
/* Рабочая область на всю высоту main; колонки тянутся до низа и скроллятся независимо */

.load-params {
    border: 1px solid var(--c-border);
    padding: 11px 14px;
    margin-bottom: 12px;
    background: var(--c-bg-alt);
}

/* ── Поле даты «как в 1С»: маска ДД.ММ.ГГГГ + всплывающий календарь (.dz-date) ── */
/* Высота — ОДНА на все контролы (--ctl). Раньше поле даты не задавало высоту вовсе
   и получалось 28/32px в зависимости от места: в строке с кнопками (30px) это читалось
   как «кнопки разной высоты». Цвета переведены с хардкода на токены. */
.dz-date {
    position: relative;
    display: flex;
    align-items: stretch;
    height: var(--ctl);
    border: 1px solid var(--c-border);
    border-radius: var(--r);
    background: var(--c-bg);
}

.dz-date:focus-within {
    border-color: var(--c-accent);
    box-shadow: 0 0 0 3px var(--c-accent-bg);
}

.dz-date.dz-invalid {
    border-color: var(--c-danger);
    background: var(--c-danger-bg);
}

.dz-date .dz-date-text {
    flex: 1;
    min-width: 0;
    border: 0;
    padding: 0 9px;
    background: transparent;
    font-size: 13px;
    font-family: inherit;
    color: inherit;
    font-variant-numeric: tabular-nums;
}

.dz-date .dz-date-text:focus {
    outline: none;
}

.dz-date .dz-date-toggle {
    flex: none;
    border: 0;
    background: transparent;
    padding: 0 8px;
    display: flex;
    align-items: center;
    color: var(--c-muted);
    border-radius: 0 var(--r) var(--r) 0;
}

.dz-date .dz-date-toggle:hover {
    background: var(--c-bg-alt);
    color: var(--c-text);
}

/* position: fixed — чтобы календарь не обрезался прокручиваемым предком
   (тело модалки: overflow-y: auto). Координаты ставит JS при открытии (positionPop). */
.dz-date-pop {
    position: fixed;
    top: 0;
    left: 0;
    border: 1px solid var(--c-border);
    background: var(--c-bg);
    box-shadow: var(--shadow-pop);
    z-index: 60;
    padding: 8px;
    width: 236px;
}

.dz-date-pop .dz-cal-head {
    display: flex;
    align-items: center;
    gap: 4px;
    margin-bottom: 7px;
}

.dz-date-pop .dz-cal-nav {
    flex: none;
    width: 24px;
    padding: 3px 0;
    border: 1px solid var(--c-border);
    background: var(--c-bg-panel);
    color: var(--c-text-soft);
    font-size: 15px;
    line-height: 1;
}

.dz-date-pop .dz-cal-nav:hover {
    background: var(--c-accent-bg);
}

.dz-date-pop .dz-cal-month {
    flex: 1;
    min-width: 0;
    padding: 3px 4px;
    border: 1px solid var(--c-border);
    background: var(--c-bg);
    font-size: 12.5px;
}

.dz-date-pop .dz-cal-year {
    flex: none;
    width: 62px;
    padding: 3px 4px;
    border: 1px solid var(--c-border);
    background: var(--c-bg);
    font-size: 12.5px;
}

.dz-date-pop .dz-cal-grid {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 1px;
}

.dz-date-pop .dz-cal-wd {
    text-align: center;
    padding: 3px 0;
    font-size: 11px;
    font-weight: 600;
    color: var(--c-faint);
}

.dz-date-pop .dz-cal-day {
    text-align: center;
    padding: 5px 0;
    font-size: 12.5px;
    cursor: pointer;
    border: 1px solid transparent;
    user-select: none;
}

.dz-date-pop .dz-cal-day:hover {
    background: var(--c-accent-bg);
}

.dz-date-pop .dz-cal-day.dz-out {
    color: var(--c-faint);
}

.dz-date-pop .dz-cal-day.dz-today {
    border-color: var(--c-accent);
}

.dz-date-pop .dz-cal-day.dz-sel {
    background: var(--c-accent);
    color: var(--c-on-accent);
}

.dz-date-pop .dz-cal-day.dz-sel:hover {
    background: var(--c-accent-dark);
}

.dz-date-pop .dz-cal-day.dz-dis,
.dz-date-pop .dz-cal-day.dz-dis:hover {
    color: var(--c-faint);
    cursor: default;
    background: none;
}

/* Кнопки — геометрия концепта: высота --ctl, радиус --r, кегль 12.5px/500 */
.btn-primary {
    height: var(--ctl);
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 0 11px;
    border: 1px solid var(--c-accent);
    border-radius: var(--r);
    background: var(--c-accent);
    color: var(--c-on-accent);
    font-weight: 500;
    font-size: 12.5px;
    font-family: inherit;
    line-height: 1;   /* концепт: font: 500 12.5px/1 — иначе текст «плавает» по высоте */
    text-decoration: none;
    white-space: nowrap;
}

.btn-primary:hover {
    background: var(--c-accent-dark);
    border-color: var(--c-accent-dark);
    text-decoration: none;
    color: var(--c-on-accent);
}

.btn-primary:disabled {
    opacity: .5;
    cursor: default;
    background: var(--c-accent);
}

/* Строка полей: ФИО + Система в одну линию, ФИО — основной элемент строки (шире) */

.btn-secondary {
    height: var(--ctl);
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 0 11px;
    border: 1px solid var(--c-border);
    border-radius: var(--r);
    background: var(--c-bg);
    font-size: 12.5px;
    font-weight: 500;
    font-family: inherit;
    line-height: 1;
    text-decoration: none;
    color: var(--c-text-soft);
    white-space: nowrap;
}

.btn-secondary:hover {
    text-decoration: none;
    background: var(--c-bg-alt);
}

/* Отдельная страница Details: простые формы не тянем на всю ширину экрана */
.details-narrow {
    max-width: 760px;
}

.btn-danger {
    display: inline-flex;
    align-items: center;
    height: var(--ctl); /* одна высота контролов на всё приложение */
    /* Собственного margin у кнопки НЕТ (снят 31.08.2026): вертикаль задаёт контейнер.
       Прежний margin-top:10px «под низ формы» протекал во все флекс-ряды — строка
       действий реестра .filters из-за него была 60px вместо 50px, а четыре контейнера
       (.dz-panel-foot, .card-save-bar, .backup-actions, .ds-acts) держали заплатки
       margin-top:0, чтобы его погасить.
       Метрика — как у .btn-secondary (25.09.2026): прежние 13px / вес 400 / padding 14px без
       line-height: 1 выбивались из ряда — в подвале dzConfirm «Отменить» и «Удалить…»
       стояли разным кеглем. */
    gap: 6px;
    padding: 0 11px;
    border: 1px solid var(--c-danger-border);
    border-radius: var(--r);
    background: var(--c-bg);
    font-size: 12.5px;
    font-weight: 500;
    font-family: inherit;
    line-height: 1;
    white-space: nowrap;
    text-decoration: none;
    color: var(--c-danger);
    cursor: pointer;
}

.btn-danger:hover {
    background: var(--c-danger);
    color: var(--c-on-accent);
}

/* Группа «цветная точка + подпись» в строке списка (допуск/мед у спортсменов) */

.pick-empty {
    padding: 12px 16px;
    color: var(--c-faint);
}

/* Недоступная кнопка-ссылка — правило ГЛОБАЛЬНОЕ, без привязки к блоку: раньше оно жило под
   селектором `.pagination` (снесён 02.08.2026 вместе с последним носителем класса), и в подвале
   реестра `.tfoot` класс `.disabled` молча ничего не делал — «нерабочая» ссылка кликалась. */
.btn-secondary.disabled {
    pointer-events: none;
    opacity: .5;
}

/* Метка в read-only карточке (label в field-grid) */
.field-label {
    color: var(--c-muted);
}

/* Заголовок секции — «акцентная подложка».
   Было: 11px серым (контраст 5.90) при подписях полей под ним 7.05 — заголовок
   бледнее собственного содержимого, иерархия перевёрнута, семь секций сливались
   в простыню. Стало: тёмный текст на светлой акцентной плашке (17.8).
   Текст в разметке набирать ОБЫЧНЫМ регистром — капс делает CSS.
   Вертикальные padding'и симметричны: border-left идёт по padding-box, и при
   асимметрии (0 сверху / 5px снизу) метка съезжала ниже текста на 3.8px. */
/* refresh: заголовок секции — простой (вес + hairline снизу), без капса и акцентной
   плашки. Капса в системе больше нет нигде, одинокая плашка читалась как случайность. */
.field-section {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 13px;
    font-weight: 650;
    color: var(--c-text);
    background: none;
    padding: 0 0 6px;
    margin-bottom: 10px;
    border-left: none;
    border-bottom: 1px solid var(--c-border);
}

/* Секция, идущая НЕ первой, отбивается сверху сама (31.08.2026). Раньше воздух перед
   заголовком давал только `margin-bottom` предыдущего блока: после `.field-grid` (16px)
   отбивка была, а после ряда чипов-галочек — НОЛЬ, и «Статус» прилипал к «Допускам»
   на карточке вида прыжка. Margin соседних блоков схлопывается, поэтому там, где
   отбивка уже была, зазор остаётся те же 16px, а не 32. Свой ритм `.fcols` (9px)
   перебивает это правило специфичностью — карточка физлица не меняется. */
.field-section:not(:first-child) {
    margin-top: 16px;
}

.field-grid {
    display: grid;
    gap: 10px 16px;
    margin-bottom: 16px;
}

.field-grid.cols-2 {
    grid-template-columns: 1fr 1fr;
}

.field-grid.cols-3 {
    grid-template-columns: 1fr 1fr 1fr;
}

/* Одна колонка — у .field-grid это и так умолчание, но модификатор ставится в разметке явно
   (справочники категорий и скидок): семейство cols-* должно читаться целиком, иначе `cols-1`
   выглядит классом-призраком. */
.field-grid.cols-1 {
    grid-template-columns: 1fr;
}

/* Двухколоночная раскладка карточек (карточка спортсмена: Физлицо + Спортсмен) */

.field-grid label {
    display: flex;
    flex-direction: column;
    gap: 3px;
}

.field-grid span {
    color: var(--c-muted);
    font-size: 11.5px;
}

/* Пометка обязательного поля */
.req {
    color: var(--c-danger);
    font-weight: 700;
}

/* Высота — токеном, а не «сколько получится из padding»: без неё <select> собирался
   в 32px, а input и vaadin-combo рядом были 30px, и соседние поля одной строки
   стояли разной высоты. Кегль и горизонтальный padding тоже общие с combo (13px / 9px),
   иначе текст в соседних полях набран разным размером и начинается с разного отступа.

   ВАЖНО — исключения. Селектор `.field-grid input` попадает и ВНУТРЬ составных полей:
   у `vaadin-combo-box` настоящий `<input slot="input">` лежит в light DOM, у нашего
   `<dz-date>` — `.dz-date-text`, у `_PersonPicker` — `.pp-input`. Без `:not(...)` они
   получали ещё одну рамку, белый фон и свой padding поверх родительского, то есть внутри
   поля рисовалось ВТОРОЕ поле, а текст уезжал вправо на 9px. Так и выглядело «криво»
   у поля ФИО. Новый составной контрол → добавить его внутренний input сюда (все 3 места)
   и в `.field-stack input` ниже; спаны кладки защищать префиксом `.pp`-стилей. */
.field-grid input:not([slot]):not(.dz-inner):not([type="radio"]), .field-grid select {
    height: var(--ctl);
    padding: 0 9px;
    border: 1px solid var(--c-border);
    border-radius: var(--r);
    background: var(--c-bg);
    font-size: 13px;
    font-family: inherit;
}

/* textarea высоту не фиксируем — она многострочная по смыслу */
.field-grid textarea {
    padding: 6px 9px;
    border: 1px solid var(--c-border);
    border-radius: var(--r);
    background: var(--c-bg);
    font-size: 13px;
    font-family: inherit;
}

.field-grid input:not([slot]):not(.dz-inner):focus,
.field-grid select:focus,
.field-grid textarea:focus {
    border-color: var(--c-accent);
    outline: none;
    box-shadow: 0 0 0 3px var(--c-accent-bg);
}

.field-grid input:not([slot]):not(.dz-inner):disabled {
    background: var(--c-bg-alt);
    color: var(--c-muted);
}

/* Многострочное поле (Комментарий физлица) */
.field-textarea {
    width: 100%;
    padding: 5px 7px;
    border: 1px solid var(--c-border);
    border-radius: var(--r-sm);
    background: var(--c-bg);
    font-size: 13.5px;
    resize: vertical;
    font-family: inherit;
}

.field-textarea:focus {
    border-color: var(--c-accent);
    outline: 2px solid var(--c-accent-border);
    outline-offset: -1px;
}

/* Список галочек-тегов. Метки — чипы (см. .chk-chip ниже): применяется на
   /RigSystems, /Athletes, /Employees единообразно. */
.checkbox-list {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

/* ── База таблицы реестра (концепт) — не удалять при зачистках: на ней держатся
   все страницы с .list-table. Параметры: 12.5px, разделители строк легче общих
   линий, рамки вокруг таблицы нет (её держит .tw сверху). */
.list-table {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    background: var(--c-bg);
    font-size: 12.5px;
}

/* Шапка — липкая, на холсте surface-2, обычный регистр (в концепте шапка таблицы
   БЕЗ капса — замерено: text-transform none; капс там только в группах меню). */
.list-table th {
    position: sticky;
    top: 0;
    z-index: 2;
    text-align: left;
    padding: 0 10px;
    height: 31px;
    background: var(--c-th-bg);
    border-bottom: 1px solid var(--c-line);
    font-size: 11.5px;
    font-weight: 500;
    color: var(--c-th-fg);
    white-space: nowrap;
    user-select: none;
}

.list-table td {
    padding: 0 10px;
    border-bottom: 1px solid var(--c-line-row);
    vertical-align: middle;
    white-space: nowrap;
}

/* Числовые колонки — вправо и моноширинными цифрами, чтобы разряды выстраивались */
.list-table th.num, .list-table td.num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.list-table th.mid, .list-table td.mid {
    text-align: center;
}

/* Кликабельные строки реестра: высота строки — токен --row (34px, как в концепте) */
.list-table tbody tr {
    cursor: pointer;
    height: var(--row);
}

/* Зебры нет: границу строки держит hairline снизу, зебра поверх — визуальный шум. */
.list-table tbody tr:hover {
    background: var(--c-bg-hover);
}

/* ── Строка-приёмник в обычном списке (.list-table): страница инструктажа, 08.08.2026 ──
   Тот же приём, что у таблицы-редактора взлёта (.sheet tr.sheet-new): под последним
   участником всегда пустая строка с «умным» полем ФИО — выбрал человека, строка
   добавилась, приёмник снова пуст. Кнопки «+ Добавить» рядом со списком больше нет.
   Здесь таблица обычная, а не .sheet, поэтому плоский вид поля прописан точечно. */
.list-table tr.row-new {
    cursor: default;
}

.list-table tr.row-new > td {
    border-bottom: 0;
}

.list-table tbody tr.row-new:hover {
    background: none;
}

.list-table tr.row-new td.num {
    color: var(--c-faint);
}

/* Пикер В СТРОКЕ таблицы выглядит ячейкой, а не полем-коробкой (то же решение, что
   у .sheet .pp-field): скруглённая рамка выбивается из «острой» таблицы. */
.list-table td.row-new-person {
    padding: 0;
}

.list-table td.row-new-person .pp {
    width: 100%;
}

.list-table td.row-new-person .pp-field {
    height: var(--row);
    border: 0;
    border-radius: 0;
    background: none;
    padding: 0 10px;
}

.list-table td.row-new-person .pp-field:hover {
    box-shadow: inset 0 0 0 1px var(--c-border);
    background: var(--c-bg-alt);
}

.list-table td.row-new-person .pp-field:focus-within {
    box-shadow: inset 0 0 0 2px var(--c-accent);
    background: var(--c-bg);
}

/* Выбранная строка: не только фоном, но и меткой акцентом слева — фон в одиночку
   слишком близок к ховеру, чтобы быть единственным носителем «где я». */
/* Выбор строки держат фон + акцентная метка. Жирность у активной строки НЕ добавлять:
   потолстевший текст расширяет ячейку, и авторазметка таблицы двигает колонки при каждом
   переключении выбора (поймано на /Payments: строка с комментарием ↔ строка без). */
.list-table tbody tr.active {
    background: var(--c-bg-active);
    box-shadow: inset 2px 0 0 var(--c-accent);
}

/* Отмеченная чекбоксом строка (массовый выбор) — акцентная заливка, заметно отличная от
   ховера и активной строки; держится и при наведении. */
.list-table tbody tr.row-selected td {
    background: var(--c-accent-bg);
}

/* Имя в строке чуть плотнее остального текста, но НЕ полужирное (концепт: 500) */
.list-table td.col-name {
    font-weight: 500;
}

/* Колонка-чекбокс (массовый выбор строк): узкая, по центру. Клик по ней не открывает
   превью строки — всплытие гасит JS страницы (см. Aircraft/Index.cshtml). */
.list-table th.col-select,
.list-table td.col-select {
    width: 34px;
    text-align: center;
    padding-left: 6px;
    padding-right: 0;
}

.list-table th.col-select input,
.list-table td.col-select input {
    margin: 0;
    vertical-align: middle;
    cursor: pointer;
    accent-color: var(--c-accent);
}

/* Архивные (мягко удалённые) строки реестра — приглушены; видны только роли sa при показе архива. */
.list-table tbody tr.row-archived td {
    color: var(--c-muted);
}

/* Галочка-фильтр в строке .filters (напр. «Показывать архивные» для sa). */
.fchk {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 12.5px;
    color: var(--c-muted);
    white-space: nowrap;
    cursor: pointer;
    user-select: none;
}

    .fchk input {
        margin: 0;
        cursor: pointer;
        accent-color: var(--c-accent);
    }

/* Меню действий над выбранными строками — native <details> («С выбранными ▾» на журнале). */
.dz-menu {
    position: relative;
    display: inline-block;
}

    .dz-menu > summary {
        list-style: none;
        cursor: pointer;
    }

        .dz-menu > summary::-webkit-details-marker { display: none; }

        /* Недоступное меню действий (решение 01.09.2026, концепт docs/list-actions-concepts.html §6).
           У <summary> НЕТ свойства disabled: присваивание `el.disabled = true` из компонента
           data-bulk-* молча ничего не делает, и меню открывалось «пустым» — все пункты серые,
           а по подписи не понять, что сперва надо отметить строки. Состояние несёт `aria-disabled`
           (его ставит тот же компонент), pointer-events гасит и раскрытие. Гашение — теми же
           средствами, что у прочих недоступных кнопок (.btn-primary:disabled, .btn-secondary.disabled):
           opacity .5, своих цветов не заводим. */
        .dz-menu > summary[aria-disabled="true"] {
            pointer-events: none;
            opacity: .5;
            cursor: default;
        }

    .dz-menu-count { font-variant-numeric: tabular-nums; }

    .dz-menu-pop {
        position: absolute;
        top: calc(100% + 4px);
        right: 0;
        z-index: 40;
        min-width: 210px;
        background: var(--c-bg);
        border: 1px solid var(--c-border);
        border-radius: var(--r);
        box-shadow: var(--shadow);
        padding: 4px;
        display: flex;
        flex-direction: column;
    }

    /* Пункты меню бывают и <a> (переход), и <button> (форма) — выглядеть они обязаны
       ОДИНАКОВО. text-decoration нужен в обоих правилах: базовое гасит подчёркивание
       ссылки, а на ховере глобальное `a:hover` (специфичность 0,1,1) перебивает базовое
       `.dz-menu-item` (0,1,0) — и подчёркивались ровно ссылки, кнопки нет (14.08.2026). */
    .dz-menu-item {
        text-align: left;
        padding: 7px 10px;
        border: 0;
        background: transparent;
        color: var(--c-text);
        font: inherit;
        font-size: 13px;
        border-radius: 5px;
        cursor: pointer;
        white-space: nowrap;
        text-decoration: none;
    }

        .dz-menu-item:hover:not(:disabled) { background: var(--c-bg-alt); text-decoration: none; }
        .dz-menu-item.danger { color: var(--c-danger); }
        .dz-menu-item:disabled { color: var(--c-faint); cursor: default; }

.list-table td.pick-empty {
    padding: 12px 16px;
    cursor: default;
}

.inline-form {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-left: 6px;
}

.btn-compact {
    padding: 2px 10px;
    font-size: 12px;
}

/* Подпись «* — обязательные поля» в подвале модалки: прижата влево от кнопок */
.form-req-note {
    margin-right: auto;
    color: var(--c-muted);
    font-size: 12px;
}

/* Блоки .rig-form* и .ent-card* УДАЛЕНЫ 02.08.2026 вместе с прежней формой парашютной
   системы: её заменила карточка-форма (.fcols.single, /RigSystems/Details), а широкая
   модалка правки — компактной модалкой создания. Компонент «карточки сущностей» больше
   ничем не рисуется; понадобится расходящийся набор полей — заводить заново по месту. */

/* Callout доменного правила. Вид переведён на концепт 18.07.2026 (решение пользователя
   «все подсказки в новом стиле»): рамка ПО ВСЕМУ ПЕРИМЕТРУ, скругление со всех сторон,
   полосы слева НЕТ. Метрика ровно та же, что у плашки-расчёта концепта — там это одна плашка
   «спокойная информация акцентом», и разводить их на два вида нечем.
   Прежний вид (жирная метка слева 3px сплошным акцентом, углы прямые) читался как
   предупреждение, хотя несёт обычное правило.
   margin-top оставлен намеренно: на нём висит отступ на 17 страницах, а замена его на gap
   контейнера — отдельная правка, которую надо смотреть глазами на каждой из них.
   NB: правило ЖИЛО между блоками .rig-form и чуть не уехало вместе с ними при вычистке
   02.08.2026 — общий компонент нельзя держать внутри «страничной» пачки правил. */
.field-hint {
    margin-top: 10px;
    padding: 10px 12px;
    background: var(--c-accent-bg);
    border: 1px solid var(--c-accent-border);
    border-radius: var(--r);
    color: var(--c-accent-ink);
    font-size: 12.5px;
    line-height: 1.35;
}

    /* Выделенное внутри правила — акцентом, как в концепте («За строку манифеста») */
    .field-hint b { color: var(--c-accent-dark); }

/* ══════════════════════════════════════════════════════════════════════════
   Умное поле выбора физлица (_PersonPicker) — пилот на панели «Добавить участника».
   Кастом вместо vaadin-combo ДЛЯ ЛЮДЕЙ: серверный поиск (htmx /People/Search),
   богатая строка, создание в теле панели (Вариант B). Попап живёт ВНУТРИ .dz-panel —
   клик по подсказке не считается «мимо» (см. docs/pitfalls.md про оверлей combo).
   ══════════════════════════════════════════════════════════════════════════ */
.pp { position: relative; }

/* Поле ВСЕГДА текстовое: после выбора имя остаётся в input'е (его можно править).
   Фон БЕЛЫЙ всегда (решение 22.07.2026, шапка журнала взлётов): серый «пустой» фон из
   концепта person-picker-concepts.html выбивал пикер из строки одинаковых белых полей
   формы. Правится здесь, в компоненте — пикер выглядит одинаково на ВСЕХ страницах. */
.pp-field {
    height: var(--ctl);
    border: 1px solid var(--c-border);
    border-radius: var(--r);
    background: var(--c-bg);
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 0 6px 0 9px;
}
.pp-field:focus-within {
    border-color: var(--c-accent);
    box-shadow: 0 0 0 3px var(--c-accent-bg);
}

/* Слева лупа; когда человек выбран — вместо неё аватар выбранного.
   Спан-кладка пикера с префиксом `.pp` — иначе внутри .field-grid её перебивает
   `.field-grid span` (подписи полей: muted, 11.5px) — специфичность (0,1,1) > (0,1,0). */
.pp .pp-mag { color: var(--c-faint); display: flex; flex: 0 0 auto; }
.pp.has-value .pp-mag { display: none; }
/* .pp — для специфичности выше .avatar-sm { display:grid }, иначе пустой кружок виден без выбора */
.pp .pp-picked-av { display: none; }
.pp.has-value .pp-picked-av { display: inline-grid; place-items: center; }
.pp.is-new .pp-picked-av { background: var(--c-accent-bg); color: var(--c-accent-dark); }

.pp .pp-chev { color: var(--c-faint); display: flex; align-items: center; flex: 0 0 auto; }
.pp-input {
    flex: 1; min-width: 0; border: 0; background: none; outline: 0;
    font-size: 13px; color: var(--c-text); padding: 0;
}
.pp-input::placeholder { color: var(--c-faint); }

/* Бейдж «новое» — когда выбрано ещё не заведённое физлицо (создание по имени) */
.pp-newbadge { display: none; }
.pp.is-new .pp-newbadge {
    display: inline-flex; align-items: center; height: 18px; padding: 0 6px; border-radius: 5px;
    background: var(--c-accent-bg); color: var(--c-accent-dark); font: 600 10.5px/1 var(--font);
    white-space: nowrap; flex: 0 0 auto;
}

/* Крестик очистки — ровный круг 18×18 с SVG по центру (глиф ✕ вставал криво и растягивал кнопку) */
.pp-clear {
    width: 18px; height: 18px; box-sizing: border-box; padding: 0; border: 0; border-radius: 50%;
    background: var(--c-bg-panel); color: var(--c-muted);
    display: none; place-items: center; cursor: pointer; flex: 0 0 auto;
}
.pp.has-value .pp-clear { display: grid; }
.pp-clear:hover { background: var(--c-line); color: var(--c-text); }

/* Выпадающий слой. position:fixed + координаты из JS — чтобы отрисовываться ПОВЕРХ панели/модалки,
   а не обрезаться их overflow (тот же приём, что у .dz-date-pop, см. docs/pitfalls.md).
   z-index выше .dz-panel (40) и .dz-modal (50). */
.pp-pop {
    position: fixed; z-index: 60;
    background: var(--c-bg); border: 1px solid var(--c-border); border-radius: var(--r);
    box-shadow: var(--shadow-lg); overflow-y: auto; max-height: 320px;
}

.pp-group {
    font-size: 10px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase;
    color: var(--c-faint); padding: 9px 12px 4px;
}
.pp-opt {
    display: flex; align-items: center; gap: 10px; padding: 6px 12px; cursor: pointer;
    border-left: 2px solid transparent;
}
.pp-opt:hover { background: var(--c-bg-alt); }
.pp-opt.sel { background: var(--c-accent-bg); border-left-color: var(--c-accent); }
.pp-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
/* Префикс .pp и явный color — защита от `.field-grid span` (см. комментарий у .pp-mag) */
.pp .pp-name { font-weight: 500; font-size: 13px; color: var(--c-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pp-name mark { background: var(--c-mark); color: inherit; border-radius: 2px; padding: 0 1px; }
.pp .pp-sub { font-size: 11.5px; color: var(--c-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-top: 1px; }
.pp-tags { display: flex; align-items: center; gap: 6px; flex: 0 0 auto; }
/* Аватар и «плюс» — тоже спаны: вернуть свои кегль/цвет (роль-варианты .ac/.emp ниже по файлу
   при равной специфичности перекрашивают как надо) */
.pp .avatar-sm { font-size: 9px; color: var(--c-av-fg); }
.pp .pp-role {
    height: 19px; display: inline-flex; align-items: center; padding: 0 7px; border-radius: 5px;
    font: 500 11px/1 var(--font); white-space: nowrap;
    background: var(--c-bg-panel); color: var(--c-muted);
}
.pp-role.ac { background: var(--c-accent-bg); color: var(--c-accent-dark); }
.pp-role.emp { background: var(--c-emp-chip-bg); color: var(--c-emp-fg); }

/* Пункт, который выбрать нельзя (страница пометила его классом `taken`: напр. участник
   уже стоит во взлёте). Гасим строку целиком и снимаем ховер — «недоступно» должно
   читаться ДО клика, иначе выбор кончается ошибкой на ровном месте. Чип-причина —
   тот же .pp-role, но в цветах предупреждения. */
.pp-opt.taken { opacity: .55; cursor: default; }
.pp-opt.taken:hover { background: transparent; }
.pp .pp-role.taken { background: var(--c-danger-bg); color: var(--c-danger); }

.pp-empty { padding: 14px 12px; text-align: center; color: var(--c-faint); font-size: 12.5px; }

.pp-create {
    display: flex; align-items: center; gap: 9px; padding: 9px 12px; cursor: pointer;
    border-top: 1px solid var(--c-line); color: var(--c-accent-dark); font-weight: 500; font-size: 12.5px;
}
.pp-create:hover, .pp-create.sel { background: var(--c-accent-bg); }
/* Текст строки «создать» — защита от `.field-grid span` (см. комментарий у .pp-mag);
   :not — чтобы не перебить кегль/цвет самого плюса */
.pp .pp-create span:not(.pp-plus) { font-size: inherit; color: inherit; }
.pp .pp-plus {
    width: 22px; height: 22px; border-radius: 5px; background: var(--c-accent); color: var(--c-on-accent);
    display: grid; place-items: center; font-size: 14px; flex: 0 0 auto;
}

/* ══════════════════════════════════════════════════════════════════════════
   ДИЗАЙН-СИСТЕМА: чипы, заголовки секций, вкладки, карточки компонентов.
   Правила и обоснования — в CLAUDE.md, раздел «Дизайн-система».
   ══════════════════════════════════════════════════════════════════════════ */

/* ── Чип статуса (read-only, в таблицах и карточках) ──
   Статус — то, ради чего сканируют список. Текстом его приходится вычитывать
   построчно, пятном он читается боковым зрением. */
/* Метрика чипа — из концепта: фиксированная высота 20px и радиус 5px, без рамки. */
.chip {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    height: 20px;
    padding: 0 7px;
    border: 1px solid transparent;
    border-radius: 5px;
    font-size: 11.5px;
    font-weight: 500;
    line-height: 1;
    white-space: nowrap;
    vertical-align: middle;
}

.chip-ok {
    background: var(--c-ok-bg);
    border-color: var(--c-ok-border);
    color: var(--c-ok);
}

.chip-off {
    background: var(--c-bg-panel);
    border-color: var(--c-border-soft);
    color: var(--c-muted);
}

.chip-info {
    background: var(--c-accent-bg);
    border-color: var(--c-accent-border);
    color: var(--c-accent-dark);
}

.chip-warn {
    background: var(--c-warn-bg);
    border-color: var(--c-warn-border);
    color: var(--c-warn);
}

/* Ошибка — «тройка» палитры. Заведён под уровни журнала сервера (08.09.2026):
   ERROR и WARN обязаны различаться пятном, иначе фильтровать журнал глазами нельзя. */
.chip-danger {
    background: var(--c-danger-bg);
    border-color: var(--c-danger-border);
    color: var(--c-danger);
}

/* ── Чип-чекбокс (интерактивный) ──
   ОДИН класс для всех «галочек-тегов»: виды прыжков, «Арендная» и т.п.
   Раньше это были два разных способа сказать одно и то же — голый чекбокс
   и чип. Отмеченное видно пятном, а не галкой 13×13. */
.chk-chip,
.checkbox-list label {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 10px;
    border: 1px solid var(--c-border);
    border-radius: var(--r-sm);
    background: var(--c-bg);
    font-size: 12.5px;
    cursor: pointer;
}

.chk-chip:hover,
.checkbox-list label:hover {
    background: var(--c-bg-hover);
}

/* :has() — Chrome/Edge 105+, Firefox 121+. Если не поддержан, чип просто
   остаётся невыделенным: сама галочка внутри всё равно показывает состояние. */
/* Вес при отметке НЕ меняем (25.09.2026; то же правило, что у строк таблицы и .dz-seg):
   жирный чип шире, ряд .checkbox-list переносится по-новому, и соседние чипы прыгают под
   курсором. Отмеченное держат заливка, рамка и цвет. */
.chk-chip:has(input:checked),
.checkbox-list label:has(input:checked) {
    background: var(--c-accent-bg);
    border-color: var(--c-accent);
    color: var(--c-accent-dark);
}

.chk-chip input,
.checkbox-list label input {
    width: auto;
    margin: 0;
    padding: 0;
}

/* Внутри field-grid перебиваем `label { flex-direction: column }` и растяжку
   по ячейке; align-self:end ставит чип вровень с низом соседнего поля. */
.field-grid .chk-chip {
    flex-direction: row;
    justify-self: start;
    align-self: end;
}

/* ── Вкладки внутри модалки ── */

/* Обе панели лежат в одной ячейке грида и обе участвуют в раскладке, поэтому
   обёртка всегда по высоте самой высокой вкладки и модалка не «прыгает» при
   переключении. visibility (не display:none) сохраняет место и убирает из tab-order. */
.dz-tabwrap {
    display: grid;
}

.dz-tabpane {
    grid-area: 1 / 1;
    display: flex;
    flex-direction: column;
    gap: 14px;
    visibility: hidden;
}

.dz-tabpane.active {
    visibility: visible;
}

/* Таблица-данные (не реестр): строки не выбираются, поэтому ни курсора-руки, ни
   подсветки под курсором — они обещали бы клик, которого нет. Зебра остаётся. */
.list-table.static tbody tr {
    cursor: default;
}

.list-table.static tbody tr:hover {
    background: transparent;
}

.list-table.static tbody tr:nth-child(even):hover {
    background: var(--c-zebra);
}

.list-table th.col-amount,
.list-table td.col-amount {
    text-align: right;
    white-space: nowrap;
}

/* Добавление клиента: combo (растягивается) + кнопка, обе по высоте combo (34px) */
/* ═══════════════════════════════════════════════════════════════════════════
   Компоненты переноса дизайна из концепта (ui-concepts.html), этап 1.
   Матрица цен и отметка допуска в 4 состояниях сознательно НЕ заведены здесь:
   их негде показать (/Services снесён 01.08.2026, /Shift удалён 16.09.2026), а непроверенный
   глазом CSS на 24 поверхности — ровно то, от чего страхует ревизия этапа 4.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Выезжающая панель ──────────────────────────────────────────────────────
   ЕДИНСТВЕННЫЙ способ создать/поправить запись (решение 18.07.2026, этап 0).
   Модалка .trn-modal удалена этапом 5б — единственный способ правки записи это панель.
   Затемняющей подложки НЕТ намеренно: список слева обязан остаться читаемым,
   иначе панель ничем не отличается от модалки. Отрыв держит --shadow-panel. */
/* Метрика панели — из концепта (.drawer): ширина 520 по умолчанию, тень --shadow-lg. */
.dz-panel {
    position: fixed;
    top: 46px;      /* высота .app-topbar */
    right: 0;
    bottom: 0;
    z-index: 40;
    width: 520px;
    display: flex;
    flex-direction: column;
    background: var(--c-bg);
    border-left: 1px solid var(--c-border);
    box-shadow: var(--shadow-lg);
}

/* Форма с расходящимся набором полей (напр. участник взлёта: поля зависят от вида) */
.dz-panel.wide {
    width: 640px;
}

/* Панель идёт ПОВЕРХ контента и НЕ ужимает его (решение 18.07.2026, как в концепте).
   Раньше .panel-open добавлял padding-right, из-за чего при открытии панели таблица
   перекомпоновывалась и колонки прыгали. Класс оставлен: по нему JS понимает,
   что панель открыта, а вёрстку он больше не двигает. */
.panel-open {
    /* намеренно пусто — панель перекрывает, а не сжимает */
}

.dz-panel-head {
    display: flex;
    align-items: center;
    gap: 10px;
    flex: none;
    padding: 13px 16px;
    border-bottom: 1px solid var(--c-line);
}

.dz-panel-head svg {
    stroke: var(--c-accent);
}

.dz-panel-title {
    font-size: 14px;
    font-weight: 600;
}

/* Подзаголовок панели (что именно правим) — рядом с заголовком, не второй строкой */
.dz-panel-sub {
    color: var(--c-muted);
    font-size: 12.5px;
}

/* Закрытие — ghost-кнопка «✕ Esc» (концепт: .btn.ghost.sm), а НЕ квадратная иконка:
   подсказка про Esc должна читаться, поэтому это кнопка с текстом, без рамки и фона. */
.dz-panel-close {
    margin-left: auto;
    height: 25px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 0 8px;
    border: 1px solid transparent;
    border-radius: var(--r);
    background: none;
    color: var(--c-muted);
    font-size: 12px;
    font-weight: 500;
    line-height: 1;
}

.dz-panel-close:hover {
    background: var(--c-bg-panel);
    color: var(--c-text);
    text-decoration: none;
}

/* Форма растягивается на остаток высоты, прокручивается только ТЕЛО.
   Подвал — СОСЕДНИЙ блок тела, а не вложенный: так не воспроизводится дефект
   подвале модалки тренажа (белая полоса снизу из-за нижнего padding'а тела, pitfalls.md). */
.dz-panel-form {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
}

.dz-panel-body {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 13px;      /* отступ между блоками — gap контейнера, НЕ margin соседей */
    padding: 16px;
}

.dz-panel-foot {
    flex: none;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 11px 16px;
    border-top: 1px solid var(--c-line);
    background: var(--c-bg-alt);
}

/* ── МОДАЛКА (создание/правка по центру, с подложкой) ──────────────────────────
   Разворот решения об удалении модалок — пилот /People (21.07.2026), концепт
   docs/list-layout-concepts.html; РАСКАТАНА на все реестры 22.07.2026 (решение).
   Внутри модалки — те же .dz-panel-head/-form/-body/-foot, что у выезжающей
   панели: разметка формы и клавиатура (.js-panel-close, Ctrl+↵, клик по подложке)
   общие, различается только обёртка. Превью-колонка списка остаётся под подложкой —
   просмотр записи делается ДО открытия формы. .wide (640px) — богатые формы
   с вкладками (/RigSystems). */
.dz-modal-wrap {
    position: fixed;
    inset: 0;
    z-index: 50;            /* над топбаром/панелью (40); .dz-date-pop (60) остаётся выше модалки */
    display: grid;
    place-items: center;
    padding: 24px;
}

.dz-modal-scrim {
    position: absolute;
    inset: 0;
    background: var(--c-scrim);
}

.dz-modal {
    position: relative;
    width: 460px;
    max-width: 100%;
    max-height: calc(100vh - 48px);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    background: var(--c-bg);
    border: 1px solid var(--c-border);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-lg);
}

.dz-modal.wide {
    width: 640px;
}

/* ── ДИАЛОГ ПОДТВЕРЖДЕНИЯ (.dz-confirm, строит JS — dzConfirm в site.js, 08.08.2026) ──
   Заменяет СИСТЕМНЫЙ confirm(): тот умеет только «ОК/Отмена», а спрашивать приходится
   выбор из нескольких действий («удалить участника» / «удалить группу»), да и вид его
   задаёт браузер. Слой и шапка/подвал — те же, что у модалки формы, поэтому Esc и клик
   по подложке работают общими обработчиками. Уже 420px: в диалоге одна фраза, и окно
   шириной с форму выглядело бы полупустым. */
.dz-confirm {
    width: 420px;
}

/* Диалог с ТРЕМЯ подписями в подвале («Остаться» · «Уйти без сохранения» · «Сохранить и уйти» —
   сторож ухода dzLeaveGuard): в 420px они не встают в строку и подвал ломается на две. */
.dz-confirm.roomy {
    width: 520px;
}

.dz-confirm .dz-panel-body {
    padding: 16px;
}

.dz-confirm-text {
    margin: 0;
    line-height: 1.45;
}

/* Затрагиваемые записи — СПИСКОМ (правка 08.08.2026): из перечисления через запятую не видно
   ни ролей, ни того, кого именно удаляют, а решают именно по этому. Строка списка = имя +
   приглушённое уточнение (роль · система); та, с которой позвали диалог, подсвечена. */
.dz-confirm-list {
    margin: 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

/* Имя и уточнение — В СТОЛБИК, а не в строку (правка 08.08.2026): длинное ФИО и «Тандем
   (Инструктор) · Stealth_340 (С+Ж)» в одной строке переносились каждое по-своему, и список
   выходил рваным. В столбик строки списка выровнены всегда, чем бы их ни заполнили. */
.dz-confirm-list li {
    padding: 7px 10px;
    border-radius: var(--r-sm);
    background: var(--c-bg-alt);
}

.dz-confirm-list li.is-current {
    background: var(--c-danger-bg);
    box-shadow: inset 3px 0 0 var(--c-danger);
}

.dz-confirm-li-name {
    display: block;
    font-weight: 600;
}

.dz-confirm-li-note {
    display: block;
    margin-top: 1px;
    color: var(--c-muted);
    font-size: 12px;
    line-height: 1.35;
}

/* Заголовок диалога несёт ФИО — на длинном имени он не должен ломать шапку */
.dz-confirm .dz-panel-title {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.dz-confirm-hint {
    margin: 10px 0 0;
    font-size: 12px;
    line-height: 1.45;
    color: var(--c-muted);
}

/* Подвал диалога: «Отменить» у ЛЕВОЙ границы, действия прижаты к правой, самое приоритетное —
   крайнее правое (как «Сохранить» в формах: главное действие всегда в одном углу). Перенос
   строки — на случай трёх длинных подписей в узком окне. */
.dz-confirm .dz-panel-foot {
    flex-wrap: wrap;
}

.dz-confirm .dz-panel-foot .js-panel-close {
    margin-right: auto;
}

/* Основное действие диалога — единственная ЗАЛИТАЯ danger-кнопка в приложении: в ряду
   из двух опасных действий приоритет должен читаться до чтения подписей. */
.btn-danger.pri {
    background: var(--c-danger);
    border-color: var(--c-danger);
    color: var(--c-on-accent);
}

.btn-danger.pri:hover {
    filter: brightness(1.08);
}

/* Модалка «Новый спортсмен» — высота по содержимому: «умное» поле рисует выпадашку слоем
   position:fixed ПОВЕРХ модалки (см. .pp-pop), поэтому запас высоты под список больше не нужен. */

/* ── Поля внутри панели — метрика концепта (.fld / .inp) ──────────────────────
   Отличается от полей в строке фильтров: там контролы 30px (--ctl), здесь поля
   формы 32px. Так в концепте, и разнобоя это не создаёт — поля и кнопки панели
   стоят в разных зонах (тело / подвал), а не в одной строке. */
.dz-panel .field-grid {
    grid-template-columns: 1fr 1fr;
    gap: 13px 14px;
    margin-bottom: 0;
}

/* Поле на всю ширину сетки — растягиваем на обе колонки, а не заводим свою сетку.
   Правило ОБЩЕЕ для .field-grid (25.09.2026): прежде оно было привязано к .dz-panel/.dz-modal,
   и на карточке справочника (/Aircraft/Details, форма в .blk) «Модель» и «Примечание»
   с классом wide стояли в одну колонку — правило блока молча перестало работать при
   переезде формы из модалки (тот же урок, что с `.pagination .disabled`). */
.dz-panel .field-grid:not(.cols-2) > label,
.field-grid > label.wide {
    grid-column: 1 / -1;
}

/* Подпись поля: мельче основного текста и с весом — иначе не читается как подпись */
.dz-panel .field-grid label > span:first-child {
    font-size: 11.5px;
    font-weight: 500;
    color: var(--c-muted);
    margin-bottom: 4px;
}

.dz-panel .field-grid label {
    gap: 0;
}

.dz-panel .field-grid input:not([slot]):not(.dz-inner),
.dz-panel .field-grid select,
.dz-panel .dz-date {
    height: 32px;
}

.dz-panel .dzs-btn {
    height: 32px;
}

/* Часы и минуты одним полем-парой: время вылета вводят с клавиатуры, попап тут лишний */
.time-fields {
    display: flex;
    align-items: center;
    gap: 6px;
}

/* Метрика ЗДЕСЬ, а не в наследство от `.field-grid`: компонент обязан выглядеть одинаково
   в любом контейнере. Пока тут стояла только ширина, высоту давали правила `.field-grid`, и в
   полосе параметров взлёта (`.afld`, вне грида) поля времени приехали 25px против 30px у
   соседей — гистограмма высот дала две группы (ловленый дефект, design-system.md). */
.time-fields input {
    width: 60px;
    height: var(--ctl);
    border: 1px solid var(--c-border);
    border-radius: var(--r);
    padding: 0 9px;
    font-size: 13px;
    font-family: inherit;
    background: var(--c-bg);
    color: var(--c-text);
}

    .time-fields input:focus {
        outline: 0;
        border-color: var(--c-accent);
        box-shadow: 0 0 0 3px var(--c-accent-bg);
    }

.time-fields-sep {
    color: var(--c-faint);
}

/* ── Сегменты (перенос концепта 1:1, .seg) ──────────────────────────────────
   Фильтр на 2–4 варианта вместо выпадающего списка: варианты видны сразу,
   выбор — один клик, состояние в URL (кнопки «Применить» нет).
   Вид — ПИЛЮЛЯ: серая подложка-контейнер, активный вариант «всплывает» белым
   с лёгкой тенью. Прежний вариант (рамка + заливка активного акцентом) заменён,
   потому что концепт объявлен источником вида 1:1 (см. design-system.md). */
.dz-seg {
    display: flex;
    background: var(--c-bg-panel);
    border-radius: var(--r);
    padding: 2px;
}

.dz-seg-item {
    display: flex;
    align-items: center;
    gap: 6px;
    height: 26px;
    padding: 0 10px;
    border: 0;
    border-radius: 4px;
    background: none;
    font-size: 12px;
    font-weight: 500;
    line-height: 1;
    color: var(--c-muted);
    cursor: pointer;
}

.dz-seg-item:hover {
    color: var(--c-text);
    text-decoration: none;
}

/* Вес НЕ меняем при выборе (как у строк таблицы): жирный текст шире обычного,
   и соседние сегменты дёргались бы при каждом переключении. */
.dz-seg-item.active {
    background: var(--c-bg);
    color: var(--c-text);
    box-shadow: var(--shadow-sm);
}

/* Лента взлётов дня (.load-strip) удалена 29.08.2026 вместе с v6: вкладки шапки листа — .ltab
   в секции «Составление взлётов /Loads» ниже. */

/* ═══════════════════════════════════════════════════════════════════════════
   Таблица-редактор состава взлёта (.sheet, концепт docs/loadlog-editor-concepts.html).
   В покое неотличима от списка: значения текстом, никаких постоянных рамок-инпутов.
   Ховер — рамка-приглашение с кареткой, клик — редактор прямо в ячейке (JS «sheet»
   в site.js), сохранение — htmx-POST строкой.

   ОДИН СКИН НА ДВЕ ТАБЛИЦЫ (30.08.2026): здесь же живёт лист составления `/Loads`
   (`.composer-sheet`) — журнал и лист это ОДНА таблица-редактор в двух режимах, а не два
   похожих экрана. Всё общее (сетка колонок, ячейка имени, отметки, полоса группы, попап
   словаря) описано в этой секции; в секции `/Loads` ниже остаётся только то, чего у журнала
   нет вовсе: шапка группы блоком, свободные слоты, хват, панель посадки. ═══ */

/* ── Сетка: ширины КЛАССАМИ, раскладка фиксированная, тянется одна колонка «Участник» ──
   `table-layout: fixed` обязателен: auto-раскладка на мониторе шире клиентского растаскивает
   вид/высоту/систему по всей ширине (поймано на показе /Loads 30.08.2026). Тянуть оставляем
   имя — оно длиннее всех и в журнале пишется полностью. */
.sheet {
    width: 100%;
    /* Ниже этой ширины таблица прокручивается в своей обёртке, а не жмёт колонки: при
       fixed-раскладке нехватка места ужимает ВСЕ колонки пропорционально. 830 ≈ сумма колонок
       листа составления (у клиента он самый узкий: вьюпорт 1366 → лист 836). */
    min-width: 830px;
    table-layout: fixed;
}

/* Ширины подобраны по МИНИМУМУ содержимого колонки (подпись шапки или самое длинное значение):
   при table-layout: fixed таблица всё равно не ужимается ниже min-content, и колонка уже минимума
   просто раздувает таблицу с горизонтальной прокруткой. */
.sheet .col-grip { width: 20px; }
.sheet .col-place { width: 54px; }
.sheet .col-group { width: 68px; }
/* Журнал: «Участник» забирает ВСЮ свободную ширину (решение заказчика 25.09.2026), хвоста-филлера
   нет — прежде имя стояло 260px, а остаток (≈190px на экране клиента) уходил в пустую колонку.
   Минимум имени держит min-width таблицы: 830 − сумма остальных колонок ≈ 118px. У листа
   составления /Loads имя фиксированное и филлер свой — см. .composer-sheet ниже по файлу. */
.sheet .col-name { width: auto; }
.sheet .col-jt { width: 168px; }   /* «Тандем (Инструктор)» + каретка */
.sheet .col-alt { width: 62px; }
.sheet .col-rig { width: 140px; }
.sheet .col-mk { width: 46px; }        /* «Укл.» */
.sheet .col-mk-rent { width: 60px; }   /* «Аренда» — подпись длиннее */
.sheet .col-mk-hc { width: 54px; }     /* «Хенди» */
.sheet .col-actions { width: 60px; }
.sheet .col-fill { width: 0; padding: 0; }   /* хвост в журнале схлопнут: ширину забирает «Участник» */

/* Значение в ячейке не ломает колонку: длинное — многоточием */
.sheet .sheet-val {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Участник — подлежащее строки: имя весом выделено из служебных значений */
.sheet .col-name .sheet-val {
    font-weight: 600;
}

/* Ячейки-значения сами держат высоту строки и padding — рамка состояния идёт по границе td */
.sheet td {
    padding: 0;
}

/* Номер места — служебная нумерация: приглушена, вправо (класс .num), у строк группы бледнее */
.sheet td.col-place {
    padding: 0 10px;
    color: var(--c-faint);
    font-size: 11px;
    font-weight: 600;
}

.sheet tr.g td.col-place {
    color: var(--c-border);
}

/* Ячейка участника — теперь .sheet-cell (замена человека): отступ несёт ячейка, td нулевой,
   иначе ховер-рамка плавала бы коробочкой с двойным отступом (фидбек 23.07.2026) */
.sheet td.col-name {
    padding: 0;
}

.sheet td.mid,
.sheet td.col-actions {
    text-align: center;
}

/* Пикер приёмника — с 23.07.2026 плоский (см. .sheet .pp-field ниже): td без отступов */
.sheet td.sheet-person-td {
    padding: 0;
}

/* Пикер ВНУТРИ таблицы-редактора выглядит ЯЧЕЙКОЙ, а не полем-коробкой (фидбек 23.07.2026:
   скруглённая рамка выбивалась из «острой» таблицы; концепт рисует ФИО-ввод плоской .cell).
   Состояния — те же, что у .sheet-cell: ховер-приглашение, акцентная рамка в фокусе. */
.sheet .pp-field {
    height: var(--row);
    border: 0;
    border-radius: 0;
    background: none;
    padding: 0 10px;
}

.sheet .pp-field:hover {
    box-shadow: inset 0 0 0 1px var(--c-border);
    background: var(--c-bg-alt);
}

.sheet .pp-field:focus-within {
    box-shadow: inset 0 0 0 2px var(--c-accent);
    background: var(--c-bg);
}

/* Плейсхолдер-приглашение в ячейке (концепт .cell .ph, УСИЛЕН по фидбеку 23.07.2026:
   приглушённый серый «не читался точкой входа») — акцентный «＋ Выберите вид прыжка…».
   position:absolute ОБЯЗАТЕЛЕН: текст длиннее колонки раздувал авто-ширину, а при открытии
   редактора она схлопывалась — колонка прыгала (тот же класс граблей, что width:0 у
   .sheet-inp). Абсолютный спан в расчёт ширины колонки не входит вовсе. */
.sheet-ph {
    position: absolute;
    left: 10px;
    right: 10px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--c-accent);
    pointer-events: none;
}

/* Заглушка «сначала вид прыжка» умного приёмника: ro-факт, но кликабельный —
   клик открывает редактор вида (пайплайн «вид → человек», решение 23.07.2026) */

.sheet .pp {
    width: 100%;
}

.sheet-cell {
    position: relative;   /* якорь абсолютного плейсхолдера .sheet-ph */
    display: flex;
    align-items: center;
    gap: 6px;
    height: var(--row);
    padding: 0 10px;
    cursor: text;
}

.sheet-cell.num {
    justify-content: flex-end;
    font-variant-numeric: tabular-nums;
}

/* Ячейка колонки «Группа» (08.08.2026): метка Г1/Г2 — служебный маркер связи, а не данные
   строки, поэтому мельче и приглушённее прочих значений; каретка прижата к метке (колонка
   узкая, 56px, и margin-left:auto растащил бы их по краям). Пустая ячейка одиночной строки
   так и остаётся пустой — «нет группы» не пишем, это шум на каждой второй строке. */
.sheet-groupcell {
    justify-content: center;
    gap: 2px;
    padding: 0 4px;
    font-size: 12px;
    color: var(--c-muted);
}

.sheet-groupcell .sheet-caret {
    margin-left: 0;
}

.sheet-caret {
    margin-left: auto;
    color: var(--c-faint);
    font-size: 10px;
    visibility: hidden;
}

.sheet-cell.num .sheet-caret {
    display: none; /* у числовой ячейки каретка не нужна — там не список */
}

.sheet-cell:not(.ro):hover {
    box-shadow: inset 0 0 0 1px var(--c-border);
    background: var(--c-bg-alt);
}

.sheet-cell:not(.ro):hover .sheet-caret,
.sheet-cell:not(.ro):focus .sheet-caret {
    visibility: visible;
}

.sheet-cell:not(.ro):focus {
    outline: 0;
    box-shadow: inset 0 0 0 1px var(--c-accent-border);
}

.sheet-cell.is-editing {
    box-shadow: inset 0 0 0 2px var(--c-accent);
    background: var(--c-bg);
    cursor: text;
}

/* ro-«факт»: значение видно, но правится НЕ здесь (роль группы, система тандем-клиента,
   высота непервых строк группы) — приглушение отличает его от редактируемых ячеек
   (фидбек 23.07.2026: «не видно, что поле read-only»). */
.sheet-cell.ro {
    cursor: default;
    color: var(--c-faint);
}

/* Редактор на месте значения — без своей рамки, рамку держит ячейка.
   width: 0 ОБЯЗАТЕЛЕН: у таблицы авто-раскладка, и врождённая ширина голого input
   (~170px от дефолтного size="20") больше узкой колонки («Высота» 90px) — при открытии
   редактора колонка прыгала вширь. Ноль убирает вклад инпута в ширину колонки,
   а видимую ширину всё равно даёт flex: 1 (basis 0 → растёт на всю ячейку). */
.sheet-cell > .sheet-inp {
    flex: 1;
    width: 0;
    min-width: 0;
    height: 100%;
    border: 0;
    outline: 0;
    background: transparent;
    padding: 0;
    margin: 0;
    font: inherit;
    color: inherit;
}

.sheet-cell.num > .sheet-inp {
    text-align: right;
}

/* Крутилки числового поля в ячейке не нужны: значение вводят с клавиатуры, а стрелки
   съедают ширину колонки и выдают ячейку-редактор за постоянное поле ввода. */
.sheet-cell > .sheet-inp[type=number] {
    -moz-appearance: textfield;
    appearance: textfield;
}

    .sheet-cell > .sheet-inp[type=number]::-webkit-outer-spin-button,
    .sheet-cell > .sheet-inp[type=number]::-webkit-inner-spin-button {
        margin: 0;
        -webkit-appearance: none;
        appearance: none;
    }

/* Ошибка правки: строка подсвечена, причина — плашкой строкой ниже */
.sheet tr.is-error > td {
    background: var(--c-danger-bg);
}

.sheet tr.sheet-errrow > td {
    padding: 3px 10px 8px;
}

.sheet-errtip {
    display: inline-block;
    font-size: 11.5px;
    color: var(--c-danger);
    background: var(--c-danger-bg);
    border: 1px solid var(--c-danger-border);
    border-radius: var(--r);
    padding: 3px 8px;
}

/* Строка-приёмник: постоянная пустая строка внизу; черновик (человек выбран, минимум
   не собран) — жёлтая метка, как «строка ещё НЕ записана» */
.sheet tr.sheet-new > td {
    border-bottom: 0;
}

.sheet tr.sheet-new .sheet-placecol {
    color: var(--c-faint);
}

.sheet tr.sheet-draft {
    background: var(--c-warn-bg);
}

.sheet tr.sheet-draft > td:first-child {
    box-shadow: inset 3px 0 0 var(--c-warn-border);
}

/* Сброс черновика виден всегда, пока черновик есть (не по ховеру, как у обычных строк) */
.sheet .sheet-draft-reset:not([hidden]) {
    visibility: visible;
}

/* Словарный попап ячейки (вид прыжка / система). Осознанное исключение из правила
   «словарь = dz-select» (оно писалось для ФОРМ): у ячейки редактор живёт прямо в ней,
   без кнопки-поля. position:fixed — как .pp-pop/.dz-date-pop (pitfalls.md). */
.sheet-pop {
    position: fixed;
    z-index: 60;
    min-width: 240px;
    max-width: 380px;
    overflow-y: auto;
    background: var(--c-bg);
    border: 1px solid var(--c-border);
    border-radius: var(--r);
    box-shadow: var(--shadow-lg);
}

/* Пункт словаря. В журнале это div (попап строит site.js), в листе — button (шаг уходит
   htmx-POST'ом), поэтому здесь же сброс кнопочного вида: без него пункт-кнопка рисовался
   серой пилюлей по ширине текста (поймано 30.08.2026). Один пункт — один вид на двух экранах. */
.sheet-opt {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 7px 11px;
    border: 0;
    border-bottom: 1px solid var(--c-line-row);
    border-radius: 0;
    background: none;
    font: inherit;
    font-size: 12.5px;
    color: var(--c-text);
    text-align: left;
    cursor: pointer;
    white-space: nowrap;
}

.sheet-opt:last-child {
    border-bottom: 0;
}

.sheet-opt:hover,
.sheet-opt.on {
    background: var(--c-accent-bg);
}

/* Занятый пункт словаря (система уже стоит на другой строке этого взлёта): выбрать нельзя,
   поэтому гасим строку, снимаем ховер и уводим её в конец списка (JS). Причина — чипом
   справа, теми же цветами, что у занятого человека в .pp-opt. */
.sheet-opt.taken {
    opacity: .55;
    cursor: default;
}

.sheet-opt.taken:hover {
    background: transparent;
}

/* Приписка справа — ФАКТ («№2 · 3 чел.», «заготовкой на потом»): нейтральна. Красной плашкой
   она становится только у ЗАНЯТОГО пункта, где это отказ («уже в этом взлёте, место 4»). */
.sheet-opt-note {
    margin-left: auto;
    color: var(--c-faint);
    font-size: 10.5px;
    line-height: 17px;
}

.sheet-opt.taken .sheet-opt-note {
    padding: 0 6px;
    border-radius: 5px;
    background: var(--c-danger-bg);
    color: var(--c-danger);
    font-size: 11px;
}

.sheet-pop-empty {
    padding: 9px 11px;
    color: var(--c-faint);
    font-size: 12.5px;
}

/* Подсказка по работе с ячейками — справа в тулбаре состава */
.ptools-hint {
    font-size: 11.5px;
    color: var(--c-faint);
}

/* ═══════════════════════════════════════════════════════════════════════════
   Рабочая область по концепту `docs/ui-concepts.html` (перенос 1:1, 18.07.2026).
   Соответствие: .work-head = .work-head, .wh-1 = .wh-1, .filters = .filters,
   .tw = .tw, .tfoot = .tfoot. Заголовок раздела живёт ЗДЕСЬ (в строке действий
   .wh-1). Страница с собственными действиями/фильтрами ставит ViewData["OwnHead"]=true
   и рисует .wh-1 сама; остальным .wh-1 (якорь + заголовок) рисует _Layout.
   ═══════════════════════════════════════════════════════════════════════════ */

/* Оболочка рабочей области: шапка и подвал фиксированы, прокручивается только .tw */
.work-wrap {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

.work-head {
    padding: 0;
    flex: none;
}

/* ── СТРОКА ДЕЙСТВИЙ (action bar) ─────────────────────────────────────────────
   Первая строка рабочей области (.wh-1). Слева — постоянный навигационный якорь
   (partial _ActionNav: стрелки + крошка «назад»), затем заголовок и счётчик;
   справа — действия страницы (создание, экспорт…). Якорь стоит на одном месте
   на каждом экране — предсказуемое «назад» под курсором (решение 20.07.2026,
   концепт docs/actionbar-concepts.html). Заголовок здесь не выносить в отдельную
   строку — он часть бара. */
.wh-1 {
    display: flex;
    align-items: center;
    gap: 9px;
    height: 46px;
    margin: 0;
    padding: 0 12px 0 8px;
    border-bottom: 1px solid var(--c-line);
    background: var(--c-bg);
}

.wh-1 h1,
.wh-1 h2 {
    margin: 0;
    font-size: 17px;
    font-weight: 600;
    white-space: nowrap;   /* бар — одна строка фикс. высоты; заголовок не переносим */
}

/* Счётчик рядом с заголовком («42 взлёта») — сколько всего в разделе */

.wh-1 .app-spacer {
    flex: 1;
}

/* Навигационный якорь (partial _ActionNav) — теперь только крошка «назад».
   Классы .ab-arrow и .ab-div удалены 02.08.2026 вместе со стрелками истории
   (решение пользователя): навигацию назад даёт браузер. */
.ab-nav {
    display: flex;
    align-items: center;
    gap: 3px;
    flex: none;
}

.ab-back {
    color: var(--c-muted);
    font-size: 12.5px;
    text-decoration: none;
    white-space: nowrap;
}

.ab-back:hover {
    color: var(--c-text);
}

.ab-sep {
    color: var(--c-faint);
}

/* Основное действие в шапке — акцент-контур (решение 20.07.2026, уточнено 21.07.2026):
   светлая подложка + акцентный текст. Тише сплошной заливки, «вписано» в строку.
   Кнопка «Создать» (единый текст «+ Создать» на всех реестрах) стоит ПЕРВОЙ в строке
   фильтров .filters (слева от поиска), а не в баре справа — так основное действие рядом
   с полем поиска, а не в дальнем углу. Стиль общий для .wh-1 (прочие действия бара —
   экспорт, импорт) и .filters. Заливку (.btn-primary по умолчанию) держим только в
   подвалах панелей/форм, где «Создать»/«Сохранить» — финальное подтверждение. */
.wh-1 .btn-primary,
.filters .btn-primary,
/* «В чек»/«Записать» в служебных формах кассы — то же действие по смыслу: основное в своём
   блоке, но не финальное подтверждение документа (им остаётся залитое «Провести»). */
.pos-form .btn-primary {
    background: var(--c-accent-bg);
    border-color: var(--c-accent-border);
    color: var(--c-accent-dark);
}

.wh-1 .btn-primary:hover,
.filters .btn-primary:hover,
.pos-form .btn-primary:hover {
    background: var(--c-accent-bg-hover);
    border-color: var(--c-accent);
}

/* Кнопка «Создать» — первая в строке фильтров, слегка отделена от контролов поиска */
.filters > .btn-primary {
    margin-right: 4px;
}

/* «Удалить взлёт» в баре сохранения карточки взлёта (перенесена из строки заголовка
   .wh-1 в .card-save-bar, 24.07.2026): форма-обёртка не должна ломать flex-ряд. */
.card-save-bar form {
    margin: 0;
}

/* Фильтры под баром получают свои отступы (раньше их держал padding .work-head) */
.work-head .filters {
    padding: 10px 16px;
}

/* Панель сохранения карточки взлёта (решение 24.07.2026): явный раздел между строкой действий
   и блоком «Параметры взлёта» — та же граница снизу, что у .wh-1 сверху и у .loadform снизу
   (просьба 24.07.2026: «сделать как у параметров взлёта снизу»). */
.card-save-bar {
    border-bottom: 1px solid var(--c-line);
    background: var(--c-bg);
}

/* Вторая строка шапки: фильтры. Кнопки «Применить» нет — фильтр применяется сам,
   состояние живёт в URL. */
.filters {
    display: flex;
    align-items: center;
    gap: 8px;
    padding-bottom: 10px;
    flex-wrap: wrap;
}

.filters .search {
    height: var(--ctl);
    width: 190px;
    border: 1px solid var(--c-border);
    border-radius: var(--r);
    padding: 0 9px;
    font-size: 13px;
    font-family: inherit;
    background: var(--c-bg-alt);
    color: var(--c-text);
}

.filters .search:focus {
    outline: 0;
    border-color: var(--c-accent);
    background: var(--c-bg);
    box-shadow: 0 0 0 3px var(--c-accent-bg);
}

.filters .search::placeholder {
    color: var(--c-faint);
}

/* Период: подпись + два КОМПАКТНЫХ поля даты. Ширина по содержимому «01.07.2026»,
   а не растянутая: в концепте поле даты — короткая плашка, и растянутое на 205px
   поле было главной причиной, почему строка фильтров читалась иначе. */
.daterange {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 12.5px;
    color: var(--c-muted);
}

.daterange .dz-date {
    width: 124px;
    flex: none;
}

.daterange .d {
    height: var(--ctl);
    display: flex;
    align-items: center;
    border: 1px solid var(--c-border);
    border-radius: var(--r);
    padding: 0 9px;
    background: var(--c-bg);
    color: var(--c-text);
    font-variant-numeric: tabular-nums;
}

/* Чип-фильтр «+ Борт»: пунктир, пока не задан; сплошной акцентный, когда выбран */
.fchip {
    height: var(--ctl);
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 0 9px;
    border: 1px dashed var(--c-border);
    border-radius: var(--r);
    color: var(--c-muted);
    font-size: 12.5px;
    background: none;
    cursor: pointer;
}

.fchip:hover {
    text-decoration: none;
    border-color: var(--c-accent-border);
    color: var(--c-text);
}

/* Когда чип — это <select>, ширину ему диктует САМЫЙ ДЛИННЫЙ пункт списка, и вместо
   компактной кнопки «+ Борт» получается широкое поле. Фиксируем по подписи. */
select.fchip {
    width: 92px;
    font-family: inherit;
    appearance: none;
    background-image: none;
}

.fchip.set {
    border-style: solid;
    border-color: var(--c-accent-border);
    background: var(--c-accent-bg);
    color: var(--c-accent-dark);
    font-weight: 500;
}

/* Обёртка таблицы: единственный прокручиваемый блок рабочей области */
.tw {
    flex: 1;
    min-height: 0;
    overflow: auto;
    border-top: 1px solid var(--c-line);
}

/* Подвал списка: итоги вместо пагинации — «Показано N из M · Прыжков за период: K» */
.tfoot {
    flex: none;
    min-height: 46px;   /* вровень с верхним action bar (46px) — нижняя полоса весомее */
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 0 14px;
    border-top: 1px solid var(--c-line);
    background: var(--c-bg-alt);
    font-size: 12px;
    color: var(--c-muted);
}

.tfoot b {
    color: var(--c-text);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

.tfoot .app-spacer {
    flex: 1;
}

/* Тумблер в подвале таблицы (карточка взлёта: «Определять группы автоматически», 08.08.2026).
   Кликается вся подпись; кегль подвала мельче тела, поэтому галочка прижата к тексту без
   лишнего воздуха. Полоса подвала уже есть — тумблер не стоит ни пикселя вертикали. */
.tfoot-toggle {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    cursor: pointer;
    white-space: nowrap;
}

.tfoot-toggle input {
    margin: 0;
}

/* ── Пагинатор подвала (партиал `_Pager`) ────────────────────────────────────
   Кнопки страниц и позиция — ОДИН сегмент в общей рамке, а не три соседа: подвал
   разводит своих детей на gap:16px, и отдельные «‹», «Стр. N из M», «›» читались
   как несвязанные элементы (поймано 02.08.2026). Высота 26px — контрол подчинён
   тексту итогов, а не спорит с ним, как прежние .btn-secondary (30px). */
.pager {
    display: inline-flex;
    align-items: stretch;
    height: 26px;
    border: 1px solid var(--c-border);
    border-radius: var(--r-sm);
    overflow: hidden;
    background: var(--c-bg);
}

.pager-btn {
    width: 27px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--c-text-soft);
    text-decoration: none;
}

.pager-btn:hover {
    background: var(--c-bg-hover);
    text-decoration: none;
}

/* Шеврон рисуем SVG, а не глифом ‹ ›: типографские кавычки в шрифте интерфейса мелкие
   и сидят выше базовой линии — стрелка получалась смещённой вверх от центра кнопки. */
.pager-btn svg {
    width: 13px;
    height: 13px;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}

/* Край списка (первая/последняя страница): гасим и КЛИК, а не только цвет. */
.pager-btn.disabled {
    pointer-events: none;
    color: var(--c-faint);
    background: var(--c-bg-alt);
}

.pager-pos {
    display: inline-flex;
    align-items: center;
    padding: 0 9px;
    border-left: 1px solid var(--c-line);
    border-right: 1px solid var(--c-line);
    font-size: 11.5px;
    font-variant-numeric: tabular-nums;
    color: var(--c-muted);
    white-space: nowrap;
}

/* Индикатор автосохранения (карточка взлёта): точка + «Все изменения сохранены»; ошибка
   встаёт на его место текстом причины. Кнопки «Сохранить» на странице нет — шапка пишется
   по выходу из поля (решение 22.07.2026, концепт docs/loadlog-editor-concepts.html). */
.saveind {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    color: var(--c-muted);
}

.saveind .dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--c-ok);
}

.saveind.err {
    color: var(--c-danger);
}

/* Несохранённые изменения (буфер простого режима /LoadLog/Details, решение 24.07.2026):
   индикатор становится предупреждающим, точка — янтарной. Черновик (`.draft`, правка
   01.08.2026) — тот же вид: взлёта ещё нет в БД, и зелёное «сохранено» там врало бы. */
.saveind.dirty,
.saveind.draft {
    color: var(--c-warn);
    font-weight: 500;
}

.saveind.dirty .dot,
.saveind.draft .dot {
    background: var(--c-warn);
}

/* ── Список с превью-колонкой (Вариант В) ────────────────────────────────────
   Клик по строке = выбор + read-only превью справа; правка (dblclick / «Изменить»
   / Enter) превращает ту же колонку в форму. Одна модель на все реестры
   (решение 20.07.2026, концепт docs/list-preview-concepts.html). В отличие от
   выезжающей .dz-panel — колонка В ПОТОКЕ, список рядом с ней, а не под ней. */
.worksplit {
    flex: 1;
    min-height: 0;
    display: flex;
}

/* Левая колонка: таблица + подвал-итоги, скроллится только .tw внутри */
.listpane {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

/* Правая колонка — ТОЛЬКО read-only просмотр (создание/правка — модалка .dz-modal,
   решение 22.07.2026). Концепт задавал 300px, расширена до 400px по фидбеку:
   карточке при 1920 просторнее, списку всё ещё остаётся с запасом. */
.lprev {
    width: 400px;
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    border-top: 1px solid var(--c-line);
    border-left: 1px solid var(--c-line);
    background: var(--c-bg-alt);
}

/* Шапка колонки: имя записи + подпись + бейдж режима */
.lprev-h {
    flex: none;
    display: flex;
    align-items: flex-start;
    gap: 9px;
    padding: 11px 13px;
    border-bottom: 1px solid var(--c-line);
    background: var(--c-bg);
}

.lprev-h .t {
    font-size: 14px;
    font-weight: 600;
    letter-spacing: -.01em;
}

.lprev-h .s {
    font-size: 11.5px;
    color: var(--c-muted);
    margin-top: 2px;
}

.lprev-mode {
    margin-left: auto;
    flex: none;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    padding: 2px 6px;
    border-radius: 4px;
}

.lprev-mode.ro {
    background: var(--c-bg-panel);
    color: var(--c-faint);
}

/* Тело просмотра — единственный скроллящийся блок колонки */
.lprev-b {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    padding: 12px 13px;
}

/* Подвал колонки («Открыть → / Изменить») ОБЯЗАН быть одной высоты с подвалом-итогами
   списка .tfoot (46px) — тогда нижняя полоса идёт сплошной через обе колонки. Высоту
   держит min-height, а не вертикальный padding: кнопки 30px (--ctl) центрируются в 46px. */
.lprev-f {
    flex: none;
    display: flex;
    align-items: center;
    gap: 8px;
    min-height: 46px;
    padding: 0 16px;
    border-top: 1px solid var(--c-line);
    background: var(--c-bg-alt);
}

.lprev-f .app-spacer {
    flex: 1;
}

/* read-only строки превью: «ключ — значение» */
.pv-sec {
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--c-faint);
    margin: 15px 0 6px;
}

.pv-sec:first-child {
    margin-top: 0;
}

.pv-row {
    display: flex;
    align-items: baseline;
    gap: 9px;
    padding: 4px 0;
    font-size: 12.5px;
    border-bottom: 1px solid var(--c-line-row);
}

.pv-row:last-child {
    border-bottom: 0;
}

.pv-row .k {
    width: 108px;
    flex: 0 0 auto;
    color: var(--c-muted);
    font-size: 12px;
}

.pv-row .v {
    flex: 1;
    min-width: 0;
}

/* Пустое состояние — ничего не выбрано */
.lprev-empty {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 24px;
    text-align: center;
    color: var(--c-faint);
    font-size: 12.5px;
}

.lprev-empty svg {
    width: 26px;
    height: 26px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.5;
    opacity: .55;
}

/* Клавиатурная подсказка на кнопке (концепт: kbd в «+ Новый взлёт N») */
kbd {
    font: 11px/1 var(--mono);
    background: var(--c-bg);
    /* рамка со всех сторон, нижняя толще — «объём» клавиши (концепт) */
    border: 1px solid var(--c-border);
    border-bottom-width: 2px;
    border-radius: 4px;
    padding: 3px 5px;
    color: var(--c-muted);
    display: inline-block;
    vertical-align: middle;
}

.btn-primary kbd {
    margin-left: 2px;
    background: var(--c-on-accent-veil);
    border-bottom-color: var(--c-on-accent-line);
    color: var(--c-on-accent);
}

/* ── Ячейки списка по концепту (аватар + ФИО, приглушённые детали, чип способа) ── */

/* Второстепенная деталь в ячейке: время рядом с датой, комментарий, «—».
   Мельче основного текста строки — иначе она с ним спорит по весу. */
.cell-sub {
    color: var(--c-faint);
    font-size: 11.5px;
    font-weight: 400;
}

/* Человек в ячейке: кружок с инициалами + ФИО */
.cell-p {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}

.avatar-sm {
    width: 20px;
    height: 20px;
    flex: none;
    border-radius: 50%;
    background: var(--c-av-bg);
    color: var(--c-av-fg);
    display: grid;
    place-items: center;
    font-size: 9px;
    font-weight: 600;
}

    /* Цвет по роли (концепт): спортсмен — акцент, сотрудник — фиолетовый, клиент — серый */
    .avatar-sm.ac { background: var(--c-accent-bg); color: var(--c-accent-dark); }
    .avatar-sm.emp { background: var(--c-emp-av-bg); color: var(--c-emp-fg); }

/* Приглушённый чип — значение-факт (способ оплаты), а не статус: цветом не кричим.
   Рамки нет — в концепте это заливка surface-3 без обводки. */
.chip-mute {
    background: var(--c-bg-panel);
    border-color: transparent;
    color: var(--c-muted);
}

/* Денежная колонка: моноширинные цифры, чуть плотнее по весу */
.list-table td.money {
    font-variant-numeric: tabular-nums;
    font-weight: 500;
}

/* Действие в строке — компактная кнопка (концепт: .btn.xs) */
.btn-xs {
    height: 21px;
    padding: 0 6px;
    font-size: 11.5px;
    border-radius: var(--r);
}

/* Действия строки ПОЯВЛЯЮТСЯ ПО НАВЕДЕНИЮ (концепт: .rowact { opacity: 0 }).
   Постоянно видимая кнопка в каждой строке — это столбец шума на весь список;
   работать с записью начинают, уже наведя на неё курсор. */
.list-table td.col-actions {
    text-align: right;
    padding-right: 12px;
}

.list-table td.col-actions .btn-xs {
    opacity: 0;
}

.list-table tbody tr:hover td.col-actions .btn-xs,
.list-table tbody tr.active td.col-actions .btn-xs,
.list-table td.col-actions .btn-xs:focus-visible {
    opacity: 1;
}

/* Подпись-пояснение ПОД полем («строго больше нуля», «по умолчанию — перевод»).
   Не путать с .field-hint: тот — callout доменного правила, этот — тихая сноска. */
/* Специфичность нарочно поднята: `.field-grid span` (0-1-1) перебивал одиночный
   `.field-note` (0-1-0), и сноска набиралась кеглем подписи вместо своих 11px. */
.field-note,
.field-grid .field-note {
    display: block;
    margin-top: 4px;
    font-size: 11px;
    color: var(--c-faint);
}

/* Сообщение над списком (напр. «запись вне текущего фильтра») */
.work-notice {
    margin: 0 16px 10px;
}

/* ═══════════════════════════════════════════════════════════════════════════
   ВЫПЛАТЫ СОТРУДНИКАМ (перенос из docs/ui-concepts.html, раздел «Выплаты»)
   Токены концепта → наши: --line-strong = --c-border, --line = --c-line,
   --surface-2 = --c-bg-alt, --surface-3 = --c-bg-panel, --accent-soft = --c-accent-bg.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Карточка сущности: хлебная крошка, шапка, показатели ── */
.card-head {
    padding: 14px 16px 0;
    border-bottom: 1px solid var(--c-line);
    background: var(--c-bg);
    flex: 0 0 auto;
}

.ch-1 { display: flex; align-items: flex-start; gap: 14px; }
.ch-name { font-size: 19px; font-weight: 600; letter-spacing: -.02em; margin-bottom: 6px; }
.ch-meta { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }

.stats { display: flex; margin-top: 15px; }

.stat {
    padding: 0 20px 13px 0;
    margin-right: 20px;
    border-right: 1px solid var(--c-line);
}

    .stat:last-child { border-right: 0; }
    .stat .k { font-size: 11.5px; color: var(--c-muted); margin-bottom: 3px; }

    .stat .v {
        font-size: 16px;
        font-weight: 600;
        font-variant-numeric: tabular-nums;
        letter-spacing: -.01em;
    }

        .stat .v small { font-size: 11.5px; font-weight: 500; color: var(--c-faint); margin-left: 4px; }

/* ── Баннер состояния документа (проведён / предупреждение) ── */
.banner {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 0 16px 10px;
    padding: 9px 12px;
    border-radius: var(--r);
    font-size: 12.5px;
}

    .banner.closed { border: 1px solid var(--c-border); background: var(--c-bg-panel); color: var(--c-text-soft); }
    .banner.closed b { color: var(--c-text); }
    .banner.warn { border: 1px solid var(--c-warn-border); background: var(--c-warn-bg); color: var(--c-warn-ink); }
    .banner.warn b { color: var(--c-warn); }

/* Свой margin плашки (0 16px 10px) рассчитан на полосу во всю ширину рабочей области. Внутри
   тела модалки/панели и превью отступы держит контейнер, и там плашка стояла на 16px уже полей
   с обеих сторон (25.09.2026; тот же приём, что у .dz-panel-body .error-message выше по файлу).
   В превью отбивку снизу держит правило, а не инлайн-стиль на каждой из десяти страниц. */
.dz-panel-body .banner {
    margin: 0;
}

.lprev-b .banner {
    margin: 0 0 12px;
}

/* Сегменты как ПОЛЕ ФОРМЫ (способ оплаты/выплаты в кассах), а не как фильтр по URL.
   Радиокнопка скрыта, но остаётся в форме и доступна с клавиатуры — рисуем её подпись.
   Нативный <select> здесь запрещён общим правилом (своя высота и стрелка), а combo из двух
   пунктов в узкой полосе проведения выглядел бы тяжелее самой полосы. */
.dz-seg-radio input {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
    pointer-events: none;   /* страховка: даже если текст-правило .field-grid растянет скрытый radio, он не должен перехватывать клики — переключаем по label */
}

/* position: relative — якорь для скрытого radio (25.09.2026). Без него radio с position:absolute
   отсчитывал размеры от ОКНА: `.field-stack input:not([slot]):not(.dz-inner)` (0,3,1) перебивает
   его width:0 своим width:100%, и на карточке физлица поле «Пол» раздувало документ до 1398px
   при окне 1349 — страница прокручивалась вбок. Теперь 100% — это ширина самой подписи. */
.dz-seg-radio {
    position: relative;
    display: inline-flex;
    align-items: center;
    height: 28px;
    padding: 0 12px;
    font-size: 13px;
    color: var(--c-text-soft);
    border-right: 1px solid var(--c-border);
    cursor: pointer;
}

    .dz-seg-radio:last-child { border-right: 0; }
    .dz-seg-radio:hover { background: var(--c-bg-hover); }
    .dz-seg-radio:has(input:focus-visible) { outline: 2px solid var(--c-accent); outline-offset: -2px; }

/* Сегмент-поле внутри трека `.dz-seg` — ОДИН вид на все такие поля (пол, способ выплаты,
   способ оплаты в кассе): серый трек + белая приподнятая пилюля у выбранного, как у
   сегментов-фильтров `.dz-seg-item` на реестрах. Ни синей заливки, ни разделителей.
   Правило было привязано к `.field-stack` (08.08.2026 отвязано): вне обёртки тот же
   контрол получал сплошную синюю заливку, и «Перевод/Наличные» в кассе выглядели третьим
   вариантом одного и того же переключателя. Две равные половины; трек и его padding 2px
   дают итоговую высоту 30px = --ctl. */
.dz-seg .dz-seg-radio {
    flex: 1;
    justify-content: center;
    height: 26px;
    padding: 0 10px;
    border-right: 0;
    border-radius: 4px;
    font-size: 12px;
    font-weight: 500;
    color: var(--c-muted);
}

.dz-seg .dz-seg-radio:hover {
    background: none;
    color: var(--c-text);
}

.dz-seg .dz-seg-radio:has(input:checked) {
    background: var(--c-bg);
    color: var(--c-text);
    box-shadow: var(--shadow-sm);
}

/* ── Карточка сущности: две колонки (перенос концепта) ──────────────────────
   Список — главное содержимое, реквизиты ужаты в узкую колонку слева.
   Применено на странице одного инструктажа: у него всего четыре реквизита,
   а список прошедших и есть смысл записи. */
.card-body {
    flex: 1;
    min-height: 0;
    display: flex;
}

.card-aside {
    width: 266px;
    flex: 0 0 auto;
    border-right: 1px solid var(--c-line);
    background: var(--c-bg-alt);
    overflow: auto;
    padding: 14px;
}

.card-main {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.asec {
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--c-faint);
    margin: 20px 0 7px;
}

    .asec:first-child { margin-top: 0; }

/* Поле «подпись сверху» в узкой колонке реквизитов: .field-grid здесь не подходит —
   она двухколоночная, а в 266px колонке подпись и поле встают друг под другом. */
.field-stack {
    display: block;
    margin-bottom: 10px;
}

    .field-stack > span {
        display: block;
        font-size: 11.5px;
        font-weight: 500;
        color: var(--c-muted);
        margin-bottom: 4px;
    }

    .field-stack select,
    .field-stack input:not([slot]):not(.dz-inner) {
        width: 100%;
        height: var(--ctl);
        border: 1px solid var(--c-border);
        border-radius: var(--r);
        padding: 0 9px;
        font-size: 13px;
        font-family: inherit;
        background: var(--c-bg);
        color: var(--c-text);
    }

/* Строка действий над списком внутри карточки (добавление человека).
   СВОЙ класс, а не .filters: site.js вешает на .filters автоотправку формы, и на <div>
   это падало бы с TypeError при первом же выборе в combo (form.submit не функция). */
.card-main-bar {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 11px 14px;
    border-bottom: 1px solid var(--c-line);
    flex: 0 0 auto;
}

    .card-main-bar b { font-size: 12.5px; }

/* «Не задана» — осмысленное состояние, а не отсутствие данных: набирается словами
   и приглушённым, чтобы не читаться как сумма. */
.list-table td.money.none {
    color: var(--c-faint);
    font-weight: 400;
}

/* Отрицательная сумма в чеке (скидка у оплаты, удержание у выплаты) — красным: строка
   с минусом обязана читаться минусом, а не «просто числом». */
.list-table td.money.neg {
    color: var(--c-danger);
}

/* Два действия в колонке строки (Изменить + Убрать). Форма нужна ради POST'а, но блочной
   она переносила бы вторую кнопку на свою строку и раздувала строку таблицы вдвое. */
.list-table td.col-actions { white-space: nowrap; }

    .list-table td.col-actions form { display: inline-block; }

    .list-table td.col-actions .btn-xs + .btn-xs,
    .list-table td.col-actions form { margin-left: 4px; }

/* ── Карточка взлёта: полоса параметров + состав (перенос концепта, «Создание взлёта») ──
   Взлёт — рабочий документ, а не карточка-справка: параметры правят прямо здесь, поэтому
   вместо `.card-head` со `.stats` идёт компактная полоса полей над составом. */
.loadform {
    flex: 0 0 auto;
    padding: 13px 16px 15px;
    border-bottom: 1px solid var(--c-line);
    background: var(--c-bg-alt);
}

/* Заголовок полосы параметров. Flex остался с поры, когда справа стояла кнопка «Свернуть»
   (сворачивание шапки убрано 02.08.2026); у единственного текстового потомка вид не меняется. */
.lf-sec {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--c-faint);
    margin-bottom: 9px;
}

    .lf-sec .app-spacer { flex: 1; }

/* Свёрнутой шапки взлёта (.loadhead-fact — строка-факт вместо полосы полей, решение
   01.08.2026) БОЛЬШЕ НЕТ: сворачивание убрано 02.08.2026 по просьбе заказчика — параметры
   правят по ходу заполнения журнала, и клик «✎ Параметры» стоил дороже сэкономленных 67px.
   Полоса .loadform теперь всегда развёрнута. */
.lf-row {
    display: flex;
    align-items: flex-end;
    gap: 12px;
}

    .lf-row + .lf-row { margin-top: 11px; }

/* Строка действий полосы параметров: без flex распорка .app-spacer ничего не растягивала
   и «Отмена»/«Сохранить параметры» стояли слева вместо правого края (30.08.2026). */
.lf-acts {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 11px;
}

/* Поле полосы параметров: подпись сверху, узкая фиксированная ширина.
   ОТСТУПЛЕНИЕ ОТ КОНЦЕПТА, намеренное: там высота поля 31px при кнопках 30px — в главной
   рабочей области это дало бы две группы в гистограмме высот, а это ловленый дефект
   (design-system.md). Держим --ctl; 1px на глаз неразличим, вторая группа — заметна. */
.afld {
    flex: 0 0 auto;
    min-width: 0;
}

    .afld.grow1 { flex: 1; }

    .afld > label {
        display: block;
        font-size: 10.5px;
        font-weight: 500;
        color: var(--c-muted);
        margin-bottom: 3px;
    }

    /* Только ПРЯМЫЕ потомки: у составных полей (.time-fields, combo, dz-date) свои
       внутренние инпуты, и width:100% ломал бы их раскладку — грабля из pitfalls.md. */
    .afld > input:not([slot]):not(.dz-inner),
    .afld > select,
    /* .numpick — составное поле (инпут + каретка), поэтому прямым потомком .afld не является;
       вид у него ровно тот же, что у обычного поля, — держим одним правилом. */
    .afld > .numpick > input {
        width: 100%;
        height: var(--ctl);
        border: 1px solid var(--c-border);
        border-radius: var(--r);
        padding: 0 9px;
        /* 13px, а не 12.5 из концепта: рядом в той же строке стоят combo, а у них по
           дизайн-системе 13px — разнокегль внутри одной строки заметнее, чем полкегля к макету. */
        font-size: 13px;
        font-family: inherit;
        background: var(--c-bg);
        color: var(--c-text);
    }

        .afld > input:not([slot]):not(.dz-inner):focus,
        .afld > .numpick > input:focus {
            outline: 0;
            border-color: var(--c-accent);
            box-shadow: 0 0 0 3px var(--c-accent-bg);
        }

    /* Поле-число с быстрым списком: ходовые значения выпадают попапом, но список НЕ замкнут —
       любое число вводится руками (высота взлёта, просьба 24.07.2026 «как при добавлении
       участника»). Поэтому ни <select>, ни vaadin-combo, а тот же лёгкий попап, что у ячейки
       высоты в .sheet. Каретка нарисована поверх правого паддинга и НЕ ловит клики: попадание
       уходит в сам инпут, он же и раскрывает список. */
    .afld > .numpick > input {
        padding-right: 20px;
    }

.numpick {
    position: relative;
}

    /* Спиннеры числового поля убраны — их работу взял список, вместе они рябят */
    .numpick > input::-webkit-outer-spin-button,
    .numpick > input::-webkit-inner-spin-button {
        -webkit-appearance: none;
        margin: 0;
    }

    .numpick > input[type=number] {
        -moz-appearance: textfield;
    }

    .numpick-caret {
        position: absolute;
        right: 8px;
        top: 50%;
        transform: translateY(-50%);
        font-size: 9px;
        line-height: 1;
        color: var(--c-faint);
        pointer-events: none;
    }

/* Попап пресетов (один на страницу). position:fixed — как .sheet-pop/.pp-pop/.dz-date-pop
   (pitfalls.md: попап внутри прокручиваемой области обрезается). */
.numpick-pop {
    position: fixed;
    z-index: 60;
    max-height: 260px;
    overflow-y: auto;
    background: var(--c-bg);
    border: 1px solid var(--c-border);
    border-radius: var(--r);
    box-shadow: var(--shadow-lg);
}

.numpick-opt {
    padding: 7px 11px;
    font-size: 12.5px;
    text-align: right;   /* числа читаются по правому краю, как в колонке «Высота» */
    white-space: nowrap;
    cursor: pointer;
    border-bottom: 1px solid var(--c-line-row);
}

    .numpick-opt:last-child {
        border-bottom: 0;
    }

    .numpick-opt:hover,
    .numpick-opt.on {
        background: var(--c-accent-bg);
    }

    /* Значение-«факт» на месте поля (дата непустого взлёта): по концепту это .fixed —
       пунктирная рамка говорит «показано фактом, не выбор». */
    .afld > .afld-fact {
        display: inline-flex;
        align-items: center;
        width: 100%;
        height: var(--ctl);
        padding: 0 9px;
        border: 1px dashed var(--c-border);
        border-radius: var(--r);
        font-size: 13px;
        color: var(--c-muted);
        background: var(--c-bg-alt);
    }

/* Тулбар состава .ptools УДАЛЁН 01.08.2026 (низкий экран клиента): полоса стоила 41px
   постоянной высоты ради заголовка, дублировавшего колонки таблицы, и счётчика, который
   и так стоит в подвале. Подсказка по ячейкам (.ptools-hint) переехала в .tfoot и класс
   свой сохранила — он описывает роль текста, а не место. */

/* Отметка в ячейке — состояние, не галочка/пусто. Три явных состояния переключаемой отметки
   журнала (укладка, аренда, хенди; решение 06.09.2026): `.yes` — есть (✓ на зелёной), `.off` —
   явное «нет» (✕ на нейтральной: «уложил сам» и «аренды нет» — нормальные состояния, красный
   `.mk.no` здесь был бы враньём), `.ro` — недоступно: тот же глиф ✓/✕, но без заливки и бледный,
   клика нет (строка-зеркало клиента тандема — значение принадлежит инструктору). Прочерк `.na`
   переключаемой отметке НЕ ставится (заказчик, 06.09.2026): до этого «нет» и «недоступно»
   рисовались одним прочерком — их путали. */
.mk {
    display: inline-grid;
    place-items: center;
    width: 22px;
    height: 22px;
    border-radius: 5px;
    font-size: 12px;
    font-weight: 700;
}

    .mk.yes { background: var(--c-ok-bg); color: var(--c-ok); }
    .mk.no { background: var(--c-danger-bg); color: var(--c-danger); }
    /* «Нет» — плотная серая плашка с тёмным глифом: от белого фона и от бледного «недоступно»
       отличается и заливкой, и контрастом (06.09.2026: на --c-bg-alt/--c-muted не отличалось). */
    .mk.off { background: var(--c-bg-panel); color: var(--c-text-soft); }
    .mk.na { background: transparent; color: var(--c-faint); font-weight: 400; font-size: 13px; }
    /* Отметка-ЗЕРКАЛО (строка клиента тандема, 08.08.2026) и замок хенди по виду: класс глушит
       клик (site.js). Вид «недоступно» (06.09.2026): значение видно, но контрол «выключен» —
       без заливки, пунктирная рамка, бледный глиф, полупрозрачно. Три состояния должны
       различаться с первого взгляда: ✓ зелёная плашка / ✕ серая плашка / пунктир без заливки. */
    .mk.ro {
        background: transparent;
        color: var(--c-faint);
        border: 1px dashed var(--c-border);
        opacity: .6;
        cursor: default;
    }

/* Отметка-КНОПКА (журнал взлётов: «Укл.», «Аренда», «Хенди» — клик переключает). Сброс глобального
   `button` (padding 6px 14px, рамка, фон): без него квадрат 22px раздувался до 30×22 с рамкой, а
   поля сдвигали его вниз ячейки. Правило удалили 16.09.2026 вместе с досками /Shift как «мёртвое»,
   хотя носитель — журнал — жив; возвращено 25.09.2026. `.mk.ro` (0,2,0) перебивает border:0
   своей пунктирной рамкой. */
button.mk {
    border: 0;
    padding: 0;
    cursor: pointer;
    font: inherit;
    font-size: 12px;
    font-weight: 700;
}

    button.mk:hover { outline: 1px solid var(--c-border); }
    button.mk.ro:hover { outline: 0; }

.list-table th.mid,
.list-table td.mid { text-align: center; }

/* Группа манифеста (тандем, обучение): манифест ПЛОСКИЙ — одно место одна строка,
   ничего не сворачивается. Связь внутри группы показывает полоса слева, границу между
   группами — линия сверху у первой строки. Роль читается из колонки «Вид прыжка». */
.list-table tr.g td:first-child { box-shadow: inset 2px 0 0 var(--c-accent-border); }
.list-table tr.g.g-first td { border-top: 1px solid var(--c-line); }
.list-table tr.g.g-first td:first-child { box-shadow: inset 2px 0 0 var(--c-accent); }

/* ── Группы в таблице-редакторе журнала (.sheet): ЦВЕТ вместо линии-разделителя ──────────
   (1) Линия сверху у первой строки группы УБРАНА (08.08.2026): border-collapse у таблицы
   separate, поэтому она не сливалась с разделителем предыдущей строки, а вставала ВТОРОЙ —
   тёмная двойная полоса читалась как лишний отступ перед группой. Разделять группы больше
   нечем и не нужно: их различает цвет и метка Г1/Г2 в колонке «Группа».
   (2) Цвет группы едет переменной --c-grp (класс .group-N ставят и сервер, и site.js по НОМЕРУ
   группы во взлёте), полоса у всех строк группы одинаковая: раньше первая строка красилась
   плотнее остальных — это отвечало «где группа началась», но не «кто с кем».
   Палитра — ТА ЖЕ, что у групп манифеста на /Loads (--c-group-0..4, классы .group-N ниже):
   второй набор «цветов групп» в дизайн-системе заводить нельзя, один смысл — один набор. */
/* Запасной цвет группы (класс .group-N ещё не проставлен) — специфичность та же, что у .group-N
   ниже, и порядок решает: иначе `.sheet tr.g` перебивал бы цвет группы акцентом. */
.g { --c-grp: var(--c-accent); }

/* Класс .group-N задаёт ПЕРЕМЕННУЮ и ничего не рисует — поэтому он не привязан к таблице:
   его носят и строки листа/журнала, и карточка заготовки в хранилище (цвет вида прыжка). */
.group-0 { --c-grp: var(--c-group-0); }
.group-1 { --c-grp: var(--c-group-1); }
.group-2 { --c-grp: var(--c-group-2); }
.group-3 { --c-grp: var(--c-group-3); }
.group-4 { --c-grp: var(--c-group-4); }

.sheet tr.g.g-first td { border-top: 0; }

.sheet tr.g td:first-child,
.sheet tr.g.g-first td:first-child { box-shadow: inset 3px 0 0 var(--c-grp); }

/* Метка в колонке «Группа» — основным текстом, цвет группы несёт только полоса слева
   (25.09.2026). Палитра --c-group-* категориальная, для МЕТОК: текстом на белом янтарь
   давал 2.2:1, розовый 2.7, зелёный 2.8 — «Г1» не читалась. Какая это группа, метка
   говорит номером, а не цветом. */
.sheet tr.g .sheet-groupcell {
    color: var(--c-text);
    font-weight: 600;
}

/* ── Полосы-предупреждения листа составления /Loads ───────────────────────────────────────
   Остаток вытесненного «бланка взлёта» (концепт 5): сам бланк (.paper/.slot/.composer-main,
   контейнер-скроллер .composer-sheet с padding 16/18 и фоном страницы, чипы «люди дня»,
   всплывашка .movepop, подвал .paper-f, .cap-bar) удалён 30.08.2026 — им никто не пользовался
   с переписывания /Loads на v10, а имя .composer-sheet у контейнера СТОЛКНУЛОСЬ с таблицей
   состава v10 и дарило ей отступ сверху/слева и фон (ровно та коллизия имён, о которой
   предупреждает pitfalls.md). Живыми из блока остались только эти две полосы. */
.overbar {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 7px 16px;
    background: var(--c-warn-bg);
    border-bottom: 1px solid var(--c-warn-border);
    font-size: 12px;
    color: var(--c-warn);
}
    .overbar b { font-weight: 600; }

/* Обмен взлётов местами: подсказка-полоса под лентой дня */
.swapbar {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0 16px 11px;
    padding: 7px 11px;
    border-radius: var(--r);
    border: 1px solid var(--c-warn-border);
    background: var(--c-warn-bg);
    color: var(--c-warn);
    font-size: 12.5px;
}
    .swapbar b { font-weight: 600; }
    .swapbar .app-spacer { flex: 1; }

/* Показатель шапки, значение которого — не число, а слово или дата: кегль числа (16px)
   на «не задана» читается как заголовок, а не как значение. */
.stat .v.v-text {
    font-size: 14px;
    font-weight: 500;
}

    .stat .v.v-none { color: var(--c-faint); }

/* Кнопка выбора файла — <label> поверх скрытого input[type=file]: нативный
   контрол не стилизуется и приносит свою типографику, ломая ряд контролов. */
.import-pick {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    cursor: pointer;
    white-space: nowrap;
}

.import-result {
    margin: 0 0 10px;
    padding: 8px 11px;
    border: 1px solid var(--c-ok-border);
    border-radius: var(--r);
    background: var(--c-ok-bg);
    color: var(--c-ok);
    font-size: 13px;
}

.import-list {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--c-border);
    border-radius: var(--r);
}

.import-row {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 0 10px;
    height: 30px;
    cursor: pointer;
    font-size: 13px;
}

.import-row + .import-row {
    border-top: 1px solid var(--c-line);
}

.import-row:hover {
    background: var(--c-bg-hover);
}

/* Имя занимает остаток строки, чип «уже есть» прижат вправо */
.import-name {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Телефон · рост · вес из файла — справа от имени, приглушённо: это довесок, а решение
   «заводить или нет» принимается по ФИО. flex: 0 0 auto — довесок не жмёт имя, а имя
   при нехватке места ужимается многоточием (оно и так flex: 1). */
.import-extra {
    flex: 0 0 auto;
    color: var(--c-faint);
    font-size: 11.5px;
    white-space: nowrap;
}

.import-foot-note {
    margin-right: auto;
    color: var(--c-faint);
    font-size: 11.5px;
}

/* ── Демо-данные (/Admin/DemoData) ──
   Страница не список, поэтому ни .tw, ни .list-* ей не подходят — нужен только отступ тела
   под шапкой. 16px по бокам берётся от .work-head (13px 16px 0), чтобы статистика и подсказки
   стояли на одной вертикали с заголовком; .app-content с его 18px дал бы уступ в 2px. */
.demo-body {
    padding: 0 16px 16px;
    max-width: 760px;
}

    /* У .stats свой margin-top под шапку карточки; здесь блок идёт первым, отступ лишний */
    .demo-body .stats { margin-top: 0; }

/* ── Бекап и восстановление (/Admin/Backup) ──
   Та же служебная страница, что демо-данные: не список, телу нужны только отступы;
   вертикальные зазоры между блоками держит gap контейнера, а не margin соседей. */
.backup-body {
    padding: 0 16px 16px;
    max-width: 760px;
    display: flex;
    flex-direction: column;
    gap: 13px;
}

    .backup-body .stats { margin-top: 0; }

/* Загрузка файла и пара «Восстановить/Отмена» — flex-ряды на общих правилах.
   Формы-обёртки отдельных кнопок не должны вести себя как блоки. */
.backup-upload,
.backup-actions {
    display: flex;
    align-items: center;
    gap: 8px;
}

    .backup-actions form { display: contents; }

/* ── Настройки сервиса (/Admin/Settings, 08.08.2026) ───────────────────────────────────────
   Тумблеры списком: галочка слева, название и пояснение справа. Строка — сама <label>,
   поэтому кликается целиком, а не одним квадратиком 13px. */
.settings-body {
    padding: 0 16px 16px;
    max-width: 760px;
}

.settings-lead {
    margin: 0 0 4px;
    color: var(--c-muted);
}

.set-group {
    display: flex;
    flex-direction: column;
    gap: 2px;
    border: 1px solid var(--c-line);
    border-radius: var(--r);
    padding: 4px;
}

.set-row {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 9px 10px;
    border-radius: var(--r-sm);
    cursor: pointer;
}

.set-row:hover {
    background: var(--c-bg-hover);
}

.set-row input {
    margin: 2px 0 0;
    flex: none;
}

.set-text {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.set-name {
    font-weight: 600;
}

.set-hint {
    font-size: 12px;
    color: var(--c-muted);
}

/* Список копий на сервере живёт в теле страницы, вне .tw — рамка своя */
.backup-files {
    border: 1px solid var(--c-line);
    border-radius: var(--r);
}

/* Колонки отметок — по центру */
.list-table th.mid,
.list-table td.mid { text-align: center; }

/* Акцентная микро-кнопка — «следующий шаг» строки (концепт .btn.xs.pri) */
.btn-xs.pri {
    background: var(--c-accent);
    border-color: var(--c-accent);
    color: var(--c-on-accent);
}

    .btn-xs.pri:hover { background: var(--c-accent-dark); }

/* Группа «Период» — компонент несёт свою раскладку САМ (грабли .time-fields):
   раньше стили жили только под .search-bar, и в строке .filters группа складывалась
   в столбик (поймано на /Briefings при переносе) */
.date-range {
    display: flex;
    align-items: center;
    gap: 8px;
}

.date-range-label {
    color: var(--c-muted);
    font-size: 12px;
}

.date-range-sep {
    color: var(--c-faint);
}

/* ── Хаб «Справочники» (/Dictionaries, этап 5б) ──────────────────────────────────────────
   Настройка ДЗ свёрнута из восьми пунктов меню в один: сюда заходят раз в месяц.
   Плитка — карточка с иконкой, названием и подсказкой «что внутри». */
.hub-body {
    padding: 4px 16px 16px;
    overflow: auto;
}

    .hub-body .field-section { margin-top: 14px; }

.hub-tiles {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 10px;
    margin-top: 10px;
    max-width: 1060px;
}

.hub-tile {
    display: grid;
    grid-template-columns: 20px 1fr;
    gap: 3px 10px;
    align-items: center;
    padding: 12px 14px;
    border: 1px solid var(--c-border);
    border-radius: var(--r);
    background: var(--c-bg);
    color: var(--c-text);
    text-decoration: none;
}

    .hub-tile:hover {
        background: var(--c-bg-hover);
        border-color: var(--c-accent-border);
        text-decoration: none;   /* иначе глобальное a:hover (0-1-1) подчёркивает текст плитки */
    }

    .hub-tile svg {
        grid-row: 1 / 3;
        color: var(--c-accent);
    }

.hub-tile-name {
    font-weight: 600;
    font-size: 13px;
}

.hub-tile-sub {
    grid-column: 2;
    font-size: 11.5px;
    color: var(--c-faint);
}

/* ── Перетаскивание строк реестра = порядок (drag-and-drop; пилот — /Catalog «Типы прыжков»,
   компонент с 31.08.2026 — см. `data-reorder-url` в site.js; применён также на категориях
   оплат и выплат). Грип ⠿ в первой колонке; тянуть можно только за него (клик по строке —
   по-прежнему просмотр). ── */
.ord-grip-cell {
    text-align: center;
    padding-left: 4px;
    padding-right: 4px;
}

.ord-grip {
    display: inline-block;
    color: var(--c-faint);
    cursor: grab;
    font-size: 14px;
    line-height: 1;
    letter-spacing: -1px;
    user-select: none;
    /* Крупнее сам символ — но клик-зона на всю ячейку (грип центрирован) */
    padding: 2px 4px;
}

    .ord-grip:hover {
        color: var(--c-muted);
    }

    .ord-grip:active {
        cursor: grabbing;
    }

/* Строка в процессе перетаскивания — приглушаем, чтобы её «тень» была видна на новом месте */
tr.ord-dragging {
    opacity: .45;
    background: var(--c-accent-bg);
}

/* Курсор захвата на всей перетаскиваемой строке в момент удержания грипа */
tr[draggable="true"] .ord-grip {
    cursor: grab;
}

/* ── Ручной порядок стрелками (категории кассы и их состав) ──────────────────
   Порядок правится стрелками, а не полем «номер»: номера пришлось бы перебивать
   у соседей руками. Размер кнопок 26×24 — тот же минимум мишени, что у степпера
   количества в чеке (18×20 оказались малы для мыши, замер 08.08.2026). */
.ord {
    display: inline-flex;
    border: 1px solid var(--c-border);
    border-radius: 5px;
    overflow: hidden;
    background: var(--c-bg);
}

    .ord button {
        width: 26px;
        height: 24px;
        padding: 0;
        border: 0;
        background: none;
        color: var(--c-muted);
        font: inherit;
        font-size: 12px;
        line-height: 24px;
        cursor: pointer;
    }

        .ord button + button { border-left: 1px solid var(--c-line); }

        .ord button:hover:not(:disabled) {
            color: var(--c-accent-dark);
            background: var(--c-accent-bg);
        }

        /* Край списка — не ошибка: кнопка гаснет и не кликается, ругаться не за что */
        .ord button:disabled {
            color: var(--c-faint);
            cursor: default;
        }

/* Приглушённая приписка в строке превью (цена рядом с названием позиции) */
.pv-dim { color: var(--c-muted); }

/* ── Касса (/Payments/Create, этап 3 плана кассы) ────────────────────────────
   Перенос классов .pos-* из концепта billing-concepts.html (экран 2) на токены.
   Слева чек-форма фиксированной ширины, справа панель кнопок из справочника
   позиций; чек набирается ТОЛЬКО кнопками (предикт — отдельный этап). */
.pos {
    flex: 1;
    min-height: 0;
    display: flex;
}

.pos-check {
    width: 420px;
    flex: 0 0 auto;
    border-right: 1px solid var(--c-line);
    display: flex;
    flex-direction: column;
    background: var(--c-bg);
}

/* Бланк оплаты — верхний блок колонки чека: человек, деньги и кнопки ОДНОЙ группой
   (вариант А концепта payment-layout-concepts.html, 14.08.2026). До этого поле «кто платит»
   стояло в шапке, а итог с кнопками — в подвале у самого дна: между ними 496px, и при
   обычном чеке в 3–5 строк это была сплошная пустота («кнопки прижаты вниз», «кто платит и
   кнопки в разных местах» — фидбек заказчика 14.08.2026). Побочно выиграна строка чека
   (13 вместо 12): у подвала были свои padding и граница, теперь их нет.
   Подписи «Кто платит» по-прежнему нет — её несёт плейсхолдер, и кнопок рядом с полем нет
   («＋» рядом с человеком читается как «добавить второго»). */
.pos-head-block {
    flex: 0 0 auto;
    padding: 9px 13px;
    background: var(--c-bg-alt);
    border-bottom: 1px solid var(--c-border);
    display: flex;
    flex-direction: column;
    gap: 8px;
}

    /* Полоса денег: способ слева, итог справа — в одной строке, а не двумя полосами */
    .pos-head-block .pos-total { align-items: center; }

    /* Кнопки во всю ширину колонки: главное действие смены получает цель 193px вместо 81 */
    .pos-head-block .pos-actions > button { flex: 1; }

    /* Ошибка проведения — внутри блока, прямо над кнопками: сообщение появляется там,
       куда в этот момент смотрят. Отступы гасим (вертикальный держит gap блока). */
    .pos-head-block .error-message {
        margin: 0;
        font-weight: 500;
    }

.pos-lines {
    flex: 1;
    min-height: 0;
    overflow: auto;
    padding: 4px 0;
}

.pos-line {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 13px;
    font-size: 12.5px;
    min-height: 34px;
    border-bottom: 1px solid var(--c-line-row);
}

    /* Только что добавленная строка вспыхивает: подтверждение, что нажатие плитки дошло,
       без взгляда на итог. Гасит её JS через ~1 сек. */
    .pos-line.new { background: var(--c-accent-bg); }

    .pos-line .nm {
        flex: 1;
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

        /* Цена за единицу — только при N > 1: при одной штуке сумма и есть цена */
        .pos-line .nm .sub {
            color: var(--c-muted);
            font-size: 11px;
        }

/* Степпер количества: три одинаковых прыжка — ОДНА строка «×3», а не три строки.
   Размер кнопок 26×26 — не косметика: 18×20 (первая редакция) ниже комфортного минимума
   для мыши, и по «−» промахивались (фидбек 08.08.2026). Вертикаль строки при этом НЕ
   выросла — компенсировано её padding'ом 6→4px, строк чека по-прежнему 12. */
.qty {
    display: inline-flex;
    align-items: center;
    height: 26px;
    flex: 0 0 auto;
    border: 1px solid var(--c-border);
    border-radius: 5px;
    overflow: hidden;
    background: var(--c-bg);
}

    .qty button {
        width: 26px;
        height: 24px;
        padding: 0;
        border: 0;
        background: none;
        color: var(--c-muted);
        font: inherit;
        font-size: 14px;
        line-height: 24px;
        cursor: pointer;
    }

        .qty button:hover { color: var(--c-accent-dark); background: var(--c-accent-bg); }

        .qty button:active { background: var(--c-accent-border); }

    .qty b {
        min-width: 26px;
        align-self: stretch;
        line-height: 24px;
        text-align: center;
        font-size: 12.5px;
        font-weight: 600;
        font-variant-numeric: tabular-nums;
        border-left: 1px solid var(--c-line);
        border-right: 1px solid var(--c-line);
    }

    /* Скидка количеством не набирается — место под степпер сохраняем, чтобы строки
       не «прыгали» по левому краю */
    .qty.qty-none { visibility: hidden; }

    /* Автоматическая скидка: КОЛИЧЕСТВО видно (два комплекта в чеке дают ×2), а кнопок нет —
       кратность считает правило, руками её не правят. Место под кнопки сохраняем той же
       хитростью, что у .qty-none: иначе строка скидки поедет по левому краю. */
    .qty.qty-fixed button { visibility: hidden; cursor: default; }

    .pos-line .amt {
        font-variant-numeric: tabular-nums;
        font-weight: 500;
        white-space: nowrap;
    }

        .pos-line .amt.neg { color: var(--c-danger); }

    /* «×» — намеренно тихая кнопка: удаление строки чека — частое исправление, не событие */
    /* Мишень «убрать строку» — 26×26, как у степпера: тихая по цвету, но не мелкая */
    .pos-line .rm {
        border: 0;
        border-radius: 4px;
        background: none;
        color: var(--c-faint);
        font-size: 16px;
        line-height: 1;
        width: 26px;
        height: 26px;
        padding: 0;
        flex: 0 0 auto;
        cursor: pointer;
    }

        .pos-line .rm:hover {
            color: var(--c-danger);
            background: var(--c-danger-bg);
        }

.pos-empty {
    color: var(--c-faint);
    font-size: 12.5px;
    padding: 24px 20px;
    text-align: center;
    line-height: 1.6;
}

    .pos-empty b {
        display: block;
        color: var(--c-muted);
        font-weight: 600;
        margin-bottom: 3px;
    }

/* Комментарий к оплате: заводится плиткой на панели, а виден здесь — иначе о нём
   забудут, а он уедет в документ. Полосы нет, пока комментарий не заполнен. */
.pos-note {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 7px 13px;
    background: var(--c-bg-alt);
    border-top: 1px solid var(--c-line);
    font-size: 12px;
    color: var(--c-muted);
}

    .pos-note .k {
        flex: 0 0 auto;
        color: var(--c-faint);
    }

    .pos-note .v {
        flex: 1;
        min-width: 0;
        color: var(--c-text);
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    .pos-note .rm {
        border: 0;
        background: none;
        color: var(--c-faint);
        font-size: 14px;
        line-height: 1;
        padding: 0;
        cursor: pointer;
    }

        .pos-note .rm:hover { color: var(--c-danger); }

/* Ошибка проведения — общая плашка приложения (.error-message), а не свой класс: до 11.08.2026
   тут стоял `.errline`, которого в CSS НЕ БЫЛО ВОВСЕ, и сообщение рисовалось обычным абзацем —
   «ошибку плохо видно» (фидбек заказчика). Урок тот же, что с [hidden] на display:flex: перед
   разбором «почему выглядит не так» — проверить, что правило вообще существует.
   Само правило гашения отступов — у `.pos-head-block .error-message` выше. */

.pos-total {
    display: flex;
    align-items: baseline;
    gap: 8px;
}

    /* Счётчик позиций забирает свободное место: способ слева, сумма прижата к правому краю */
    .pos-total .k {
        flex: 1;
        text-align: right;
        color: var(--c-muted);
        font-size: 12.5px;
    }

    .pos-total .v {
        font-size: 22px;
        font-weight: 700;
        font-variant-numeric: tabular-nums;
    }

.pos-actions {
    display: flex;
    align-items: center;
    gap: 8px;
}

/* Панель: поиск и вкладки не прокручиваются вместе с плитками — иначе поиск уезжает
   из-под руки ровно тогда, когда он нужен. */
.pos-panel {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    padding: 9px 14px 12px;
    background: var(--c-bg-alt);
    display: flex;
    flex-direction: column;
}

.pos-panel-scroll {
    flex: 1;
    min-height: 0;
    max-width: 1040px;
    overflow: auto;
}

/* Ширины ограничены: на мониторе 1920 панель ~1300px, и без потолка поиск растягивался
   во всю стену (подсказка «↵ в чек» уезжала на 1300px от поля), а плитки вставали в 9
   колонок вместо четырёх. На клиентских 1366 потолок не достигается и ничего не меняет. */
.psearch {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 0 0 auto;
    max-width: 560px;
    margin-bottom: 8px;
}

    .psearch input {
        flex: 1;
        min-width: 0;
        height: var(--ctl);
        border: 1px solid var(--c-border);
        border-radius: var(--r);
        background: var(--c-bg);
        color: var(--c-text);
        padding: 0 9px;
        font: inherit;
        font-size: 13px;
    }

    .psearch .hint {
        font-size: 11px;
        color: var(--c-faint);
        white-space: nowrap;
    }

/* Вкладки категорий: одна вкладка — один экран плиток без прокрутки. Плитки лежат
   ОДНОЙ сеткой, вкладка и поиск только прячут лишние — поэтому поиск ищет по всему
   прайсу, а не по открытой вкладке. */

.pos-nohit {
    margin: 10px 2px 0;
    font-size: 12px;
    color: var(--c-faint);
}

/* Заголовок категории — как .pv-sec превью (капс у микро-заголовков групп) */
.pos-cat {
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--c-faint);
    margin: 15px 0 8px;
}

    .pos-cat:first-child { margin-top: 0; }

.pos-btns {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 8px;
}

.pos-btn {
    position: relative;
    background: var(--c-bg);
    border: 1px solid var(--c-border);
    border-radius: var(--r);
    padding: 9px 10px;
    min-height: 52px;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    cursor: pointer;
    text-align: left;
    font: inherit;
    color: var(--c-text);
}

    .pos-btn:hover {
        border-color: var(--c-accent-border);
        background: var(--c-accent-bg);
    }

    /* Служебные действия («Своя цена», «Скидка», «Комментарий») — пунктиром: это не
       позиции прайса, а действия кассира */
    .pos-btn.svc { border-style: dashed; }

    .pos-btn.hit {
        border-style: solid;
        border-color: var(--c-accent);
        background: var(--c-accent-bg);
    }

    /* Счётчик — сколько этой позиции уже в чеке: взгляд не ходит в чек за проверкой */
    .pos-btn .cnt {
        position: absolute;
        right: 8px;
        bottom: 8px;
        height: 18px;
        min-width: 18px;
        padding: 0 5px;
        border-radius: 9px;
        background: var(--c-accent);
        color: var(--c-on-accent);
        font-size: 10.5px;
        font-weight: 700;
        line-height: 18px;
        text-align: center;
    }

    .pos-btn .bn {
        font-size: 12px;
        font-weight: 600;
        line-height: 1.2;
    }

    .pos-btn .bp {
        font-size: 11.5px;
        color: var(--c-muted);
        font-variant-numeric: tabular-nums;
        margin-top: 6px;
    }

/* Мини-форма служебной плитки: разворачивается по требованию под плитками. Раньше эти
   поля стояли внизу панели ПОСТОЯННО, а нужны в одном чеке из десяти. */
.pos-form {
    max-width: 460px;
    margin-top: 8px;
    padding: 9px 10px;
    border: 1px solid var(--c-accent-border);
    border-radius: var(--r);
    background: var(--c-bg);
}

    .pos-form .row {
        display: flex;
        align-items: center;
        gap: 8px;
    }

        .pos-form .row + .row { margin-top: 7px; }

    .pos-form input {
        flex: 1;
        min-width: 0;
        height: var(--ctl);
        border: 1px solid var(--c-border);
        border-radius: var(--r);
        background: var(--c-bg);
        color: var(--c-text);
        padding: 0 9px;
        font: inherit;
        font-size: 13px;
    }

        .pos-form input.n {
            flex: 0 0 110px;
            font-variant-numeric: tabular-nums;
        }

    .pos-form .field-hint { margin: 7px 0 0; }

/* ═══════════════════════════════════════════════════════════════════════════
   НИЗКИЙ ЭКРАН — компактная плотность (решение 01.08.2026)
   ───────────────────────────────────────────────────────────────────────────
   Рабочий ПК дропзоны — 1366×768, и браузер там с вкладками: вьюпорт ≈ 620px,
   а не 768. Замер карточки взлёта до правок: постоянного «хрома» 362px, строкам
   оставалось 258px = 7 строк при 12 местах в борту. Разворот в F11 давал 11-12 —
   отсюда и жалоба «в полный экран лучше, но вкладками не попользоваться».

   Порог 720px по ВЫСОТЕ окна (не по ширине и не по разрешению экрана): свернул
   пользователь окно или развернул — плотность подстраивается сама, на больших
   мониторах вид остаётся прежним. Меняем ТОЛЬКО метрику плотности (высота строки,
   отступы полос), не кегль: мельче 12.5px текст на этих машинах уже не читается.
   ═══════════════════════════════════════════════════════════════════════════ */
@media (max-height: 720px) {
    :root {
        --row: 30px;   /* строка таблицы: 34 → 30 (12 мест = экономия 48px) */
    }

    /* Подвалы и полосы действий отдают половину воздуха. Подвал превью .lprev-f — ПАРОЙ
       с .tfoot (25.09.2026): иначе на экране клиента нижняя полоса реестра шла ступенькой
       34 / 46px, хотя правило «одной высоты» записано у самого .lprev-f. */
    .tfoot,
    .lprev-f {
        min-height: 34px;
    }

    .work-head .filters {
        padding: 6px 16px;
    }

    .loadform {
        padding: 9px 16px 11px;
    }
}

/* ═══════════════════════════════════════════════════════════════════════════
   КАРТОЧКА ФИЗЛИЦА /People/Details (концепт docs/person-card-concepts.html, 02.08.2026)
   Человек слева, роли вкладками справа. Заменяет прежние /People/Details и
   /Athletes/Details: раньше поля физлица дублировались на карточке спортсмена,
   и правка ФИО существовала в двух местах.

   Три вещи, из-за которых блок выглядит именно так:
   1. Режима «Править» НЕТ — поля доступны всегда, но в БД ничего не уходит до
      «Сохранить». Значит нужны состояния ПОЛЯ: изменено / ошибка.
   2. Метка «● изменено» живёт в строке подписи ФИКСИРОВАННОЙ высоты — иначе поля
      прыгали бы вниз при каждом вводе.
   3. Переключение вкладки роли меняет ТОЛЬКО правую колонку (панели — грид-стек
      .dz-tabwrap, переключение visibility): ФИО и телефон к роли отношения не имеют.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Шапка человека (одна строка, ~65px) ── */
.pcard-head {
    display: flex;
    align-items: center;
    gap: 13px;
    padding: 11px 16px;
    border-bottom: 1px solid var(--c-line);
    background: var(--c-bg);
    flex: 0 0 auto;
}

.pcard-av {
    width: 38px;
    height: 38px;
    border-radius: 50%;
    background: var(--c-accent-bg);
    color: var(--c-accent-dark);
    display: grid;
    place-items: center;
    font-size: 13.5px;
    font-weight: 600;
    flex: 0 0 auto;
}

/* Клиент (ролей нет) — нейтральный аватар: акцент означает «роль заведена» */
.pcard-av.cli {
    background: var(--c-av-bg);
    color: var(--c-av-fg);
}

.pcard-who {
    min-width: 0;
    flex: 0 1 auto;
}

.pcard-name {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    font-size: 16px;
    font-weight: 600;
    letter-spacing: -.015em;
}

.pcard-sub {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    margin-top: 2px;
    font-size: 11.5px;
    color: var(--c-muted);
}

.pcard-sub .dot {
    margin: 0 6px;
    color: var(--c-faint);
}

/* Показатель в шапке карточки: общий .stat рассчитан на .card-head с воздухом
   сверху и снизу, здесь полоса ужата до одной строки — метрику задаём тут. */
.pcard-head .stats {
    margin-top: 0;
    flex: 0 0 auto;
}

.pcard-head .stat {
    padding: 0 0 0 20px;
    margin: 0 0 0 20px;
    border-right: 0;
    border-left: 1px solid var(--c-line);
    white-space: nowrap;
}

.pcard-head .stat:first-child {
    border-left: 0;
    margin-left: 0;
    padding-left: 0;
}

/* Ключ над значением: в общем .stat это уже так, но там пара живёт в .card-head,
   где спаны — блоки по своим правилам. Здесь метрику держим сами (см. правило
   «компонент несёт свою метрику сам»). */
.pcard-head .stat .k {
    display: block;
    font-size: 10.5px;
    color: var(--c-muted);
    margin-bottom: 1px;
}

.pcard-head .stat .v {
    display: block;
    font-size: 12.5px;
    font-weight: 500;
    line-height: 1.2;
}

/* ── Тело: человек слева, роли справа ── */
.fcols {
    display: flex;
    flex: 1;
    min-height: 0;
    align-items: stretch;
}

.fmain {
    flex: 1.15;
    min-width: 0;
    padding: 12px 14px;
    overflow: auto;
}

.froles {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    padding: 10px 12px 12px;
    border-left: 1px solid var(--c-line);
    background: var(--c-bg-alt);
    overflow: auto;
}

/* Колонка узкая, а у поля ввода есть СВОЯ минимальная ширина (браузерный `size`): без
   min-width:0 грид-ячейки не дают колонке ужаться, и у обеих колонок карточки вылезал
   горизонтальный скроллбар (замер: содержимое 547px против 486px колонки). */
.fcols .field-grid > * {
    min-width: 0;
}

.fcols .field-grid input,
.fcols .field-grid select,
.fcols .field-grid textarea {
    min-width: 0;
}

.fcols .field-section {
    margin-bottom: 9px;
}

.fcols .field-grid + .field-grid,
.fcols .field-grid + .field-section,
.fcols .field-err + .field-grid {
    margin-top: 9px;
}

/* Подпись у заголовка секции («действуют») — не капс и не спорит с заголовком */
.fsec-st {
    font-size: 10.5px;
    font-weight: 500;
    color: var(--c-faint);
}

/* ── Вкладки ролей ── */
.roletabs {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 10px;
    flex: 0 0 auto;
}

/* Точка у названия вкладки: заведена роль или нет. Красная — ошибка на вкладке
   (спрятанная ошибка читается как «кнопка Сохранить не работает»). */
.dz-seg-item .dot-n {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--c-faint);
    opacity: .6;
    flex: 0 0 auto;
}

.dz-seg-item.has .dot-n {
    background: var(--c-ok);
    opacity: 1;
}

.dz-seg-item.bad .dot-n {
    background: var(--c-danger);
    opacity: 1;
}

.froles .dz-tabwrap {
    flex: 1;
    min-height: 0;
}

.froles .dz-tabpane {
    gap: 0;
    min-width: 0;
}

.chip-emp {
    background: var(--c-emp-chip-bg);
    border-color: transparent;
    color: var(--c-emp-fg);
}

/* ── Пустая роль и подвал колонки ролей ── */
/* Кнопки заведения ролей — одинаковой ШИРИНЫ (stretch), одинакового вида и с одним
   глаголом в подписи (просьба 02.08.2026): ни одна из ролей не «главнее» другой, и
   акцент на одной читался бы как рекомендация системы, которой у неё нет. */
.rolenone {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 6px;
    text-align: center;
    padding: 14px 12px;
    border: 1px dashed var(--c-border);
    border-radius: var(--r);
    background: var(--c-bg);
}

/* Кнопка тянется на ширину плашки — обе одинаковы и по ширине, а не только по виду */
.rolenone .btn-secondary,
.rolenone .btn-primary {
    justify-content: center;
}

.rolenone .t {
    font-size: 12.5px;
    color: var(--c-muted);
    margin-bottom: 3px;
}

.rolefoot {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: auto;
    padding-top: 9px;
    border-top: 1px solid var(--c-line);
    font-size: 11px;
    color: var(--c-faint);
}

/* Должности — галочки-теги в ряд (один класс на все галочки, .chk-chip) */
.chkrow {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

/* ── Состояния поля: изменено / ошибка ──
   Метка «● изменено» ставится СКРИПТОМ в строку подписи; высота строки подписи
   фиксирована (14px), поэтому появление метки не двигает вёрстку. */
.fcols label > span:first-child,
.fcols .field-label {
    min-height: 14px;
}

.chgm {
    margin-left: 6px;
    font-size: 10.5px;
    font-weight: 600;
    color: var(--c-accent-dark);
    white-space: nowrap;
}

.fcols label.is-changed input:not([slot]):not(.dz-inner),
.fcols label.is-changed select,
.fcols label.is-changed textarea,
.fcols label.is-changed .dz-date {
    border-color: var(--c-accent-border);
    box-shadow: inset 3px 0 0 var(--c-accent);
}

.fcols label.has-error input:not([slot]):not(.dz-inner),
.fcols label.has-error select,
.fcols label.has-error textarea,
.fcols label.has-error .dz-date {
    border-color: var(--c-danger);
    box-shadow: 0 0 0 3px var(--c-danger-bg);
}

/* Причина ошибки — под полем, а не одной строкой сверху: иначе непонятно, какое
   из пятнадцати полей карточка не приняла. */
.field-err {
    margin: 4px 0 0;
    font-size: 11px;
    color: var(--c-danger);
}

/* Индикатор в строке действий карточки: «Изменений нет» — приглушённый, «Есть несохранённые
   изменения» — янтарный, «Не сохранено: N ошибок» — красный. Ровно те же три состояния, что
   у карточки взлёта; числа изменённых полей в баре нет (просьба 02.08.2026). */
.saveind.clean {
    color: var(--c-faint);
}

/* Точка ошибки — красная: зелёная точка рядом с «Не сохранено» противоречит подписи */
.saveind.err .dot {
    background: var(--c-danger);
}

.saveind.clean .dot {
    background: var(--c-border);
}

/* ═══════════════════════════════════════════════════════════════════════════
   БЛОК — рамка + полоса-заголовок + тело
   Тот же «блок», что на главной (.hcard / .hfeed / .hacts): рамка --c-border,
   скругление --r-lg, полоса-заголовок 30px на --c-bg-alt. Заведён общим классом
   на карточке парашютной системы (14.08.2026, вариант А концепта
   docs/rig-card-blocks-concepts.html) — это ВТОРАЯ страница с такими блоками.
   Появится третья — на .blk переезжает и главная; до тех пор её классы не трогаем,
   страница ещё не откатана вживую (правило «третья страница — компонент»).

   Высота блока — ВСЕГДА по содержимому, если внутри нечего прокручивать: растянутый
   блок вешает пустоту ВНУТРИ рамки, и она читается как «что-то не загрузилось»
   (поймано на карточке главной 13.08.2026). Растягивают список, а не поля.
   ═══════════════════════════════════════════════════════════════════════════ */
.blk {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    border: 1px solid var(--c-border);
    border-radius: var(--r-lg);
    background: var(--c-bg);
    overflow: hidden;
}

.blk-h {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 8px;
    height: 30px;
    padding: 0 12px;
    background: var(--c-bg-alt);
    border-bottom: 1px solid var(--c-line);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--c-muted);
}

/* Пояснение в полосе — обычным текстом справа: заголовок капсом читают как ярлык,
   и правило, набранное так же, в него не попадёт. */
.blk-h .hint {
    margin-left: auto;
    font-size: 11.5px;
    font-weight: 400;
    letter-spacing: 0;
    text-transform: none;
    color: var(--c-faint);
}

.blk-b {
    padding: 10px 14px 12px;
}

/* Шапка документа ВНУТРИ блока (имя, чипы, подстрочка, «Заполнено N из M»):
   каркас .pcard-head с карточки физлица, метрики — как у карточки человека на
   главной (полоса ужата, фон полосы-заголовка). Своей шапки блок не заводит. */
.blk .blk-head {
    gap: 11px;
    padding: 9px 14px;
    background: var(--c-bg-alt);
}

.blk .blk-head .pcard-name {
    font-size: 15px;
}

/* Ошибка поля внутри блока: у .blk-b свои отступы, а таблица идёт без обёртки —
   плашке под ней отступы нужно задать самой. */
.blk-err {
    margin: 8px 14px 10px;
}

/* ═══════════════════════════════════════════════════════════════════════════
   КАРТОЧКА ПАРАШЮТНОЙ СИСТЕМЫ: блоки + таблица состава
   Концепты docs/rig-card-concepts.html (03.08.2026, таблица состава) и
   docs/rig-card-blocks-concepts.html (14.08.2026, вариант А — раскладка блоками).

   Раскладка. Слева блок-карточка (шапка документа + реквизиты) и блок «Состав»,
   справа колонка «Применимость» (признаки + виды прыжков списком). Полосы
   .pcard-head над телом больше нет — шапка уехала внутрь первого блока, как
   карточка человека на главной. Виды прыжков ушли из полосы во всю ширину:
   восемь чипов занимали две строки и разлучали реквизиты с составом.

   Зачем таблица. Прежняя раскладка печатала четыре одинаковые анкеты подряд
   (ранец / основной / запасной / прибор) — 6 заголовков секций, 12 повторов
   подписей «Название · Серийный номер · Дата изготовления», 732px содержимого
   в окне 474px: «Запасной парашют» и «Прибор» уходили за обрез целиком. Узлы
   различаются ОДНИМ полем (площадь есть только у куполов) — это таблица,
   которую разложили в столбик. Замер после переноса — в docs/status.md.

   ВАЖНО: .ctab — раскладка, а не редактор .sheet. Ячейки внешне похожи на
   журнал взлётов, но контракт сохранения карточный (одна форма, один POST по
   «Сохранить»). Имена классов НЕ смешивать с .sheet-* именно поэтому.
   ═══════════════════════════════════════════════════════════════════════════ */

/* Полотно карточки: метрики главной — отступы 14/16, зазор 12. Блоки прижаты к верху
   (align-items) и высотой по содержимому; незанятое остаётся воздухом в конце полотна,
   а не пустотой внутри рамок. Прокрутка полотна — страховка на случай узкого окна. */
.rig-canvas {
    flex: 1;
    min-height: 0;
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 14px 16px 16px;
    overflow: auto;
}

/* Колонка блоков `.blk`: расстояние между блоками держит gap контейнера, а не margin блока
   (правило design-system). Обобщено из страничного .rig-col 30.08.2026, когда на .blk перешли
   карточки справочников. */
.blk-col {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

/* В двухколоннике карточки системы левая колонка блоков тянется, правая (.rig-apply) — фиксирована. */
.rig-canvas > .blk-col {
    flex: 1;
    min-width: 0;
}

/* ── Применимость: признаки и виды прыжков одной колонкой ── */
.rig-apply {
    flex: 0 0 236px;
}

.rig-apply-b {
    padding: 6px 0 8px;
}

/* Строка-галочка. Не .chk-chip: чипы стоят в ряд и переносятся, здесь список сверху
   вниз, и рамка у каждой строки дала бы восемь рамок в узкой колонке. */
.krow {
    display: flex;
    align-items: center;
    gap: 9px;
    height: 27px;
    padding: 0 10px;
    font-size: 12.5px;
    cursor: pointer;
}

.krow:hover {
    background: var(--c-bg-hover);
}

.krow:has(input:checked) {
    color: var(--c-accent-dark);
    font-weight: 500;
}

.krow input[type="checkbox"] {
    width: auto;
    height: auto;
    margin: 0;
    flex: 0 0 auto;
}

.krow-t {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* «Изменено» ставит общий контроллер карточки (site.js) на <label>. Подписи-спана
   в строке нет, поэтому метка — полоса слева, как у ячеек таблицы состава. */
.krow.is-changed {
    box-shadow: inset 3px 0 0 var(--c-accent);
}

.krow-sep {
    height: 1px;
    margin: 5px 10px;
    background: var(--c-line-row);
}

/* Правило «пусто = для любого вида» — подстрочкой над списком, а не плашкой:
   плашка .field-hint во всю ширину стоила 39px вертикали ради одной фразы. */
.krow-note {
    padding: 4px 10px 2px;
    font-size: 11px;
    line-height: 1.35;
    color: var(--c-faint);
}

/* Реквизиты одной полосой внутри блока-карточки: название пошире, номер узкий,
   владелец добирает остаток. Ширины подобраны по содержимому, а не поровну.
   Признаков в полосе больше НЕТ — они уехали в колонку «Применимость» вместе
   с видами прыжков (вариант А концепта rig-card-blocks-concepts.html). */
.field-grid.rig-req {
    grid-template-columns: 300px 130px minmax(240px, 1fr);
    margin-bottom: 0;
}

/* Полоса — ОДНА строка, и отбивку снизу держит она сама: у .field-stack есть свой
   margin-bottom на случай нескольких рядов, здесь он давал строке лишние 10px. */
.rig-req .field-stack {
    margin-bottom: 0;
}

/* ── Таблица состава ── */
.ctab {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    table-layout: fixed;
    font-size: 12.5px;
}

.ctab col.c-part {
    width: 150px;
}

.ctab col.c-serial {
    width: 190px;
}

.ctab col.c-area {
    width: 110px;
}

.ctab col.c-date {
    width: 170px;
}

.ctab th {
    text-align: left;
    padding: 9px 8px;
    font-size: 11.5px;
    font-weight: 500;
    color: var(--c-muted);
    background: var(--c-bg-alt);
    border-top: 1px solid var(--c-line);
    border-bottom: 1px solid var(--c-line);
    white-space: nowrap;
}

.ctab th.num {
    text-align: right;
}

.ctab th:first-child {
    border-left: 1px solid var(--c-line);
    border-top-left-radius: var(--r);
}

.ctab th:last-child {
    border-right: 1px solid var(--c-line);
    border-top-right-radius: var(--r);
}

/* Padding у td нулевой: его несёт сама ячейка-значение, иначе рамка при ховере
   стоит не там, где текст в покое, и строка «дёргается» под курсором. */
.ctab td {
    height: var(--row);
    padding: 0;
    border-bottom: 1px solid var(--c-line-row);
}

.ctab td:first-child {
    border-left: 1px solid var(--c-line);
}

.ctab td:last-child {
    border-right: 1px solid var(--c-line);
}

.ctab tbody tr:last-child td {
    border-bottom: 1px solid var(--c-line);
}

.ctab tbody tr:last-child td:first-child {
    border-bottom-left-radius: var(--r);
}

.ctab tbody tr:last-child td:last-child {
    border-bottom-right-radius: var(--r);
}

/* Имя узла — не поле: правится состав, а не перечень узлов (их всегда четыре).
   Точка слева — смысловая группа, чтобы строку узнавали не только по слову. */
.cpart {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 0 10px;
    font-weight: 500;
}

.cpart .kdot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    flex: 0 0 auto;
    background: var(--c-faint);
}

.cpart .kdot.main {
    background: var(--c-accent);
}

.cpart .kdot.res {
    background: var(--c-danger);
}

.cpart .kdot.ins {
    background: var(--c-warn);
}

/* Ячейка-значение: в покое рамки нет (иначе четыре строки по пять полей дают
   двадцать рамок и рябь), рамка-приглашение приходит по ховеру. Тот же приём,
   что у .sheet-cell, но живёт своими классами — контракт сохранения другой. */
.cin-w {
    display: block;
    margin: 2px 4px;
}

.ctab .cin,
.ctab .dz-date {
    width: 100%;
    height: var(--ctl);
    padding: 0 7px;
    border: 1px solid transparent;
    border-radius: var(--r);
    background: none;
    font-size: 12.5px;
    font-family: inherit;
    color: inherit;
    min-width: 0;
}

.ctab .dz-date {
    padding: 0;
}

.ctab .dz-date .dz-date-text {
    padding: 0 7px;
    font-size: 12.5px;
}

.ctab .cin:hover,
.ctab .dz-date:hover {
    border-color: var(--c-border);
    background: var(--c-bg);
}

.ctab .cin:focus,
.ctab .dz-date:focus-within {
    border-color: var(--c-accent);
    outline: none;
    background: var(--c-bg);
    box-shadow: 0 0 0 3px var(--c-accent-bg);
}

/* Число — моноцифрами и вправо: площади сравнивают взглядом по колонке */
.ctab .cin.num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* «Не бывает» — не пустое поле: у ранца и прибора площади нет в природе, и
   пустая ячейка здесь читалась бы как «забыли заполнить». */
.cin-na {
    display: block;
    padding: 0 7px;
    text-align: center;
    color: var(--c-faint);
}

/* Состояния ячейки — теми же классами, что у полей карточки (их ставит общий
   контроллер site.js): прозрачную рамку заменяем видимой, чтобы метка было видно
   и без ховера. */
.ctab label.is-changed .cin,
.ctab label.is-changed .dz-date {
    border-color: var(--c-accent-border);
    box-shadow: inset 3px 0 0 var(--c-accent);
}

.ctab label.has-error .cin,
.ctab label.has-error .dz-date {
    border-color: var(--c-danger);
    box-shadow: 0 0 0 3px var(--c-danger-bg);
}

/* Низкий экран (1366×768 с вкладками ≈ 620px вьюпорта): отдаём воздух полос,
   кегль не трогаем. */
@media (max-height: 720px) {
    .pcard-head {
        padding: 7px 16px;
    }

    /* Шапка внутри блока держит СВОЙ отступ (селектор весомее .pcard-head),
       поэтому воздух на низком экране отдаёт отдельным правилом. */
    .blk .blk-head {
        padding: 7px 14px;
    }

    .rig-canvas {
        padding: 10px 14px 12px;
    }

    .fmain {
        padding: 9px 14px;
    }

    .froles {
        padding: 8px 12px 10px;
    }
}

/* ═══ dz-select — свой выпадающий список для замкнутых словарей (этап B2) ═══
   Замена vaadin-combo-box: кнопка-поле в ряду обычных контролов (30px, --r) + попап
   на dzPlacePop (position:fixed, живёт и внутри модалки). Только токены — обе темы
   бесплатно, Lumo-переопределения не нужны. Каталог — ui-kit.md §3.5. */
.dz-select {
    position: relative;
    display: block;
    width: 100%;
    min-width: 0;
}

.dzs-btn {
    display: flex;
    align-items: center;
    gap: 6px;
    width: 100%;
    height: var(--ctl);
    padding: 0 8px 0 10px;
    font: inherit;
    font-size: 12.5px;
    text-align: left;
    color: var(--c-text);
    background: var(--c-bg);
    border: 1px solid var(--c-border);
    border-radius: var(--r);
    cursor: pointer;
}

.dzs-btn:focus-visible {
    outline: none;
    border-color: var(--c-accent);
    box-shadow: 0 0 0 2px var(--c-accent-bg);
}

.dzs-label {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.dzs-btn.empty .dzs-label {
    color: var(--c-faint);
}

.dzs-arrow {
    flex: none;
    color: var(--c-faint);
}

.dzs-clear {
    flex: none;
    display: grid;
    place-items: center;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    color: var(--c-faint);
}

.dzs-clear:hover {
    background: var(--c-bg-hover);
    color: var(--c-text);
}

/* Попап — та же семья, что .sheet-pop/.pp-pop (fixed, z-60 — выше подложки модалки z-50) */
.dzs-pop {
    position: fixed;
    z-index: 60;
    overflow-y: auto;
    background: var(--c-bg);
    border: 1px solid var(--c-border);
    border-radius: var(--r);
    box-shadow: var(--shadow-lg);
}

.dzs-opt {
    padding: 7px 11px;
    font-size: 12.5px;
    cursor: pointer;
    border-bottom: 1px solid var(--c-line-row);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.dzs-opt:last-child {
    border-bottom: 0;
}

.dzs-opt.on {
    background: var(--c-accent-bg);
}

.dzs-opt.sel {
    font-weight: 600;
}

.dzs-empty {
    padding: 9px 11px;
    color: var(--c-faint);
    font-size: 12.5px;
}

/* ── Карточка документа с панелью (/Payments/Details, концепт payment-details-concepts.html,
   вариант В) ──────────────────────────────────────────────────────────────────
   Слева документ (шапка + чек), справа панель во ВСЮ высоту рабочей области — язык .lprev
   реестров. Шапка живёт ВНУТРИ левой колонки, а не над обеими: над обеими её содержимое
   висит над панелью и не выровнено ни с чеком, ни с колонкой (поймано на концепте
   11.08.2026). Отступы шапки и тела одинаковые — заголовок стоит ровно над карточкой чека. */
.doc-split {
    flex: 1;
    min-height: 0;
    display: flex;
}

.doc-col {
    flex: 1;
    min-width: 0;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

.doc-col-head {
    flex: 0 0 auto;
    padding: 13px 14px 12px;
    border-bottom: 1px solid var(--c-line);
    background: var(--c-bg);
}

    .doc-col-head .ch-name { margin-bottom: 5px; }

.doc-col-body {
    flex: 1;
    min-height: 0;
    overflow: auto;
    padding: 12px 14px 14px;
}

/* Итог документа — над колонкой «Сумма» таблицы чека; подвал таблицы его НЕ повторяет,
   а говорит то, чего больше нигде нет («в том числе скидка»). */
.doc-total {
    flex: 0 0 auto;
    text-align: right;
}

    .doc-total .k {
        display: block;
        font-size: 11.5px;
        color: var(--c-muted);
        margin-bottom: 1px;
    }

    .doc-total .v {
        display: block;
        font-size: 22px;
        font-weight: 700;
        font-variant-numeric: tabular-nums;
        letter-spacing: -.01em;
    }

.doc-side {
    width: 320px;
    flex: 0 0 auto;
    border-left: 1px solid var(--c-line);
    background: var(--c-bg-alt);
    overflow: auto;
}

.ds-sec {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--c-faint);
    padding: 11px 13px 6px;
}

/* Отступ несёт САМА строка, а не обёртка: иначе разделители реквизитов обрываются
   на 13px до края панели, а в концепте они идут во всю ширину. */
.doc-side .pv-row { padding: 4px 13px; }

.ds-acts { padding: 2px 13px 4px; }

.ds-list { padding: 0 13px; }

/* Строка «оплата этого человека в этот день» — ссылка на соседнюю карточку: вопрос
   «он сегодня ещё платил?» задают у стойки вслух, и ответ должен открываться кликом. */
.ds-item {
    display: flex;
    align-items: center;
    gap: 9px;
    height: 30px;
    font-size: 12.5px;
    color: inherit;
    text-decoration: none;
    border-bottom: 1px solid var(--c-line-row);
}

    .ds-item:last-child { border-bottom: 0; }

    .ds-item:hover { color: var(--c-accent-dark); }

    .ds-item .tm {
        flex: 0 0 42px;
        color: var(--c-muted);
        font-variant-numeric: tabular-nums;
    }

    .ds-item .sm {
        flex: 1;
        min-width: 0;
        color: var(--c-muted);
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    .ds-item .am {
        font-variant-numeric: tabular-nums;
        font-weight: 500;
    }

    /* Текущая оплата в списке дня остаётся: без неё счёт дня читается как чужой */
    .ds-item.cur, .ds-item.cur .tm, .ds-item.cur .sm { color: var(--c-accent-dark); }

.ds-tot {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 8px;
    padding: 8px 13px;
    border-top: 1px solid var(--c-line);
    font-size: 12.5px;
    color: var(--c-muted);
}

    .ds-tot b { color: var(--c-text); }

.ds-link {
    display: block;
    padding: 8px 13px 14px;
    font-size: 12px;
}

/* Кнопка во всю ширину панели: в колонке 320px кнопка по содержимому выглядит потерянной */
.btn-wide {
    width: 100%;
    justify-content: center;
}

/* Блок документа (чек, комментарий) — модификатор .card-main: рамка + радиус + холст, как
   в концепте. Базовый .card-main рамки не несёт намеренно: на других страницах он лежит
   внутри уже обведённого блока и рисовал бы вторую линию. */
.card-main.doc-card {
    flex: 0 0 auto;
    border: 1px solid var(--c-border);
    border-radius: var(--r);
    background: var(--c-bg);
    overflow: hidden;
}

    /* Полоса заголовка блока — на подложке, как в концепте: она шапка блока, а не первая строка */
    .card-main.doc-card > .card-main-bar {
        height: 36px;
        padding: 0 12px;
        background: var(--c-bg-alt);
    }

    /* Обёртка таблицы несёт свою верхнюю линию (в реестре она отделяет список от фильтров) —
       здесь она встаёт впритык к линии полосы «Чек», и две 1px-линии читаются жирной чертой. */
    .card-main.doc-card > .tw {
        border-top: 0;
    }

    /* Подвал блока: общий .tfoot реестра выше и мельче (46px/12px/отступ 14) — в документе
       он часть карточки, а не полоса под списком. Замер концепта: 38px, 12.5px, отступ 12. */
    .card-main.doc-card > .tfoot {
        height: 38px;
        min-height: 38px;
        padding: 0 12px;
        font-size: 12.5px;
        /* Линия над подвалом — того же веса, что разделители строк: в реестре подвал отделён
           от списка сильной линией осознанно (он «полоса под списком»), а внутри карточки
           более тёмная линия читается жирной чертой поперёк документа. */
        border-top-color: var(--c-line-row);
    }

/* ── Таблица СТРОК ДОКУМЕНТА (чек оплаты/выплаты) — модификатор .list-table ──
   Реестровая таблица рассчитана на список, по которому кликают: серая липкая шапка
   (отделяет «шапку списка» при прокрутке), курсор-палец и подсветка строки. В документе
   кликать не по чему, а прокручиваться нечему — оттуда и расхождение с концептом
   (фидбек 11.08.2026). Здесь шапка на холсте карточки, отступы 12px как в концепте,
   строки инертные. Реестры модификатор не трогает. */
.list-table.doc-lines th {
    position: static;
    height: 31px;
    padding: 0 12px;
    background: var(--c-bg);
    /* Та же лёгкая линия, что между строками: в списке шапка липкая и отделяется сильнее,
       в документе шапка колонок — часть таблицы, а не её крышка. */
    border-bottom-color: var(--c-line-row);
}

.list-table.doc-lines td {
    padding: 0 12px;
}

/* Курсор обычный — строка документа никуда не ведёт; подсветка на ховере ОСТАЁТСЯ
   (просьба 11.08.2026): в чеке из десятка строк она держит глаз на нужной, когда ведёшь
   от названия к сумме через пустое поле. Палец обещал бы переход, подсветка — нет. */
.list-table.doc-lines tbody tr {
    cursor: default;
}

    /* Последняя строка не рисует свою нижнюю линию: следом идёт линия подвала, и вдвоём
       они дают ту же жирную черту (в реестре последней строки «в упор» не бывает). */
    .list-table.doc-lines tbody tr:last-child td {
        border-bottom: 0;
    }

    /* Ховер строки — общий (`--c-bg-hover` из базовой .list-table), намеренно не гасится. */

/* ═══ Баннер ошибок (#dz-error-banner, errors.js) ═══════════════════════════
   Единственная точка, где пользователь видит серверную 500 htmx-запроса, отвал
   сети и упавший скрипт. Создаётся JS при первой ошибке; текст — textContent. */
#dz-error-banner {
    position: fixed;
    top: 12px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 100; /* выше модалок и попапов (максимум по файлу — 60) */
    display: flex;
    align-items: center;
    gap: 10px;
    max-width: min(560px, calc(100vw - 24px));
    padding: 8px 12px;
    background: var(--c-danger-bg);
    border: 1px solid var(--c-danger-border);
    color: var(--c-danger);
    border-radius: var(--r);
    box-shadow: var(--shadow-pop);
    font-size: 13px;
}

    #dz-error-banner .close {
        border: 0;
        background: none;
        color: inherit;
        font-size: 16px;
        line-height: 1;
        cursor: pointer;
        padding: 2px 4px;
    }

/* ═══════════════════════════════════════════════════════════════════════════
   ГЛАВНАЯ — точка входа по человеку (концепт docs/home-concepts.html)
   Поиск сверху → карточка физлица → колонка действий справа → короткая история.
   Шапка человека ПЕРЕИСПОЛЬЗУЕТ .pcard-head/.pcard-av/.pcard-who + .stats/.stat
   с карточки /People/Details — своя полоса того же смысла не заводится.
   ═══════════════════════════════════════════════════════════════════════════ */

.home-body {
    gap: 12px;
    padding: 14px 16px 16px;
    overflow: hidden;
}

/* Поиск — обёртка _PersonPicker. Ширина ограничена: ФИО длиннее не бывает, а поле
   во всю стену читается как строка фильтра, а не как точка входа. */
.home-search {
    flex: 0 0 auto;
    max-width: 560px;
}

/* На пустой главной поле стоит ПО ЦЕНТРУ полотна, вместе с приглашением: искать —
   единственное, что здесь можно сделать. Как только человек выбран, форма рисуется
   без этого модификатора и уезжает наверх, отдавая место данным. */
.home-search.center {
    width: 520px;
    max-width: 100%;
    margin-top: 8px;
}

/* Поле поиска на главной КРУПНЕЕ обычного контрола (38px против --ctl 30px) — так в концепте,
   и по делу: это единственное поле экрана и точка входа во всю работу, а не строка фильтра.
   Метрику держим ЗДЕСЬ, а не в компоненте: на прочих страницах пикер обязан оставаться
   вровень с соседними контролами строки (иначе разъедется ряд 30px). */
.home-search .pp-field {
    height: 38px;
    padding: 0 8px 0 11px;
    box-shadow: var(--shadow-sm);
}

.home-search .pp-input {
    font-size: 13.5px;
}

.home-search .pp-mag svg {
    width: 16px;
    height: 16px;
}

/* Стартовое состояние: ТОЛЬКО поиск, никакой ленты записей (решение 13.08.2026). */
/* Приглашение с полем стоит ВЫШЕ геометрического центра: ровно по центру блок читается
   «просевшим» — глаз ищет точку входа в верхней трети экрана, а под полем всё равно пусто.
   Замер на вьюпорте клиента (полотно 572): центр поля на 40% высоты, иконка в 72px от верха.
   Смещение задаём отступом снизу, а не margin-top: блок остаётся центрированным при любой
   высоте окна, просто с поправкой вверх. */
.home-start {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    /* Потолок 250px, но не больше 40% высоты окна: на целевом экране клиента (вьюпорт ≈620)
       это те же ~250px, а на низком окне отступ ужимается и блок не вылезает за верх. */
    padding-bottom: min(250px, 40vh);
}

.home-start-ico {
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background: var(--c-bg-panel);
    color: var(--c-faint);
    display: grid;
    place-items: center;
    margin-bottom: 4px;
}

.home-start-t {
    font-size: 15px;
    font-weight: 600;
}

/* .home-start-s (поясняющий абзац под заголовком) снят 15.08.2026 вместе с текстом:
   он повторял подпись в поле поиска. Правило удалено, чтобы мёртвый класс не всплыл копией. */

/* Тело пульта: карточка и история слева, действия колонкой справа */
.home-panel {
    flex: 1;
    min-height: 0;
    display: flex;
    gap: 12px;
}

.home-main {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

/* ── Карточка человека ──
   Высота ПО СОДЕРЖИМОМУ. Растягивать её на остаток экрана нельзя: при коротком
   комментарии под колонками повисает пустота ВНУТРИ рамки, и она читается как
   «что-то не загрузилось» (поймано на просмотре концепта 13.08.2026). Остаток
   забирает список истории — см. .hfeed. Правило общее: растягивают список, не поля. */
.hcard {
    flex: 0 0 auto;
    border: 1px solid var(--c-border);
    border-radius: var(--r-lg);
    background: var(--c-bg);
    overflow: hidden;
}

    /* Шапка человека — общий каркас .pcard-head с карточки физлица, но метрики концепта
       главной: полоса ужата (9/14 против 11/16), аватар 36, имя 15px. Переопределяем ЗДЕСЬ,
       не трогая сам компонент: на /People/Details шапка живёт по своим размерам. */
    .hcard .pcard-head {
        background: var(--c-bg-alt);
        gap: 11px;
        padding: 9px 14px;
    }

    .hcard .pcard-av {
        width: 36px;
        height: 36px;
        font-size: 12.5px;
    }

    .hcard .pcard-name {
        font-size: 15px;
        font-weight: 650;
        gap: 7px;
    }

/* Показателей справа в шапке НЕТ (решение 14.08.2026): сводка «прыжков / последний /
   оплачено сегодня» — содержание отчётного экрана, а карточка отвечает «кто это».
   Блок `.hkpi` удалён целиком вместе с наполнявшими его запросами. */

/* Колонки реквизитов. Состав задаётся ролями, поэтому раскладок три: c2 — клиент
   (человек + комментарий), c3 — спортсмен либо сотрудник, c4 — обе роли сразу.
   Комментарию всегда самая широкая доля: его дописывают у стойки и читают целиком. */
.hgrid {
    display: grid;
}

.hgrid.c2 { grid-template-columns: minmax(0, 1fr) minmax(0, 1.7fr); }
/* c3 возвращён 25.09.2026: снесён чисткой 30.08.2026 как «мёртвый» — поиск не видел класса,
   собранного в разметке строкой `c@(cols)`, и карточка спортсмена ИЛИ сотрудника шла столбиком. */
.hgrid.c3 { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1.6fr); }
.hgrid.c4 { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1.4fr); }

.hcol {
    min-width: 0;
    padding: 9px 14px 10px;
    border-right: 1px solid var(--c-line-row);
}

    .hcol:last-child {
        border-right: 0;
    }

.hcol-h {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 6px;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--c-faint);
}

.hcol-act {
    margin-left: auto;
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0;
    text-transform: none;
    color: var(--c-accent-dark);
    text-decoration: none;
}

.hrow {
    display: flex;
    align-items: baseline;
    gap: 8px;
    font-size: 12.5px;
    line-height: 1.9;
}

    .hrow .k {
        flex: 0 0 auto;
        width: 104px;
        font-size: 11.5px;
        color: var(--c-muted);
    }

    .hrow .v {
        min-width: 0;
        font-variant-numeric: tabular-nums;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    .hrow .v.em { font-weight: 600; }
    .hrow .v.ok { color: var(--c-ok); }
    .hrow .v.warn { color: var(--c-warn); font-weight: 600; }
    .hrow .v.bad { color: var(--c-danger); font-weight: 600; }
    .hrow .v.none { color: var(--c-faint); }

    .hrow .v .note {
        color: var(--c-faint);
        font-size: 11px;
        font-weight: 400;
    }

.hroles {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
    margin: 5px 0 8px;
}

/* Комментарий: потолок 6 строк, дальше прокрутка внутри колонки — иначе длинный
   комментарий растит карточку и съедает историю. */
.hcmt {
    font-size: 12.5px;
    line-height: 1.55;
    white-space: pre-wrap;
    overflow: auto;
    max-height: 112px;
}

    .hcmt.none {
        color: var(--c-faint);
    }

/* ── История ──
   Забирает остаток полотна под карточкой. .short — записей меньше, чем помещается:
   блок сжимается по содержимому, незанятое остаётся воздухом в конце страницы. */
.hfeed {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    border: 1px solid var(--c-border);
    border-radius: var(--r-lg);
    background: var(--c-bg);
    overflow: hidden;
}

    .hfeed.short {
        flex: 0 0 auto;
    }

.hfeed-h {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 8px;
    height: 30px;
    padding: 0 12px;
    background: var(--c-bg-alt);
    border-bottom: 1px solid var(--c-line);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--c-muted);
}

.hfeed-b {
    flex: 1;
    min-height: 0;
    overflow: auto;
}

.hfeed-empty {
    padding: 14px 12px;
    font-size: 12.5px;
    color: var(--c-faint);
}

.hfrow {
    display: flex;
    align-items: center;
    gap: 10px;
    height: 31px;
    padding: 0 12px;
    border-bottom: 1px solid var(--c-line-row);
    font-size: 12.5px;
    color: var(--c-text);
    text-decoration: none;
}

    .hfrow:last-child {
        border-bottom: 0;
    }

    /* text-decoration гасим и на :hover — иначе глобальное a:hover (0-1-1) подчёркивает
       текст строки (тот же случай, что у плиток хаба). */
    .hfrow:hover {
        background: var(--c-accent-bg);
        text-decoration: none;
    }

    .hfrow .t {
        flex: 0 0 auto;
        width: 74px;
        font-size: 12px;
        color: var(--c-muted);
        font-variant-numeric: tabular-nums;
    }

    .hfrow .ico {
        flex: 0 0 auto;
        width: 16px;
        display: grid;
        place-items: center;
    }

    .hfrow .kind {
        flex: 0 0 auto;
        width: 96px;
        font-weight: 500;
        color: var(--c-text-soft);
    }

    .hfrow .who {
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        color: var(--c-muted);
    }

    .hfrow .sum {
        flex: 0 0 auto;
        width: 86px;
        margin-left: auto;
        text-align: right;
        font-weight: 600;
        font-variant-numeric: tabular-nums;
    }

    .hfrow .sum.in { color: var(--c-ok); }
    .hfrow .sum.out { color: var(--c-danger); }

    .hfrow .i-pay { color: var(--c-ok); }
    .hfrow .i-out { color: var(--c-danger); }
    .hfrow .i-load { color: var(--c-accent); }
    .hfrow .i-brief { color: var(--c-muted); }

/* ── Колонка действий ──
   Список растёт вниз и не отбирает высоту у данных — это ответ на «действий со
   временем станет больше» (печать документов и прочее). Состав — реестр
   PersonActions (Web/Home/PersonActions.cs), а не эта разметка. */
.hacts {
    flex: 0 0 236px;
    display: flex;
    flex-direction: column;
    border: 1px solid var(--c-border);
    border-radius: var(--r-lg);
    background: var(--c-bg);
    overflow: hidden;
}

.hacts-h {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    height: 30px;
    padding: 0 12px;
    background: var(--c-bg-alt);
    border-bottom: 1px solid var(--c-line);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--c-muted);
}

.hacts-b {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 6px;
    overflow: auto;
}

.hacts-sep {
    height: 1px;
    margin: 5px 8px;
    background: var(--c-line-row);
}

.hact {
    display: flex;
    align-items: center;
    gap: 9px;
    flex: 0 0 auto;
    height: 31px;
    padding: 0 8px;
    border-radius: var(--r);
    font-size: 12.5px;
    color: var(--c-text);
    text-decoration: none;
}

    .hact svg {
        flex: 0 0 auto;
        color: var(--c-accent);
    }

    .hact:hover {
        background: var(--c-accent-bg);
        text-decoration: none;   /* глобальное a:hover иначе подчёркивает подпись действия */
    }

    /* Выделенного акцентом действия здесь НЕТ (решение 14.08.2026): в концепте акцентная
       строка была примером, а на живом экране назначает «главное» за пользователя. */
    .hact .cnt {
        margin-left: auto;
        font-size: 11px;
        color: var(--c-faint);
        font-variant-numeric: tabular-nums;
    }

/* ══════════ Составление взлётов /Loads: «лист + панель посадки» (концепт load-composer-concepts-v10) ══════════
   Слева лист текущего взлёта (правка в ячейках — КЛАССЫ ЖУРНАЛА .sheet-cell/.sheet-pop/.mk: один
   язык на двух экранах), другие взлёты — вкладки .ltab в шапке .lband; справа панель посадки .seatp
   с хранилищем заготовок .stg. Группы в листе — явные блоки tr.grp-h. */
.composer-token {
    display: none;
}

.csheet {
    display: flex;
    flex-direction: column;
    min-height: 0;
    flex: 1;
}

.sheet-wrap {
    flex: 1;
    min-height: 0;
    overflow: auto;
}

/* Сетка колонок, шапка, ячейка имени, отметки и попап словаря — ОБЩИЕ с журналом, см. секцию
   «Таблица-редактор состава взлёта (.sheet)» выше. Здесь только то, чего у журнала нет. */

/* Отличие сетки от журнала: рядом стоит панель посадки, и на вьюпорте клиента лист получает
   ≈836px вместо ≈1176. Имя здесь короткое («Богданова Е. М.»), поэтому колонка фиксированная
   и узкая, а лишнюю ширину на широком мониторе забирает хвост-филлер (в журнале её забирает
   «Участник», 25.09.2026). */
.composer-sheet .col-name {
    width: 158px;
}

.composer-sheet .col-fill {
    width: auto;
}

/* Строка листа целиком не кликается (кликают ячейки) — курсор реестра здесь врал бы */
.composer-sheet tbody tr {
    cursor: default;
}

/* Хват перетаскивания (концепт .grip): единственная подсказка, что строку можно утащить на
   вкладку взлёта или в хранилище — подвал с этой подсказкой убран. У строк группы хвата нет:
   группу тянут за шапку, целиком. */
.composer-sheet .grip {
    display: block;
    padding-left: 4px;
    color: var(--c-border);
    font-size: 11px;
    line-height: 1;
    cursor: grab;
}

.composer-sheet tr[draggable="true"]:hover .grip {
    color: var(--c-faint);
}

.composer-sheet td.col-actions {
    padding: 0 6px;
}

/* Ячейки листа — те же div'ы, что в журнале (пока они были <button>, здесь лежал сброс кнопки
   со скруглением: на прямоугольной таблице ячейки и рамка правки выходили круглыми). Своего у
   листа осталось только «система не выбрана» — у журнала пустая система рисуется плейсхолдером
   приёмника, а тут это значение записанной строки. */
.composer-sheet .sheet-cell.ph .sheet-val {
    color: var(--c-faint);
}

/* Открытая ячейка и её редакторы — классы журнала (.sheet-cell.is-editing, .sheet-inp, попап
   .sheet-pop): своего вида у листа нет, правку ведёт общий контроллер.

   Единственная поправка: редактор ФИО шире своей колонки — у листа она узкая (справа стоит
   панель посадки), а пикер должен остаться полноценным полем со списком. */
.composer-sheet td.sheet-person-td .pp {
    position: absolute;
    left: 0;
    top: 0;
    z-index: 55;
    width: 300px;
    background: var(--c-bg);
    box-shadow: inset 0 0 0 2px var(--c-accent), var(--shadow-lg);
}

.composer-sheet td {
    position: relative;   /* якорь попапа ячейки: попап рисует сервер прямо в ячейке */
}

/* Попап словаря внутри ячейки. У журнала попап позиционирует JS от координат клика — здесь он
   часть ответа сервера, поэтому позиционируется CSS относительно своей ячейки. */
/* Попап ячейки — position: fixed и укладка ОБЩИМ помощником `dzPlacePop` (как в журнале):
   ширина словарного попапа равна ячейке, при нехватке места снизу он переворачивается вверх.
   До 30.08.2026 он был absolute от ячейки с min-width 230 — шире колонки и всегда вниз. */
.sheet-pop.in-cell {
    position: fixed;
    z-index: 60;
    max-height: 320px;
    overflow-y: auto;
    overflow-x: hidden;   /* ширина = ячейке: длинный пункт режется, а не даёт вторую прокрутку */
}

    /* Словарь (вид, система): ширину задаёт ячейка — min-width базового .sheet-pop не нужен */
    .sheet-pop.in-cell.dict {
        min-width: 0;
    }

    /* Сноска под списком («групповые виды — через панель») в узком попапе переносится */
    .sheet-pop.in-cell .sheet-pop-empty {
        white-space: normal;
        line-height: 1.35;
    }

/* Пункт в форме («⇣ В хранилище») — последний в попапе, разделитель под ним лишний.
   Сам вид пункта — общий `.sheet-opt` (секция журнала): там же сброс кнопочного вида. */
.sheet-pop.in-cell form:last-child .sheet-opt {
    border-bottom: 0;
}

.sheet-pop-h {
    padding: 6px 10px;
    border-bottom: 1px solid var(--c-border);
    background: var(--c-bg-alt);
    font-size: 11px;
    color: var(--c-muted);
}

/* Свободное место — обычная строка, но тихая: она отвечает на «куда ещё сажать» */
.composer-sheet tr.cfree td {
    color: var(--c-faint);
}

.composer-sheet .cfree-lab {
    font-size: 12px;
    padding-left: 10px;   /* вровень с именами: у .sheet-cell тот же отступ */
}

.composer-sheet .sheet-acts {
    display: flex;
    gap: 4px;
    justify-content: flex-end;
    opacity: 0;
}

.composer-sheet tr:hover .sheet-acts{
    opacity: 1;
}

.sheet-errbar {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 16px;
    /* Тройка --c-danger (25.09.2026): прежние --c-bad/-bg/-line не существуют в палитре,
       и все три объявления молча отбрасывались — «Отказ:» шёл голым текстом без красного. */
    border-bottom: 1px solid var(--c-danger-border);
    background: var(--c-danger-bg);
    color: var(--c-danger);
    font-size: 12.5px;
}

/* Подвал листа (.sheet-foot) убран 30.08.2026: счётчик мест дублировал шапку листа, а подсказка
   на вьюпорте клиента переносилась в три строки. В концепте v10 подвала нет. */

.cap-bar-line {
    width: 92px;
    height: 6px;
    border-radius: 3px;
    background: var(--c-bg-alt);
    overflow: hidden;
}

    .cap-bar-line i {
        display: block;
        height: 100%;
        background: var(--c-accent);
    }

    .cap-bar-line i.full {
        background: var(--c-ok);
    }

    .cap-bar-line i.over {
        background: var(--c-warn);
    }

/* ── Шапка листа: вкладки взлётов + параметры + счётчик мест (концепт v10) ──
   Вкладки — часть листа (underline-таб), не отдельная лента: переключение меняет только состав. */
.lband {
    display: flex;
    align-items: stretch;
    gap: 10px;
    border-bottom: 1px solid var(--c-border);
    background: var(--c-bg);
    min-height: 44px;
}

.ltabs {
    display: flex;
    align-items: stretch;
    overflow-x: auto;   /* взлётов за день десятки — вкладки прокручиваются, лист не пухнет */
}

.ltab {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 1px;
    padding: 5px 13px;
    border: 0;
    border-right: 1px solid var(--c-line);
    background: none;
    color: var(--c-muted);
    font: inherit;
    line-height: 1.25;
    white-space: nowrap;
    cursor: pointer;
}

    .ltab b {
        font-size: 13px;
        font-weight: 650;
        color: var(--c-text-soft);
    }

    .ltab span {
        font-size: 10.5px;
        font-variant-numeric: tabular-nums;
    }

    .ltab:hover {
        background: var(--c-bg-hover);
        text-decoration: none;
    }

    .ltab.on {
        background: var(--c-accent-bg);
        box-shadow: inset 0 -2px 0 var(--c-accent);
    }

        .ltab.on b, .ltab.on span {
            color: var(--c-accent-dark);
        }

    .ltab.swap-target {
        box-shadow: inset 0 0 0 1px var(--c-accent);
    }

    .ltab.ltab-add {
        justify-content: center;
        color: var(--c-faint);
        font-size: 15px;
        padding: 0 14px;
    }

    /* Приглашение: пока тянут, вкладки ЧУЖИХ взлётов показывают, что примут строку или заготовку */
    .ltab.drop-hint {
        outline: 2px dashed var(--c-border);
        outline-offset: -2px;
        background: var(--c-bg-alt);
    }

    /* Цель перетаскивания под курсором (строка/группа → перенос, заготовка → посадка) */
    .ltab.drop-over {
        outline: 2px dashed var(--c-accent);
        outline-offset: -2px;
        background: var(--c-accent-bg);
    }

.lband-params {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 12px;
    color: var(--c-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.lband-act {
    display: inline-flex;
    align-items: center;
    padding: 2px 7px;
    border: 1px solid transparent;
    border-radius: var(--r-sm, 4px);
    color: var(--c-accent-dark);
    font-size: 12px;
    text-decoration: none;
}

    .lband-act:hover {
        border-color: var(--c-border);
        background: var(--c-bg);
        text-decoration: none;
    }

.lband .app-spacer {
    flex: 1;
}

.lband-cnt {
    display: flex;
    align-items: center;
    gap: 8px;
    padding-right: 14px;
    font-size: 12px;
    color: var(--c-muted);
    white-space: nowrap;
}

    .lband-cnt b {
        color: var(--c-text);
        font-variant-numeric: tabular-nums;
    }

/* ── Раскладка «лист + панель» ── */
/* «Взлётов на смену пока нет» — строка-подсказка вместо листа. Не .app-empty: вкладки
   и полоса параметров над ней остаются, центрировать нечего. */
.empty-hint {
    padding: 14px 16px;
    color: var(--c-muted);
    font-size: 12.5px;
}

.composer-split {
    display: flex;
    flex: 1;
    min-height: 0;
}

#composer-sheet-host {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

/* ── Шапка группы в листе: явный блок (перенос и снятие ГРУППЫ живут здесь) ── */
.composer-sheet tr.grp-h td {
    padding: 0;
    background: var(--c-bg-alt);
    border-top: 1px solid var(--c-line);
    box-shadow: inset 3px 0 0 var(--c-grp, var(--c-accent));
}

.grp-line {
    display: flex;
    align-items: center;
    gap: 8px;
    min-height: 26px;
    padding: 2px 10px 2px 12px;
    font-size: 11px;
    color: var(--c-muted);
}

    /* Кнопки группы стоят СРАЗУ за подписью, а не у правого края: на широком экране прижатые
       спейсером кнопки отрывались от контента на пол-экрана (поймано на показе 30.08.2026). */
    .grp-line .grp-acts {
        display: flex;
        gap: 6px;
        margin-left: 16px;
    }

    .grp-line b {
        font-size: 11px;
        font-weight: 700;
        letter-spacing: .02em;
        color: var(--c-text-soft);
        text-transform: uppercase;
    }

.grp-dot {
    width: 8px;
    height: 8px;
    border-radius: 2px;
    background: var(--c-grp, var(--c-accent));
}

.composer-sheet tr.g.g-last td {
    border-bottom: 1px solid var(--c-line);
}

/* Свободный слот — цель посадки заготовки: подсвечивается РОВНО столько первых слотов,
   сколько мест она займёт (JS ставит .drop-tgt при перетаскивании) */
.composer-sheet tr.cfree.drop-tgt td {
    background: var(--c-accent-bg);
    color: var(--c-accent-dark);
}

    /* Полоса — ТОЛЬКО у первой ячейки строки: на каждой ячейке она рисовала столько столбиков,
       сколько в строке ячеек (у свободного слота их три) */
    .composer-sheet tr.cfree.drop-tgt td:first-child {
        box-shadow: inset 3px 0 0 var(--c-accent);
    }

/* Источник перетаскивания. СТРОКА гаснет — она уезжает из состава; КАРТОЧКА хранилища остаётся
   яркой (её «взяли», а не спрятали) и метится акцентной рамкой: гашение читалось как размытие. */
tr.dragging {
    opacity: .35;
}

.stg.dragging {
    outline: 2px solid var(--c-accent);
    outline-offset: -1px;
}

/* ── Курсор перетаскивания ────────────────────────────────────────────────────────────────
   «Схватить» показывает КУРСОР, а не подпись: рука над всем, что тянется (строка, шапка
   группы, заготовка), и сжатая рука, пока тянут. Во время HTML5-перетаскивания курсор рисует
   браузер по dropEffect, поэтому .dz-dragging важен для остальной страницы. */
.composer-sheet tr[draggable="true"],
.composer-sheet tr[draggable="true"] .sheet-cell.ro,
.composer-sheet tr.grp-h[draggable="true"] .grp-line {
    cursor: grab;
}

body.dz-dragging,
body.dz-dragging .composer-sheet tr[draggable="true"],
body.dz-dragging .stg {
    cursor: grabbing;
}

/* Карточка под курсором: снимок для перетаскивания строки/группы (строка во всю ширину листа
   в роли «того, что тащат», читалась лентой, а не предметом). Живёт за экраном один кадр. */
.dz-drag-ghost {
    position: fixed;
    top: -1000px;
    left: -1000px;
    z-index: -1;
    max-width: 280px;
    padding: 6px 10px;
    border: 1px solid var(--c-border);
    border-left: 3px solid var(--c-accent);
    border-radius: var(--r);
    background: var(--c-bg);
    box-shadow: var(--shadow);
    font-size: 12.5px;
    line-height: 1.35;
    white-space: nowrap;
}

    .dz-drag-ghost b {
        display: block;
        font-weight: 600;
    }

    .dz-drag-ghost span {
        color: var(--c-muted);
        font-size: 10.5px;
    }

/* ── Панель посадки: форма ВСЕГДА на одном месте + хранилище заготовок ── */
.seatp {
    flex: 0 0 340px;
    width: 340px;
    display: flex;
    flex-direction: column;
    min-height: 0;
    border-left: 1px solid var(--c-border);
    background: var(--c-bg);
}

.seatp-form {
    flex: 0 0 auto;
    padding: 10px 14px 12px;
    border-bottom: 1px solid var(--c-border);
}

.seatp-h {
    margin-bottom: 8px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--c-muted);
}

/* Выбор вида прыжка — слитный сегмент-контрол (концепт v10 .seg), а не россыпь пилюль: это
   ОДИН выбор из закрытого списка. Видов в справочнике может быть больше четырёх — сегменты
   переносятся на вторую строку, оставаясь одной коробкой. */
.seatp-seg {
    display: flex;
    flex-wrap: wrap;
    margin-bottom: 10px;
    border: 1px solid var(--c-border);
    border-radius: var(--r);
    overflow: hidden;   /* скругление режет крайние сегменты */
    background: var(--c-bg);
}

.seatp-seg-i {
    flex: 1 1 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 28px;
    padding: 4px 10px;
    border-right: 1px solid var(--c-line);
    font-size: 12px;
    color: var(--c-text-soft);
    text-align: center;
    text-decoration: none;
    white-space: nowrap;
}

    .seatp-seg-i:last-child {
        border-right: 0;
    }

    .seatp-seg-i:hover {
        background: var(--c-bg-hover);
        text-decoration: none;
    }

    .seatp-seg-i.on {
        background: var(--c-accent);
        color: var(--c-on-accent);
        font-weight: 600;
    }

.seatp-row {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 8px;
} .seatp-row .dz-select {
        flex: 1;
        min-width: 0;
    }

.seatp-lb {
    flex: 0 0 84px;
    width: 84px;
    font-size: 11.5px;
    color: var(--c-muted);
}

.seatp-alt {
    width: 80px;
    height: var(--ctl, 30px);
    padding: 0 9px;
    border: 1px solid var(--c-border);
    border-radius: var(--r);
    font: inherit;
    font-size: 12.5px;
    font-variant-numeric: tabular-nums;
}

.seatp-opts {
    flex-wrap: wrap;
    padding-left: 92px;
}

.seatp-none {
    font-size: 12px;
    color: var(--c-warn);
}

.seatp-note {
    font-size: 11px;
    color: var(--c-faint);
}

.seatp-err {
    border: 1px solid var(--c-danger-border);
    border-radius: var(--r);
    margin-bottom: 8px;
}

.seatp-acts {
    display: flex;
    gap: 8px;
    margin-top: 4px;
}

    .seatp-acts .btn-primary {
        flex: 1;
    }

.seatp-hint {
    margin-top: 7px;
    font-size: 10.5px;
    color: var(--c-faint);
    line-height: 1.45;
}

/* Хранилище — заготовки дня. Принимает строки/группы из состава перетаскиванием. */
.seatp-store {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

    /* Тянут строку или группу — хранилище показывает, что ждёт её (приглашение), под курсором
       подсветка становится акцентной. Иначе «сюда можно» узнавали, только наведя вслепую. */
    .seatp-store.drop-hint {
        outline: 2px dashed var(--c-border);
        outline-offset: -2px;
        background: var(--c-bg-alt);
    }

    .seatp-store.drop-over {
        outline: 2px dashed var(--c-accent);
        outline-offset: -2px;
        background: var(--c-accent-bg);
    }

.seatp-store-h {
    display: flex;
    align-items: baseline;
    gap: 8px;
    padding: 9px 14px 7px;
    border-bottom: 1px solid var(--c-line);
}

    .seatp-store-h b {
        font-size: 12.5px;
        font-weight: 700;
    }

    .seatp-store-h span {
        font-size: 10.5px;
        color: var(--c-faint);
    }

.seatp-store-list {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    padding: 8px 10px;
}

/* Карточка заготовки: вид прыжка ЦВЕТОМ (левая грань + чип, палитра групп --c-group-0..4 —
   одинаковые виды в хранилище узнаются не читая), участники — ПО СТРОКЕ НА ЧЕЛОВЕКА (группу ищут
   по фамилиям, а «А + Б» в одну строку упиралось в ширину панели и обрезалось многоточием). */
.stg {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin-bottom: 6px;
    padding: 6px 9px;
    border: 1px solid var(--c-border-soft);
    border-left: 3px solid var(--c-grp, var(--c-border));
    border-radius: var(--r);
    background: var(--c-bg);
    cursor: grab;
}

.stg-head {
    display: flex;
    align-items: center;
    gap: 6px;
}

/* Чип вида: цвет несёт ТОЧКА (как в шапке группы листа), подпись остаётся приглушённой —
   цветной текст 9.5px на плашке не держит контраст (палитра групп насыщенная, но светлая). */
.stg-t {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    flex: 0 0 auto;
    padding: 1px 5px;
    border-radius: 4px;
    background: var(--c-bg-panel);
    color: var(--c-muted);
    font-size: 9.5px;
    font-weight: 700;
    white-space: nowrap;
}

.stg-sub {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 10.5px;
    color: var(--c-muted);
}

.stg-people {
    display: flex;
    flex-direction: column;
    gap: 1px;
}

.stg-person {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 12.5px;
    line-height: 1.35;
}

    .stg-person b {
        font-weight: 600;
    }

    .stg-person span {
        color: var(--c-faint);
        font-size: 10.5px;
    }

.stg-go {
    border-color: var(--c-accent-border);
    background: var(--c-accent-bg);
    color: var(--c-accent-dark);
    font-weight: 600;
}

.stg-empty {
    padding: 12px 6px;
    font-size: 12px;
    color: var(--c-faint);
    line-height: 1.5;
}

/* Пункт «⇣ В хранилище» в меню переноса — обычная форма внутри попапа */
.sheet-pop form {
    margin: 0;
}

.sheet-opt.stash {
    width: 100%;
    border-top: 1px solid var(--c-line);
    color: var(--c-accent-dark);
    font-weight: 600;
}

/* Низкий экран: панель чуть уже, вертикаль дороже воздуха */
@media (max-height: 720px) {
    .seatp {
        flex-basis: 320px;
        width: 320px;
    }

    .seatp-form {
        padding: 8px 12px 10px;
    }
}

/* ═══ ЖУРНАЛ СЕРВЕРА (/Admin/Logs) ══════════════════════════════════════════
   Лента файла логов в обычной .list-table. Отличий от реестра ровно два, и оба
   обязательны: строка не кликается (открывать нечего) и текст ПЕРЕНОСИТСЯ —
   сообщение с исключением в одну строку не влезает никогда. */
/* Ширины колонок — из шапки: имя категории (Microsoft.AspNetCore.HttpsPolicy…) при
   автоподборе растягивает «Источник» и съедает колонку сообщения, ради которой таблицу открыли. */
.logv {
    table-layout: fixed;
}

.logv td.logv-src {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.logv td {
    padding-top: 6px;
    padding-bottom: 6px;
    white-space: normal;
    vertical-align: top;
    cursor: default;
}

.logv td.logv-time {
    white-space: nowrap;
    color: var(--c-muted);
    font-variant-numeric: tabular-nums;
}

/* Сообщение — моноширинным: в журнале читают адреса, коды и имена, а не прозу. */
.logv-msg {
    font: 12px/1.5 var(--mono);
    white-space: pre-wrap;
    word-break: break-word;
}

.logv-more {
    cursor: pointer;
    font-size: 11.5px;
    color: var(--c-accent-dark);
}

/* Стек — свёрнут по умолчанию и со своей прокруткой: развёрнутый на весь экран
   стек выдавливает из виду соседние записи, ради которых журнал и открывали. */
.logv-stack {
    margin: 6px 0 2px;
    padding: 8px 10px;
    max-height: 320px;
    overflow: auto;
    background: var(--c-bg-alt);
    border: 1px solid var(--c-line);
    border-radius: var(--r);
    font: 11.5px/1.45 var(--mono);
    white-space: pre-wrap;
    word-break: break-word;
    color: var(--c-muted);
}
