/*
 * HR System — Component library
 * Built entirely on the tokens defined in design-system.css.
 * Load order: design-system.css, then components.css.
 */

/* ============================================================
   Buttons
   ============================================================ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: var(--font-medium);
  line-height: 1;
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  border: 1px solid transparent;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color var(--transition-fast), border-color var(--transition-fast),
    color var(--transition-fast), box-shadow var(--transition-fast), transform var(--transition-fast);
  text-decoration: none;
}
.btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
.btn:active:not(:disabled) {
  transform: translateY(1px);
}
.btn svg {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}

.btn-primary {
  background: var(--color-primary);
  color: var(--color-on-brand);
}
.btn-primary:hover:not(:disabled) { background: var(--color-primary-hover); }
.btn-primary:active:not(:disabled) { background: var(--color-primary-active); }

.btn-secondary {
  background: var(--bg-surface);
  color: var(--text-primary);
  border-color: var(--border-default);
}
.btn-secondary:hover:not(:disabled) { background: var(--bg-hover); border-color: var(--border-strong); }

.btn-danger {
  background: var(--color-danger);
  color: var(--color-on-brand);
}
.btn-danger:hover:not(:disabled) { background: var(--color-danger-hover); }
.btn-danger:active:not(:disabled) { background: var(--color-danger-active); }

/* Подтверждающее действие в паре с btn-danger: «Одобрить» рядом с «Отклонить»,
   «Закрыть заявку» рядом с «Отменить». Значимость та же, что у btn-primary —
   это главный ответ на строку, — но зелёный отделяет «согласовать» от «перейти
   дальше» там, где обе кнопки стоят рядом в одной ячейке. Раньше жил
   инлайновым style="background:var(--color-success)" в leaves/orders/requests:
   тремя копиями, каждая со своим цветом текста. */
.btn-success {
  background: var(--color-success);
  color: var(--color-on-brand);
}
.btn-success:hover:not(:disabled) { background: var(--color-success-hover); }

/* Действие, которое возвращает работу назад, а не завершает её: «Вернуть на
   доработку» рядом с «Одобрить» и «Отклонить». Не danger - ничего не теряется,
   заявка просто уходит автору; не secondary - это решение по заявке, а не выход
   из окна. Текст тёмный: амбер #F59E0B с белым даёт ~2:1 и нечитаем - тот же
   вывод уже был сделан в hr.css для кнопки увольнения, теперь он общий.
   Раньше жил инлайновым style="background:var(--color-warning)" в requests. */
.btn-warning {
  background: var(--color-warning);
  color: var(--slate-800);
}
.btn-warning:hover:not(:disabled) { filter: brightness(0.93); }

.btn-ghost {
  background: transparent;
  color: var(--text-secondary);
}
.btn-ghost:hover:not(:disabled) { background: var(--bg-hover); color: var(--text-primary); }

.btn-sm {
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-xs);
  border-radius: var(--radius-sm);
}
.btn-lg {
  padding: var(--space-4) var(--space-6);
  font-size: var(--text-base);
  border-radius: var(--radius-lg);
}
.btn-icon {
  padding: var(--space-2);
  width: 36px;
  height: 36px;
  border-radius: var(--radius-md);
}
.btn-icon.btn-sm {
  width: 28px;
  height: 28px;
  padding: var(--space-1);
}
.btn-block { width: 100%; }

.fab {
  position: fixed;
  right: var(--space-6);
  bottom: var(--space-6);
  width: 56px;
  height: 56px;
  border-radius: var(--radius-full);
  background: var(--color-primary);
  color: var(--color-on-brand);
  border: none;
  box-shadow: var(--shadow-lg);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  z-index: var(--z-dropdown);
  transition: background-color var(--transition-fast), transform var(--transition-fast);
}
.fab:hover { background: var(--color-primary-hover); }
.fab:active { transform: scale(0.96); }
.fab svg { width: 24px; height: 24px; }

/* ============================================================
   Card
   ============================================================ */
.card {
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  padding: var(--space-6);
}
.card-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-5);
}
.card-title {
  font-size: var(--text-lg);
  font-weight: var(--font-semibold);
  color: var(--text-primary);
  margin: 0;
}
.card-subtitle {
  font-size: var(--text-sm);
  color: var(--text-secondary);
  margin: var(--space-1) 0 0;
}

/* ============================================================
   Stat card
   ============================================================ */
.stat-card {
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  padding: var(--space-6);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.stat-label {
  font-size: var(--text-sm);
  font-weight: var(--font-medium);
  color: var(--text-secondary);
}
.stat-value {
  font-size: var(--text-4xl);
  font-weight: var(--font-bold);
  color: var(--text-primary);
  line-height: var(--leading-tight);
}
.stat-delta {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--text-sm);
  font-weight: var(--font-medium);
  width: fit-content;
}
.stat-delta.up { color: var(--color-success); }
.stat-delta.down { color: var(--color-danger); }
.stat-delta.neutral { color: var(--text-tertiary); }

/* Прочерк вместо числа (данных ещё нет). В размере .stat-value длинное тире
   читается не как "значения нет", а как случайная жирная полоса поперёк
   плитки, поэтому здесь он мельче и приглушён. */
.stat-value.is-empty {
  font-size: var(--text-2xl);
  color: var(--text-tertiary);
}

/* Расшифровка под числом: разбивка по видам отпуска, статусы заявок, отметка
   об истекающих документах. Значки (.badge) переносятся по строкам, поэтому
   плитка растёт вниз, а не вылезает вбок. */
.stat-note {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  font-size: var(--text-xs);
  color: var(--text-tertiary);
}
.stat-note:empty { display: none; }
/* У .badge по умолчанию white-space: nowrap - подпись вроде "Срок истекает
   (30 дн.): 1" не переносилась и вылезала за правый край плитки. Здесь пилюля
   может занять две строки; в остальных местах поведение прежнее. */
.stat-note .badge { white-space: normal; }

/* Плитка-ссылка: число ведёт на список, который оно считает. Ссылка - вся
   плитка, а не одна цифра: по цифре на телефоне легко промахнуться. Цвет и
   подчёркивание от a {} сняты - плитка остаётся плиткой, а что она нажимается,
   видно по рамке при наведении и по обводке при фокусе с клавиатуры. */
.stat-card-link {
  color: inherit;
  transition: border-color var(--transition-fast);
}
.stat-card-link:hover {
  text-decoration: none;
  border-color: var(--color-primary);
}
.stat-card-link:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

/* ============================================================
   Главная (dashboard.js): личная сводка, задачи кадровика
   ============================================================ */

/* Блок, который dashboard.js дописывает под карточкой роли (задачи кадровика
   у hr/admin, сводка аналитики у hr/admin/manager/director, личная сводка
   сотрудника). Отступ живёт в классе, а не в element.style: инлайновый стиль
   не переключается вместе с темой и не ищется по проекту. */
.dashboard-widget { margin-top: var(--space-6); }

/* Содержимое блока задач кадровика - плитки, строка «мои», таблица по видам -
   друг под другом с одним шагом, а не отступом у каждого ребёнка по отдельности. */
.dashboard-widget-body {
  display: grid;
  gap: var(--space-4);
}

/* Строка-ссылка «Мои задачи в работе»: подпись слева, число справа. Нажимается
   вся строка - по той же причине, что и .stat-card-link. */
.dashboard-link-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  color: var(--text-primary);
  font-weight: var(--font-medium);
  transition: border-color var(--transition-fast);
}
.dashboard-link-row:hover {
  text-decoration: none;
  border-color: var(--color-primary);
}
.dashboard-link-row:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}
.dashboard-link-row__count {
  font-size: var(--text-lg);
  font-weight: var(--font-semibold);
  font-variant-numeric: tabular-nums;
  color: var(--text-link);
}

/* auto-fit + minmax: на 1280px четыре плитки встают в ряд, на 390px - в одну
   колонку, без media-запросов и без фиксированных ширин. Сетка общая у личной
   сводки сотрудника и задач кадровика, поэтому и имя без «employee-». */
.dashboard-stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--space-4);
}

/* Быстрые ссылки. Ссылка с классом .btn на узком экране растягивается на всю
   ширину: три кнопки подряд по 100px посреди пустой строки выглядят обрезками,
   а промахнуться по ним пальцем легко. */
.quick-links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
}
.quick-links .btn {
  text-decoration: none;
}
@media (max-width: 767px) {
  .quick-links {
    flex-direction: column;
    align-items: stretch;
  }
}

/* ============================================================
   Forms
   ============================================================ */
.label {
  display: block;
  font-size: var(--text-sm);
  font-weight: var(--font-medium);
  color: var(--text-primary);
  margin-bottom: var(--space-2);
}

.input,
select.input,
textarea.input {
  width: 100%;
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  color: var(--text-primary);
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}
.input::placeholder { color: var(--text-tertiary); }
.input:hover { border-color: var(--border-strong); }
.input:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px var(--color-primary-subtle-bg);
}
.input:disabled {
  background: var(--bg-subtle);
  color: var(--text-tertiary);
  cursor: not-allowed;
}
.input.input-error {
  border-color: var(--color-danger);
}
.input-with-icon {
  position: relative;
}
.input-with-icon .input {
  padding-left: var(--space-10);
}
.input-with-icon svg {
  position: absolute;
  left: var(--space-3);
  top: 50%;
  transform: translateY(-50%);
  width: 18px;
  height: 18px;
  color: var(--text-tertiary);
  pointer-events: none;
}
.field-hint {
  font-size: var(--text-xs);
  color: var(--text-tertiary);
  margin-top: var(--space-1);
}
.field-error {
  font-size: var(--text-xs);
  color: var(--color-danger);
  margin-top: var(--space-1);
}
/* Поле, по которому сервер отказал, и отказ под ним (order-issue.js,
   showActionFieldErrors). */
.action-field-error {
  white-space: pre-line;
}
.input[aria-invalid="true"] {
  border-color: var(--color-danger);
}

/* Справочная врезка внутри формы: иконка ℹ, приглушённый фон, узкая полоса слева.
   Это СПРАВКА, а не проверка: блок ничего не считает, ни на что не влияет и
   ничего не блокирует - он просто рассказывает правило, которое сотруднику
   полезно знать до заполнения формы. Отсюда и оформление: тон приглушённый,
   размер шрифта как у .field-hint, чтобы врезка не спорила с полями и не читалась
   как ошибка (для ошибок есть .field-error с красным). */
.info-note {
  display: flex;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  margin-top: var(--space-2);
  border-radius: var(--radius-md);
  border-left: 3px solid var(--color-info);
  background: var(--color-info-subtle-bg);
  color: var(--text-secondary);
  font-size: var(--text-xs);
  line-height: 1.5;
}
/* И <i data-lucide>, и <svg>, в который lucide.createIcons() его заменяет:
   правило должно работать и до замены (если скрипт иконок не загрузился). */
.info-note > i,
.info-note > svg {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  margin-top: 1px;
  color: var(--color-info);
}
.info-note-title {
  display: block;
  font-weight: var(--font-semibold);
  color: var(--text-primary);
  margin-bottom: var(--space-1);
}
.info-note ul {
  margin: 0;
  padding-left: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}
/* Та же врезка, но про необратимое: удаление, сброс данных. Не .field-error -
   это не ошибка ввода, а предупреждение ДО действия. Цвет - по той же логике,
   что у .btn-danger (STYLEGUIDE, правило 4): красное означает «после этого не
   отменишь», и врезка над красной кнопкой должна говорить тем же цветом, а не
   читаться синей справкой, которую можно пропустить. Текст - основным цветом:
   приглушённый серый на красном фоне предупреждение как раз и прячет. */
.info-note-danger {
  border-left-color: var(--color-danger);
  background: var(--color-danger-subtle-bg);
  color: var(--text-primary);
}
.info-note-danger > i,
.info-note-danger > svg {
  color: var(--color-danger);
}
/* Предупреждение о действии, которое отменить можно, но которое задевает другого
   человека: забрать задачу у коллеги. Жёлтое, а не красное - красное по правилу 4
   STYLEGUIDE означает «не отменишь», а задачу можно вернуть. И не синяя справка:
   её пропускают, а здесь человек должен понять, чью работу он снимает. */
.info-note-warning {
  border-left-color: var(--color-warning);
  background: var(--color-warning-subtle-bg);
  color: var(--text-primary);
}
.info-note-warning > i,
.info-note-warning > svg {
  color: var(--color-warning);
}

/* ============================================================
   Table
   ============================================================ */
.table-wrap {
  width: 100%;
  overflow-x: auto;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  background: var(--bg-surface);
}
.table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
}
.table th {
  text-align: left;
  font-size: var(--text-xs);
  font-weight: var(--font-semibold);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-secondary);
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border-default);
  background: var(--bg-subtle);
  white-space: nowrap;
}
.table td {
  padding: var(--space-4);
  border-bottom: 1px solid var(--border-subtle);
  color: var(--text-primary);
  vertical-align: middle;
}
.table tbody tr:last-child td {
  border-bottom: none;
}
.table tbody tr {
  transition: background-color var(--transition-fast);
}
.table tbody tr:hover {
  background: var(--bg-hover);
}

/* На телефоне таблица с классом table-cards раскладывается карточками: строка
   - карточка, ячейка - «подпись: значение» (подпись из data-label). Нажатие
   на карточку открывает запись так же, как на строку. */
@media (max-width: 767px) {
  .table-cards thead { display: none; }
  .table-cards, .table-cards tbody, .table-cards tr, .table-cards td { display: block; width: 100%; }
  .table-cards tbody tr {
    border: 1px solid var(--border-default);
    border-radius: var(--radius-lg);
    margin-bottom: var(--space-3);
    padding: var(--space-2) var(--space-3);
  }
  .table-cards tbody td {
    border-bottom: none;
    padding: var(--space-1) 0;
    display: flex;
    gap: var(--space-3);
    justify-content: space-between;
    text-align: right;
  }
  .table-cards tbody td[data-label]::before {
    content: attr(data-label);
    color: var(--text-tertiary);
    font-size: var(--text-xs);
    text-align: left;
    flex-shrink: 0;
  }
  .table-cards tbody td.table-state-cell { display: block; text-align: left; }
}

/* Плотная таблица: та же сетка, только мельче шрифт и уже отступы. Нужна там,
   где колонок много, а места мало — пять таблиц личного дела (документы,
   приказы, отпуска, остатки, ознакомления) живут внутри модалки, а таблица
   документов — это семь колонок, последняя из которых четыре кнопки.
   Модификатор, а не вторая таблица: строки, ховер, состояния и скролл остаются
   ровно те же, меняется только плотность. */
.table-dense { font-size: var(--text-xs); }
.table-dense th { padding: var(--space-3); }
.table-dense td { padding: var(--space-2) var(--space-3); }

/* Денежная или количественная колонка: по правому краю и цифрами одной
   ширины, иначе разряды сумм в столбце не стоят друг под другом и «8 000 000»
   на глаз не сравнить с «12 500 000». Заголовок выравнивается вместе с
   колонкой. nowrap - сумма с пробелами-разделителями не должна рваться на две
   строки в узкой ячейке. */
.table th.table-num,
.table td.table-num {
  text-align: right;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* Сводная таблица в карточке: подпись и пара колонок чисел (задачи кадровика
   на главной), вместе с .table-dense. Заголовкам разрешён перенос: у .table th
   nowrap, и на телефоне узбекское «УМУМИЙ РЎЙХАТДА» одной строкой растягивало
   таблицу до 373px при 276px места - она прокручивалась вбок внутри своей
   рамки. На широком экране места хватает, и заголовки остаются в одну строку.
   Правило стоит после .table-num и называет th.table-num явно: иначе у
   заголовка числовой колонки остаётся nowrap - селектор там сильнее. Ячейки
   с числами (td.table-num) по-прежнему не переносятся. */
.table-summary th,
.table-summary th.table-num { white-space: normal; }

/* Строка списка, которая открывает запись (layout.js, rowOpen): курсор,
   подсветка и рамка фокуса с клавиатуры. Действий в строке нет - они внутри
   записи (правило владельца 15.10.2026). Для строк-карточек (div) подсветка
   та же, что у строки таблицы. */
.row-open { cursor: pointer; }
div.row-open:hover,
li.row-open:hover { background: var(--bg-hover); }
.row-open:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: -2px;
  background: var(--bg-hover);
}

/* Кнопки в ячейке «Действия». Тот же набор правил жил копиями в admin.css,
   kb.css, orders.css, requests.css и structure.css; этап 10 снял их все —
   правило осталось только здесь. */
.actions { display: flex; gap: var(--space-2); flex-wrap: wrap; }

/* Состояние (загрузка / пусто / ошибка) на месте строк таблицы: одна ячейка на
   всю её ширину. Собственный отступ ячейки снимается — у .state он свой, иначе
   коробка получает двойной. Копия из structure.css снята на этапе 10. */
.table td.table-state-cell { padding: 0; border-bottom: none; }

/* ============================================================
   Badge
   ============================================================ */
.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--text-xs);
  font-weight: var(--font-medium);
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-full);
  white-space: nowrap;
}
/* Плашка-фраза («врио: ФИО по 24.10.2026»): на узком экране переносится, а
   не выводит строку за край. Вес выше правил «плашки одной строкой» в
   таблице и карточке. Скругление поменьше - пилюля в две строки выглядит
   кляксой. */
.badge.badge-wrap,
.page-content .table .badge.badge-wrap {
  display: inline-block;
  max-width: 100%;
  white-space: normal;
  overflow-wrap: break-word;
  text-align: left;
  border-radius: var(--radius-md);
}
.badge-success { background: var(--color-success-subtle-bg); color: var(--color-success); }
.badge-warning { background: var(--color-warning-subtle-bg); color: var(--color-warning); }
.badge-danger { background: var(--color-danger-subtle-bg); color: var(--color-danger); }
.badge-info { background: var(--color-info-subtle-bg); color: var(--color-info); }
.badge-neutral { background: var(--bg-subtle); color: var(--text-secondary); }

/* ============================================================
   Tabs
   ============================================================ */
.tabs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-6);
  border-bottom: 1px solid var(--border-default);
}
.tab {
  position: relative;
  padding: var(--space-3) var(--space-1);
  font-size: var(--text-sm);
  font-weight: var(--font-medium);
  color: var(--text-secondary);
  background: none;
  border: none;
  cursor: pointer;
  text-decoration: none;
  transition: color var(--transition-fast);
}
.tab:hover { color: var(--text-primary); text-decoration: none; }
.tab-active {
  color: var(--color-primary);
}
.tab-active::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 2px;
  background: var(--color-primary);
  border-radius: var(--radius-full);
}

/* ============================================================
   Avatar
   ============================================================ */
.avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-avatar);
  background: var(--gradient-brand);
  color: var(--color-on-brand);
  font-weight: var(--font-semibold);
  flex-shrink: 0;
  overflow: hidden;
  line-height: 1;
}
.avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.avatar-sm { width: 28px; height: 28px; font-size: var(--text-xs); }
.avatar-md { width: 40px; height: 40px; font-size: var(--text-sm); }
.avatar-lg { width: 56px; height: 56px; font-size: var(--text-lg); }
.avatar-xl { width: 96px; height: 96px; font-size: var(--text-3xl); }

/* ============================================================
   Modal
   ============================================================ */
.modal-backdrop {
  position: fixed;
  inset: 0;
  background: var(--bg-overlay);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-4);
  z-index: var(--z-modal);
}
.modal {
  background: var(--bg-elevated);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-xl);
  width: 100%;
  /* Было 520px. Внутренняя ширина при этом - 472px (минус padding var(--space-6)
     с двух сторон), а три кнопки футера "Отмена / Сохранить черновик / Отправить
     на согласование" занимают 490px + 24px промежутков = 514px. То есть окно было
     уже собственного футера на 42px - это и есть первопричина обрезанной "Отмены",
     а не поведение флексбокса: любой раскладке нужно было куда-то деть лишние
     42px. 600px даёт 552px внутри - хватает и русским подписям (514px), и
     узбекским (~519px), при этом окно остаётся компактным. На узком экране ничего
     не меняется: там работает width:100%, а не max-width. */
  max-width: 600px;
  max-height: 90vh;
  overflow-y: auto;
  padding: var(--space-6);
}

/* Ширины окна сверх базовых 600px. До этапа 10 все три жили копиями под ОДНИМ
   именем .modal.wide - в requests.css (900px), kb.css (960px) и orders.css
   (1100px). Одно имя на три разные ширины - ровно тот случай, о котором правило
   3 в STYLEGUIDE: увидев `class="modal wide"` в разметке, ширину окна узнать
   было нельзя, её знал только файл раздела. Имена идут по той же шкале, что
   --text-2xl и --radius-xl, а сами значения оставлены прежними: этап 10 сводит
   определения в одно место, а не перекраивает окна. */
.modal-lg { max-width: 900px; }   /* заявка: форма и карточка в две колонки */
.modal-xl { max-width: 960px; }   /* редактор статьи: .form-row + панель TinyMCE */
.modal-2xl { max-width: 1100px; } /* карточка приказа: данные и просмотрщик рядом */

.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--space-5);
}
.modal-title {
  font-size: var(--text-xl);
  font-weight: var(--font-semibold);
  margin: 0;
}
/* Футер модалки. Три независимых механизма, каждый закрывает свою часть проблемы
   "кнопка «Отмена» обрезана слева, видно только «тмена»".

   1. Первопричина - арифметика, а не флексбокс: ряд кнопок был ШИРЕ окна (514px
      против 472px внутренней ширины). Это вылечено выше, в .modal - окно
      расширено до 600px, и на десктопе ряд снова помещается в одну строку.

   2. `justify-content: safe flex-end` - защита от того, КУДА уходит переполнение,
      если оно всё-таки случится (очень узкое окно, крупный системный шрифт,
      более длинный перевод). Обычный flex-end прижимает содержимое вправо, и
      лишнее вылезает ВЛЕВО - за начальный край. Такое переполнение не
      прокручивается ни при каких значениях overflow: кнопка не просто уезжает за
      границу, до неё физически нельзя добраться ни мышью, ни скроллом. Ключевое
      слово `safe` означает ровно это: "если содержимое не помещается,
      выравнивай его как start" - переполнение уходит вправо, где оно видимо и
      прокручиваемо. Строка `justify-content: flex-end` перед ней оставлена
      намеренно: браузер, не понимающий `safe`, отбросит вторую декларацию как
      невалидную и сохранит прежнее поведение вместо того, чтобы потерять
      выравнивание совсем.

   3. `flex-wrap: wrap` - чтобы на узком экране ряд переносился на вторую строку,
      а не пытался ужаться: сжаться кнопки не могут, у .btn стоит
      white-space: nowrap, и min-width:auto не даёт флекс-элементу стать уже
      своего min-content.

   Правило общее для всех .modal-footer проекта (заявки, отпуска, приказы,
   справочники, пользователи, подразделения, база знаний). */
.modal-footer {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  justify-content: safe flex-end;
  gap: var(--space-3);
  margin-top: var(--space-6);
}

/* Последний рубеж: кнопка не может быть шире футера ни при каких подписях.
   max-width ограничивает её шириной строки, а white-space:normal разрешает
   перенести подпись внутри кнопки вместо того, чтобы вытолкнуть её за край.
   На обычных ширинах не меняет ничего - подпись и так помещается в одну строку. */
.modal-footer .btn {
  max-width: 100%;
  white-space: normal;
}

/* ============================================================
   Dropdown menu
   ============================================================ */
.dropdown-menu {
  position: absolute;
  min-width: 200px;
  background: var(--bg-elevated);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: var(--space-2);
  z-index: var(--z-dropdown);
}
.dropdown-item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-md);
  font-size: var(--text-sm);
  color: var(--text-primary);
  background: none;
  border: none;
  text-align: left;
  cursor: pointer;
  text-decoration: none;
}
.dropdown-item:hover { background: var(--bg-hover); text-decoration: none; }
.dropdown-divider {
  height: 1px;
  background: var(--border-default);
  margin: var(--space-2) 0;
}

/* ============================================================
   Toast (fixed snackbar notification)
   ============================================================ */
.toast {
  position: fixed;
  bottom: var(--space-6);
  right: var(--space-6);
  display: flex;
  align-items: center;
  gap: var(--space-3);
  background: var(--bg-elevated);
  border: 1px solid var(--border-default);
  border-left: 3px solid var(--color-success);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: var(--space-4) var(--space-5);
  font-size: var(--text-sm);
  color: var(--text-primary);
  max-width: 380px;
  z-index: var(--z-toast);
  animation: toast-in var(--duration-slow) var(--ease-standard);
}
.toast-error { border-left-color: var(--color-danger); }
.toast-warning { border-left-color: var(--color-warning); }
/* Нейтральное «так уже есть»: ни успеха только что, ни повода настораживаться. */
.toast-info { border-left-color: var(--color-info); }
@keyframes toast-in {
  from { transform: translateX(24px); opacity: 0; }
  to { transform: translateX(0); opacity: 1; }
}
@media (max-width: 767px) {
  .toast { bottom: calc(64px + env(safe-area-inset-bottom) + var(--space-4)); right: var(--space-4); left: var(--space-4); max-width: none; }
}

/* Pages migrated to layout.js mark their old inline header/sidebar markup
   with this so it's hidden instead of duplicated on screen. */
[data-legacy-header],
.legacy-header {
  display: none !important;
}

/* ============================================================
   App shell: sidebar + topbar (used by layout.js)
   ============================================================ */
.app-shell {
  display: flex;
  min-height: 100vh;
}

.sidebar {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  width: 260px;
  background: var(--bg-surface);
  border-right: 1px solid var(--border-default);
  display: flex;
  flex-direction: column;
  z-index: var(--z-sidebar);
  transition: transform var(--transition-base);
}
.sidebar-brand {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-5) var(--space-5);
}
/* Логотип с названием (тема 9, layout.js brandHtml): одна разметка в меню,
   шапке на телефоне и на странице входа; размер задаёт место. */
.brand { display: inline-flex; align-items: center; gap: var(--space-3); min-width: 0; }
.brand-logo { width: 32px; height: 32px; flex-shrink: 0; }
.brand-text { display: flex; flex-direction: column; min-width: 0; }
.brand-name {
  font-size: var(--text-lg);
  font-weight: var(--font-bold);
  color: var(--logo-ink);
  line-height: 1.2;
}
.brand-tagline { font-size: var(--text-xs); color: var(--text-secondary); line-height: 1.3; }
.topbar-brand { display: none; }
.topbar-brand .brand-logo { width: 28px; height: 28px; }
@media (max-width: 767px) {
  .topbar-brand { display: inline-flex; }
}
.sidebar-nav {
  flex: 1;
  overflow-y: auto;
  padding: var(--space-2) var(--space-3);
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}
.sidebar-link {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-3);
  border-radius: var(--radius-md);
  font-size: var(--text-sm);
  font-weight: var(--font-medium);
  color: var(--text-secondary);
  text-decoration: none;
  transition: background-color var(--transition-fast), color var(--transition-fast);
}
.sidebar-link svg { width: 18px; height: 18px; flex-shrink: 0; }
/* Lucide подменяет <i data-lucide> на <svg> уже после сборки каркаса (библиотека
   едет с CDN). Без заранее заданной коробки пункты меню в этот момент
   раздвигались - панель "перерисовывалась" на глазах. Место под иконку
   резервируется сразу, поэтому подмена ничего не двигает. */
.sidebar-link i[data-lucide] { display: block; width: 18px; height: 18px; flex-shrink: 0; }
.sidebar-link:hover { background: var(--bg-hover); color: var(--text-primary); text-decoration: none; }
.sidebar-link.active { background: var(--color-primary-subtle-bg); color: var(--color-primary); }
/* Пункт выключенного модуля - он остаётся только у admin и hr, которым оставлено
   чтение накопленного (layout.js, offMarkHtml). Приглушённый цвет и значок
   выключенного питания: раздел открывается, но только на просмотр, и узнать об
   этом человек должен до перехода, а не после первой попытки что-то создать.
   Кликабельность не трогаем - в этом весь смысл: пункт и есть дверь туда. */
.sidebar-link.is-off { color: var(--text-tertiary); }
.sidebar-link.is-off:hover { color: var(--text-secondary); }
.sidebar-link.is-off.active { background: var(--bg-hover); color: var(--text-secondary); }
/* Селектор с родителем - не из вкусовщины: правило выше (.sidebar-link
   i[data-lucide]) резервирует под иконку 18px и специфичнее одиночного класса,
   поэтому значок «выключено» без этого оставался того же размера, что иконка
   раздела, и читался как вторая иконка. Lucide подменяет <i> на <svg> - под
   обоих один селектор. */
.sidebar-link .sidebar-off,
.sidebar-link svg.sidebar-off {
  margin-left: auto;
  width: 14px;
  height: 14px;
  flex-shrink: 0;
  opacity: 0.75;
}
.tab-bar-item.is-off { color: var(--text-tertiary); }
/* Счётчик у пункта меню (новые задачи в пуле, layout.js). margin-left:auto
   прижимает его к правому краю пункта при любой длине подписи. */
.sidebar-count {
  margin-left: auto;
  min-width: 20px;
  padding: 0 var(--space-2);
  border-radius: var(--radius-full);
  background: var(--color-primary);
  color: var(--color-on-brand);
  font-size: var(--text-xs);
  font-weight: var(--font-semibold);
  line-height: 20px;
  text-align: center;
}
.sidebar-section-label {
  font-size: var(--text-xs);
  font-weight: var(--font-semibold);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-tertiary);
  padding: var(--space-4) var(--space-3) var(--space-1);
}
.sidebar-footer {
  padding: var(--space-4) var(--space-5);
  border-top: 1px solid var(--border-default);
  display: flex;
  align-items: center;
  gap: var(--space-3);
}
/* Имя - «Имя Отчество» (решение владельца 26.10.2026), а не короткий логин:
   рядом с кружком и кнопкой выхода ему остаётся ~125px, и обычное «Гулнора
   Алишеровна» в одну строку уже обрезалось. До двух строк, дальше -
   многоточие; полностью - в подсказке (title, layout.js). */
.sidebar-footer .user-name {
  font-size: var(--text-sm);
  font-weight: var(--font-medium);
  color: var(--text-primary);
  line-height: var(--leading-tight);
  overflow: hidden;
  /* Одно слово длиннее строки (двойная фамилия) - переносом по слогам, а не
     разрезом в случайном месте. */
  overflow-wrap: anywhere;
  hyphens: auto;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
}
.sidebar-footer .user-role {
  font-size: var(--text-xs);
  color: var(--text-secondary);
}

.main-content {
  margin-left: 260px;
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.topbar {
  position: sticky;
  top: 0;
  height: 64px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: 0 var(--space-6);
  background: var(--bg-surface);
  border-bottom: 1px solid var(--border-default);
  z-index: var(--z-header);
}
/* Левая половина топбара: гамбургер + хлебные крошки. min-width:0 обязателен -
   без него флекс-элемент не сжимается меньше своего содержимого, и на 360px
   длинная крошка ("Сотрудники", "Мой профиль") выталкивала кнопки языка и темы
   за правый край экрана: страница получала горизонтальный скролл, а кнопка
   темы обрезалась наполовину. */
.topbar-lead {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
}
.breadcrumbs {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-sm);
  color: var(--text-secondary);
  min-width: 0;
}
.breadcrumbs a { color: var(--text-secondary); white-space: nowrap; }
.breadcrumbs .current {
  color: var(--text-primary);
  font-weight: var(--font-medium);
  /* Сжимается именно текущий раздел - он и длиннее всех, и понятен по началу. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.topbar-actions {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-shrink: 0;
}

#topbarBellSlot,
#topbarChatSlot {
  position: relative;
  display: flex;
}

.page-content {
  padding: var(--space-8);
  flex: 1;
}

.hamburger-btn { display: none; }

/* Mobile bottom tab bar */
.tab-bar {
  display: none;
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  height: 64px;
  background: var(--bg-surface);
  border-top: 1px solid var(--border-default);
  align-items: center;
  justify-content: space-around;
  z-index: var(--z-header);
  padding-bottom: env(safe-area-inset-bottom);
}
.tab-bar-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  font-size: 11px;
  color: var(--text-secondary);
  text-decoration: none;
  flex: 1;
  padding: var(--space-2) 0;
}
.tab-bar-item svg { width: 22px; height: 22px; }
/* То же резервирование, что и в .sidebar-link - см. комментарий там. */
.tab-bar-item i[data-lucide] { display: block; width: 22px; height: 22px; }
.tab-bar-item.active { color: var(--color-primary); }

@media (max-width: 767px) {
  .sidebar {
    transform: translateX(-100%);
  }
  /* Открытое меню на узком экране - поверх всего каркаса, и шапки, и нижней
     панели. Раньше слой меню (--z-sidebar 90) был НИЖЕ шапки и нижней панели
     (--z-header 100): панель с теми же разделами ложилась поверх меню, а его
     низ с кнопкой «Выход» уходил под неё - выйти было нельзя (Мелочи-3). */
  .sidebar.open {
    transform: translateX(0);
    box-shadow: var(--shadow-xl);
    z-index: calc(var(--z-header) + 2);
    padding-bottom: env(safe-area-inset-bottom);
  }
  /* Навигация - в одном месте: пока открыто полное меню, нижняя панель с
     частью тех же разделов не показывается. */
  body.sidebar-open .tab-bar {
    display: none;
  }
  .main-content {
    margin-left: 0;
    padding-bottom: 64px;
  }
  .hamburger-btn {
    display: inline-flex;
  }
  .tab-bar {
    display: flex;
  }
  .page-content {
    padding: var(--space-4);
  }
  /* 24px отступа с каждой стороны при ширине экрана 360px - это 13% строки
     топбара под пустоту, которой там взяться неоткуда. */
  .topbar {
    padding: 0 var(--space-3);
  }
  .sidebar-backdrop {
    position: fixed;
    inset: 0;
    background: var(--bg-overlay);
    z-index: calc(var(--z-header) + 1);
  }
}

/* ============================================================
   PWA install banner (Этап 14)
   Injected hidden by layout.js and revealed only when Chrome
   fires beforeinstallprompt. Sits above the mobile tab-bar.
   ============================================================ */
.install-banner {
  position: fixed;
  right: var(--space-4);
  bottom: var(--space-4);
  left: auto;
  max-width: 400px;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--bg-elevated);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xl);
  z-index: var(--z-toast);
}
.install-banner[hidden] {
  display: none;
}
.install-banner img {
  border-radius: var(--radius-sm);
  flex-shrink: 0;
}
.install-banner-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  margin-right: auto;
}
.install-banner-text strong {
  font-size: var(--text-sm);
  font-weight: var(--font-semibold);
  color: var(--text-primary);
}
.install-banner-text span {
  font-size: var(--text-xs);
  color: var(--text-secondary);
}

@media (max-width: 768px) {
  .install-banner {
    left: var(--space-3);
    right: var(--space-3);
    max-width: none;
    bottom: calc(64px + var(--space-3) + env(safe-area-inset-bottom));
  }
}

/* ============================================================
   Заголовок страницы
   Один <h1> на страницу + подзаголовок + блок действий справа.
   Раньше эту роль играли три независимые копии .content-header
   (reports.css, orders.css, requests.css), разъехавшиеся по
   отступам и размеру шрифта. Этап 10 снял все три: класса
   .content-header в проекте больше нет ни в одном файле.
   ============================================================ */
.page-tabs {
  /* Панель разделов ПОД заголовком: шапка -> вкладки -> фильтры ->
     содержимое на всех страницах (сторож -
     backend/common/tests/test_frontend_page_header_order.py). Отступ живёт
     в классе, а не в инлайновом style= на каждой странице раздела. */
  margin-bottom: var(--space-6);
}

.page-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-3) var(--space-4);
  margin-bottom: var(--space-6);
}
/* min-width:0 обязателен: без него флекс-элемент не сжимается меньше
   своего содержимого, и длинный заголовок выталкивает .page-actions за
   правый край вместо переноса на следующую строку. */
.page-header__text {
  min-width: 0;
}
.page-title {
  margin: 0;
  font-size: var(--text-2xl);
  font-weight: var(--font-semibold);
  line-height: var(--leading-tight);
  color: var(--text-primary);
}
.page-subtitle {
  margin: var(--space-1) 0 0;
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
  color: var(--text-secondary);
}
.page-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2);
}

@media (max-width: 767px) {
  .page-title { font-size: var(--text-xl); }
  /* На узком экране действия и так переносятся на свою строку - растягиваем
     их на всю ширину, иначе кнопки прижимаются к правому краю и читаются как
     продолжение заголовка. */
  .page-actions { width: 100%; }
}

/* Заголовок раздела ВНУТРИ страницы — вкладка, секция списка. Тот же ряд
   «текст слева, действия справа», что и .page-header, но рангом ниже: <h1> на
   странице один, у секций — <h2>. Правило понадобилось на страницах с
   вкладками (отпуска, приказы, заявки): там каждая вкладка носила свой
   .content-header с <h1> внутри — четыре <h1> в одном документе, то есть
   четыре разные страницы с точки зрения скринридера и оглавления. Блок
   действий внутри переиспользует .page-actions: это тот же ряд кнопок, второй
   копии он не заслуживает. */
.section-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-3) var(--space-4);
  margin-bottom: var(--space-5);
}
/* min-width:0 по той же причине, что и у .page-header__text: без него длинный
   заголовок не сжимается и выталкивает кнопки за правый край. */
.section-title {
  margin: 0;
  min-width: 0;
  font-size: var(--text-xl);
  font-weight: var(--font-semibold);
  line-height: var(--leading-tight);
  color: var(--text-primary);
}

@media (max-width: 767px) {
  .section-title { font-size: var(--text-lg); }
}

/* ============================================================
   Панель фильтров, сводка над списком, пагинация
   Три виджета, которые носят все разделы сразу: отчёты, админка,
   уведомления, база знаний. Жили тремя копиями - .filters-bar в
   reports.css, .pagination в admin.css, .pagination-bar в
   notifications.css, - и админка, не подключавшая reports.css,
   дублировала раскладку фильтров инлайновым style= на каждой
   странице. Этап 10 снял копии .filters-bar (reports, orders,
   requests, leaves), .filter-field label (orders, requests),
   .summary-row (reports), .pagination (admin) и .pagination-bar
   (notifications) - они совпадали с этими правилами слово в слово.
   Осталось ДВА осознанных исключения, и оба не копии:
     - .filter-field в orders/requests/leaves держит min-width на
       самой колонке, а не на поле ввода: там последняя ячейка
       строки фильтров - одна кнопка «Сбросить», и без этого она
       сжимается по подписи;
     - .pagination в orders/requests/hr лежит внутри карточки
       списка и доопределяет padding и gap.
   ============================================================ */
.filters-bar {
  display: flex;
  gap: var(--space-4);
  flex-wrap: wrap;
  align-items: flex-end;
  margin-bottom: var(--space-5);
}
.filter-field { display: flex; flex-direction: column; gap: var(--space-1); }
.filter-field label { font-size: var(--text-xs); color: var(--text-secondary); font-weight: var(--font-semibold); }
.filter-field input, .filter-field select { min-width: 160px; }

.summary-row { display: flex; gap: var(--space-4); flex-wrap: wrap; margin-bottom: var(--space-5); }
.summary-row .stat-card { min-width: 180px; border-top: 3px solid var(--color-primary); }

/* Кнопки "Назад / Вперёд" и номер страницы между ними. align-items нужен
   именно здесь: без него подпись "Страница 2" прижимается к верху строки и
   не совпадает по базовой линии с кнопками. */
.pagination {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: var(--space-3);
  margin-top: var(--space-5);
}
.pagination span {
  font-size: var(--text-sm);
  color: var(--text-secondary);
}


/* ============================================================
   Состояния списка: загрузка / пусто / ошибка
   Одна коробка на все три, поэтому блок не прыгает по высоте при
   переходе между ними. Разметку собирают setLoading/setEmpty/setError
   из page-kit.js. Руками эти классы пишутся только в стартовой заглушке
   разметки - до первого ответа API звать хелпер ещё некому, - и там повторяют
   ровно то, что вернул бы setLoading.
   ============================================================ */
.state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  min-height: 180px;
  padding: var(--space-10) var(--space-6);
  border-radius: var(--radius-lg);
  text-align: center;
  font-size: var(--text-sm);
  color: var(--text-secondary);
}
.state svg {
  width: 32px;
  height: 32px;
  flex-shrink: 0;
}

.state-loading {
  color: var(--text-tertiary);
}
/* Спиннер - псевдоэлемент: состояние остаётся одним узлом разметки, и его
   нечем случайно перебить со стороны страницы. При prefers-reduced-motion
   общее правило из design-system.css гасит анимацию, кольцо просто замирает
   и работает как статичная метка "идёт загрузка". */
.state-loading::before {
  content: '';
  width: 28px;
  height: 28px;
  border: 2px solid var(--border-default);
  border-top-color: var(--color-primary);
  border-radius: var(--radius-full);
  animation: state-spin 700ms linear infinite;
}
@keyframes state-spin {
  to { transform: rotate(360deg); }
}

.state-empty {
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
}
.state-empty__icon {
  display: flex;
  color: var(--text-tertiary);
}
.state-empty__title {
  font-size: var(--text-base);
  font-weight: var(--font-medium);
  color: var(--text-primary);
}
/* Внутри карточки или обёртки таблицы поверхность с рамкой уже нарисована -
   вторая читается как коробка в коробке. Само состояние остаётся тем же, у
   него просто нет своего фона там, где фон уже есть. */
.card .state-empty,
.table-wrap .state-empty {
  background: none;
  border: none;
}
.state-empty__hint {
  margin: 0;
  /* Подсказка - это предложение, а не абзац: длинная строка на широком
     экране читается хуже, чем перенесённая. */
  max-width: 46ch;
  color: var(--text-secondary);
}

.state-error {
  background: var(--color-danger-subtle-bg);
  color: var(--color-danger);
}

@media (max-width: 767px) {
  .state {
    padding: var(--space-8) var(--space-4);
  }
}

/* ============================================================
   Карточка согласуемой заявки: сетка полей, подзаголовки, маршрут
   Виджеты окна, которое открывают и заявки (requests.html), и отпуска
   (leaves.html): шапка полями, подпись группы, полоса ступеней,
   подпись «за кого решили» и подсказка о строке реестра. Жили одной
   копией в requests.css - ровно до того момента, как карточка
   понадобилась второй странице; вторая копия разошлась бы с первой на
   первой же правке и разошлась бы молча, как до Этапа 10 расходились
   .filters-bar и .pagination выше.
   Исключения остались в requests.css и копиями не являются: поле
   комментария к решению (.decision-section, .decision-notice),
   подсказка о кандидатах шага роли (.approval-hint) и подпись под
   значением под маской ПДн (.pii-masked-hint) - всё это про заявки и
   их конструктор, у отпусков этого нет.
   ============================================================ */
.detail-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-3) var(--space-5); margin-bottom: var(--space-5); }
.detail-item .label { font-size: 11px; color: var(--text-tertiary); text-transform: uppercase; font-weight: var(--font-semibold); letter-spacing: 0.04em; }
.detail-item .value { font-size: var(--text-sm); color: var(--text-primary); margin-top: 2px; }

/* Состояние внутри сетки полей занимает обе колонки: коробка «Нет данных» в
   одной колонке читается как значение первого поля. */
.detail-grid > .state { grid-column: 1 / -1; }

/* Подзаголовок внутри карточки («Данные формы», «Маршрут согласования»). Не
   .section-title: тот - заголовок раздела страницы, здесь же подпись группы
   полей внутри окна, рангом ниже заголовка самого окна. Верхний отступ не
   нужен - над подзаголовком всегда стоит блок со своим margin-bottom. */
.detail-section-title {
  margin: 0 0 var(--space-2);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-secondary);
}

/* Подпись под именем решившего: за кого он решил. */
.approval-on-behalf { font-size: var(--text-xs); color: var(--text-secondary); margin-top: 2px; }

/* Карточка строкой реестра: почему нет содержимого. Информационный цвет, а не
   предупреждение - это не ошибка и не отказ, так устроены права. */
.registry-notice {
  padding: var(--space-3); margin-bottom: var(--space-4); border-radius: var(--radius-md);
  background: var(--color-info-subtle-bg); color: var(--text-primary); font-size: var(--text-sm);
}

/* Полоса ступеней: где заявка была, где стоит и куда уже не пойдёт. */
.step-tracker { display: flex; gap: var(--space-2); flex-wrap: wrap; margin-bottom: var(--space-5); }
.step-chip {
  padding: var(--space-1) var(--space-3); border-radius: var(--radius-full); font-size: var(--text-xs); font-weight: var(--font-semibold);
  background: var(--bg-subtle); color: var(--text-secondary);
}
.step-chip.approved { background: var(--color-success-subtle-bg); color: var(--color-success); }
.step-chip.rejected { background: var(--color-danger-subtle-bg); color: var(--color-danger); }
.step-chip.returned { background: var(--color-warning-subtle-bg); color: var(--color-warning); }
.step-chip.current { background: var(--color-primary-subtle-bg); color: var(--color-primary); box-shadow: 0 0 0 2px var(--color-primary) inset; }
/* Ступень, до которой дело не дошло: заявку закрыли раньше. Своим видом, а не
   цветом «ожидает», - иначе у отклонённой заявки второй шаг читался бы как
   всё ещё ждущий решения. */
.step-chip.skipped { background: transparent; color: var(--text-tertiary); box-shadow: 0 0 0 1px var(--border-default) inset; }

@media (max-width: 480px) {
  /* Две колонки по 1fr - это ~150px на значение: «Дата подачи» и ФИО
     согласующего в такую ширину не помещаются и рвутся посередине слова. */
  .detail-grid { grid-template-columns: 1fr; }
}

/* ============================================================
   Юрлицо в шапке и переключатель учёток (accounts.js, PR 7)
   ============================================================ */
.entity-slot { position: relative; display: inline-flex; min-width: 0; }
.entity-slot[hidden] { display: none; }
.entity-chip {
  width: auto;
  max-width: 240px;
  gap: var(--space-2);
  padding: 0 var(--space-3);
  font-size: var(--text-sm);
  font-weight: var(--font-semibold);
}
.entity-chip i { flex: 0 0 auto; width: 16px; height: 16px; }
.entity-chip__label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Переключателя у роли нет и других учёток не открыто - название остаётся
   видно, но кнопкой не притворяется. */
.entity-chip.is-static, .entity-chip:disabled { cursor: default; opacity: 1; }
.entity-chip.is-static:hover { background: none; }
.account-menu {
  top: calc(100% + var(--space-1));
  right: 0;
  min-width: 280px;
  max-width: min(360px, calc(100vw - 2 * var(--space-4)));
}
.account-menu__title {
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-xs);
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.account-row { justify-content: space-between; }
.account-row.is-current { cursor: default; }
.account-row.is-current:hover { background: none; }
.account-row__text { display: flex; flex-direction: column; min-width: 0; }
.account-row__text strong, .account-row__text small {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.account-row__text small { color: var(--text-secondary); }
.account-row__go { color: var(--color-primary); font-size: var(--text-xs); flex: 0 0 auto; }
/* Предупреждение об автовыходе - поверх всего, включая блокировку
   ознакомлений: иначе человек не увидит, что его сейчас отключат. */
.idle-warning { z-index: calc(var(--z-modal) + 10); }
@media (max-width: 600px) {
  .entity-chip { max-width: 140px; }
  /* На телефоне список учёток привязан к краям экрана под шапкой, а не к
     правому краю кнопки юрлица: кнопка стоит в середине шапки, и меню шириной
     280px от её правого края уходило за левый край экрана (на 375px - на
     53px), обрезая названия юрлиц. */
  .account-menu {
    position: fixed;
    top: calc(64px + var(--space-1));
    left: var(--space-3);
    right: var(--space-3);
    min-width: 0;
    max-width: none;
  }
}

/* ============================================================
   Language picker (topbar)
   ============================================================ */
.lang-picker { position: relative; display: inline-flex; }
.lang-menu {
  top: calc(100% + var(--space-1));
  right: 0;
  min-width: 168px;
}
/* Галочка занимает место всегда, иначе названия языков прыгают влево-вправо
   при переключении - на 360px это видно особенно хорошо. */
.lang-check {
  display: inline-block;
  width: 14px;
  flex: 0 0 14px;
  color: var(--color-primary);
}

/* Тот же переключатель на страницах без каркаса (вход, подтверждение входа,
   настройка 2FA): кнопка там рисуется из auth-lang.js, и размеры ей задаёт
   класс, а не инлайновый стиль. */
.auth-lang-btn {
  width: auto;
  padding: 0 10px;
  font-size: 13px;
  font-weight: 600;
}

/* Служебный ряд в углу карточки: язык и тема. Absolute, а не в потоке, - они
   не должны отодвигать заголовок. */
.auth-card-actions {
  position: absolute;
  top: var(--space-4);
  right: var(--space-4);
  display: flex;
  align-items: center;
  gap: var(--space-1);
}

/* ============================================================
   Экран блокировки до ознакомления
   Рисует layout.js на любой странице платформы, пока у человека
   есть неподписанные обязательные документы (приказ, ЛНА).
   Правила лежат здесь, а не в acknowledgments.css: тот подключает
   одна страница, а экран нужен на всех.
   ============================================================ */

/* Пока блокировка стоит, навигация не работает - ни в панели, ни в нижнем ряду
   на телефоне. Выход (.sidebar-footer) и переключатели в топбаре не гасятся
   намеренно: человек обязан иметь возможность выйти и прочитать экран на своём
   языке. pointer-events снимает и клавиатурный путь тоже - ссылку под
   выключенными указателями Tab всё ещё находит, поэтому ниже ещё и
   visibility-нейтральное затемнение, а не только курсор. */
body.ack-blocked .sidebar-nav,
body.ack-blocked .tab-bar {
  pointer-events: none;
  opacity: .45;
}
body.ack-blocked .sidebar-nav a,
body.ack-blocked .tab-bar a {
  /* Tab обходит ссылки с tabindex=-1; pointer-events этого не делает. */
  pointer-events: none;
}

.ack-block-screen {
  position: fixed;
  inset: 0;
  z-index: 9000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-4);
  background: var(--bg-app);
  overflow-y: auto;
}

.ack-block-card {
  width: 100%;
  max-width: 480px;
  padding: var(--space-8);
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  text-align: center;
}

.ack-block-icon {
  display: flex;
  justify-content: center;
  margin-bottom: var(--space-4);
  color: var(--color-primary);
}
.ack-block-icon svg { width: 40px; height: 40px; }

.ack-block-title {
  margin: 0 0 var(--space-2);
  font-size: var(--text-xl);
  font-weight: var(--font-semibold);
  color: var(--text-primary);
}

.ack-block-text {
  margin: 0 0 var(--space-4);
  font-size: var(--text-sm);
  color: var(--text-secondary);
  line-height: var(--leading-relaxed);
}

.ack-block-list {
  margin: 0 0 var(--space-4);
  padding: 0;
  list-style: none;
  text-align: start;
  font-size: var(--text-sm);
}
/* Пометка «нужно решение по согласию» у документа на экране блокировки (тема 36). */
.ack-block-tag {
  display: inline-block;
  margin-inline-start: var(--space-2);
  font-size: var(--text-xs);
  color: var(--text-secondary);
}
/* Заголовок раздела «Согласия» под ознакомлениями в карточке и профиле. */
.consent-section-title { margin-top: var(--space-6); }

.ack-block-list li {
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  background: var(--bg-subtle);
  margin-bottom: var(--space-2);
  /* Название приказа бывает длинным и без пробелов - иначе распирает карточку. */
  overflow-wrap: anywhere;
}

.ack-block-more {
  margin: 0 0 var(--space-4);
  font-size: var(--text-xs);
  color: var(--text-secondary);
}

.ack-block-footer {
  margin-top: var(--space-6);
  padding-top: var(--space-4);
  border-top: 1px solid var(--border-subtle);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  align-items: center;
  justify-content: space-between;
}
.ack-block-langs { display: flex; flex-wrap: wrap; gap: var(--space-1); }
/* Колокольчик и выход - одной группой справа (колокольчик переносит сюда
   layout.js на время блокировки). */
.ack-block-actions { display: flex; align-items: center; gap: var(--space-2); }

@media (max-width: 480px) {
  .ack-block-card { padding: var(--space-5); }
  .ack-block-footer { justify-content: center; }
}

/* ===========================================================================
   Выключенный модуль
   ===========================================================================

   Три вещи разом, и все три - в каркасе, а не в страницах: страница закрытого
   раздела у обычной роли, полоса «только просмотр» у кадровика с
   администратором и правило, прячущее кнопки создания.

   Кнопки помечены data-module-write и прячутся классом на body. Правило стоит
   ЗДЕСЬ, а не переключением style у каждой кнопки: страниц сорок, и страница,
   забывшая пройтись по своим кнопкам, показывала бы их как ни в чём не бывало.
   Сам запрет при этом на сервере - спрятанная кнопка лишь избавляет от
   нажатия, которое всё равно кончится отказом.
   =========================================================================== */

body.module-disabled [data-module-write] { display: none !important; }

.module-block-screen {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-8) var(--space-4);
}

.module-block-card {
  width: 100%;
  max-width: 480px;
  padding: var(--space-8);
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  text-align: center;
}

.module-block-icon {
  display: flex;
  justify-content: center;
  margin-bottom: var(--space-4);
  color: var(--text-secondary);
}
.module-block-icon svg { width: 40px; height: 40px; }

.module-block-title {
  margin: 0 0 var(--space-2);
  font-size: var(--text-xl);
  font-weight: 600;
}

.module-block-text {
  margin: 0 0 var(--space-6);
  color: var(--text-secondary);
}

.module-notice {
  margin-bottom: var(--space-4);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-warning);
  border-radius: var(--radius-md);
  background: var(--bg-surface);
  color: var(--text-primary);
  font-size: var(--text-sm);
}

@media (max-width: 480px) {
  .module-block-card { padding: var(--space-5); }
}

/* Перечень повисающего в предпросмотре выключения: список, а не таблица -
   строк три-четыре, и каждая из них предложение, а не ячейка. */
.module-preview-list {
  margin: var(--space-2) 0 var(--space-4);
  padding-left: var(--space-5);
  color: var(--text-secondary);
  font-size: var(--text-sm);
}
.module-preview-list li { margin-bottom: var(--space-1); }

/* Подсказка страницы под заголовком (admin-users.html: где заводится учётка
   сотрудника). Заголовок уже даёт нижний отступ - подсказка встаёт под ним. */
.page-hint { margin: calc(-1 * var(--space-3)) 0 var(--space-4); }

/* Ряд галочек одного поля (например, «Кому видна» у статьи базы знаний):
   в строку с переносом, а не столбиком на пол-экрана. */
.checkbox-row { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-4); }

/* Подсказка «где искать обучение» (тема 6, PR3): над содержимым страницы,
   пока человек её не закрыл или не перешёл к обучению. */
.training-hint {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
  margin-bottom: var(--space-4);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-primary);
  border-radius: var(--radius-md);
  background: var(--bg-surface);
  color: var(--text-primary);
  font-size: var(--text-sm);
}
.training-hint__text { flex: 1 1 240px; }
.training-hint__close { margin-left: auto; font-size: var(--text-lg); line-height: 1; }

/* «Оформление» в «Моём профиле» (тема 9): два списка в ряд, на телефоне -
   друг под другом. */
.appearance-card { margin-bottom: var(--space-4); }
.appearance-fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: var(--space-4); }

/* ============================================================
   Телефон для трёх стилей (тема 9, 9-5)
   ============================================================
   Правила владельца на телефоне: ни одной горизонтальной прокрутки,
   таблица - карточками (вся строка в карточке, нажатие открывает запись),
   всё нажимаемое - не ниже 40px. «Пульт» и «Доска» раскладывают таблицы
   карточками сами (уже 900px); здесь - то же для «Классического» и общие
   для всех стилей размеры. */
@media (max-width: 899px) {
  /* Таблица - карточками, подпись ячейки - из заголовка столбца (layout.js
     ставит data-label и в «Классическом»). Граница - 899px, как у «Пульта»
     и «Доски»: на планшете (768px) рядом с боковым меню таблице остаётся
     ~440px. «Пульт» и «Доска» перекрывают это своими правилами ниже. */
  .page-content .table-wrap { overflow-x: visible; }
  .page-content .table thead { display: none; }
  .page-content .table,
  .page-content .table tbody,
  .page-content .table tr,
  .page-content .table td { display: block; width: 100%; min-width: 0; }
  .page-content .table tbody tr {
    border-bottom: 1px solid var(--border-default);
    padding: var(--space-3) var(--space-3);
  }
  .page-content .table tbody tr:last-child { border-bottom: none; }
  .page-content .table tbody td {
    border-bottom: none;
    padding: var(--space-1) 0;
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    justify-content: space-between;
    text-align: right;
    white-space: normal;
  }
  .page-content .table tbody td[data-label]::before {
    content: attr(data-label);
    color: var(--text-secondary);
    font-size: var(--text-xs);
    text-align: left;
    flex-shrink: 0;
    max-width: 45%;
  }
  .page-content .table tbody td.table-state-cell { display: block; text-align: left; }
  /* Длинный e-mail или логин без пробелов (data-long от layout.js)
     переносится, иначе одна такая ячейка выводила карточку за край. */
  .page-content .table td[data-long] { overflow-wrap: anywhere; }
  /* Числа, даты, плашки - одним куском. */
  .page-content .table .cell-keep,
  .page-content .table .badge { white-space: nowrap; }
}
@media (max-width: 767px) {
  /* Шапка: длинное название юрлица - многоточием и не шире ~трети экрана;
     крошки сжимаются и обрезаются, а не уезжают под кнопки справа (кнопки
     шапки не сжимаются, и текст крошек раньше рисовался под названием
     юрлица). */
  .topbar-lead,
  .breadcrumbs { overflow: hidden; }
  .entity-chip { max-width: 36vw; min-width: 0; }
  /* Фильтры - одной колонкой во всю ширину: два поля в ряд на 360px
     обрезали подписи выбора («Работающи…»), а узбекские длиннее. */
  .page-content .filters-bar {
    flex-direction: column;
    align-items: stretch;
    width: 100%;
  }
  .page-content .filters-bar .filter-field { width: 100%; flex: 0 0 auto; }
  .page-content .filters-bar .filter-field input.input,
  .page-content .filters-bar .filter-field select.input { width: 100%; min-width: 0; }
  /* Нажимаемое - не ниже 40px во всех стилях. */
  .page-content .btn,
  .page-content .tab,
  .page-content .pagination button,
  .tab-bar-item { min-height: 40px; }
  .page-content .btn-icon { min-width: 40px; }
}

/* ============================================================
   Вид меню на компьютере (тема 34, layout.js initSidebarMode):
   data-sidebar на <html> - full (как было) / icons / hidden.
   Всё - под min-width: 768px: на телефоне меню всегда выдвижное, и
   правила выше (max-width: 767px) действуют как раньше. Селекторы с
   :root[data-sidebar] сильнее правил стилей (они под :where), поэтому
   один набор работает в «Классическом», «Пульте» и «Доске».
   ============================================================ */
.sidebar-mode-picker { position: relative; display: inline-flex; flex-shrink: 0; }
.sidebar-mode-menu {
  top: calc(100% + var(--space-1));
  left: 0;
  min-width: 220px;
}
.sidebar-tip {
  position: fixed;
  z-index: var(--z-toast);
  max-width: 240px;
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-md);
  background: var(--text-primary);
  color: var(--bg-surface);
  font-size: var(--text-sm);
  line-height: 1.3;
  box-shadow: var(--shadow-lg);
  pointer-events: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.sidebar-tip[hidden] { display: none; }

@media (max-width: 767px) {
  .sidebar-mode-picker { display: none; }
  .sidebar-tip { display: none; }
}

@media (min-width: 768px) {
  .sidebar { transition: transform var(--transition-base), width var(--transition-base); }
  .main-content { transition: margin-left var(--transition-base); }

  /* --- Только значки: полоса 64px, подпись - подсказкой --- */
  /* overflow: hidden - что бы ни оказалось в панели шире полосы (длинная
     подпись, чужой блок), оно обрезается по её краю, а не ложится поверх
     страницы: отступ страницы и ширина меню всегда совпадают. Подсказки
     живут в <body>, их это не режет. */
  :root[data-sidebar="icons"] .sidebar { width: 64px; overflow: hidden; }
  :root[data-sidebar="icons"] .main-content { margin-left: 64px; }
  :root[data-sidebar="icons"] .sidebar-brand { justify-content: center; padding: var(--space-4) 0; }
  :root[data-sidebar="icons"] .sidebar .brand-text { display: none; }
  :root[data-sidebar="icons"] .sidebar-nav { padding: var(--space-1) 10px var(--space-3); overflow-x: hidden; }
  :root[data-sidebar="icons"] .sidebar-group-label { display: none; }
  :root[data-sidebar="icons"] .sidebar-group + .sidebar-group {
    margin-top: var(--space-2);
    padding-top: var(--space-2);
    /* --sidebar-line есть только у тёмных панелей «Пульта» и «Доски»;
       в «Классическом» - обычная линия. */
    border-top: 1px solid var(--sidebar-line, var(--border-default));
  }
  :root[data-sidebar="icons"] .sidebar-link {
    position: relative;
    justify-content: center;
    gap: 0;
    padding: 10px 0;
  }
  /* Название остаётся в разметке - его читает экранный диктор и берёт
     подсказка; спрятано только с экрана. */
  :root[data-sidebar="icons"] .sidebar-link > span[data-i18n] {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }
  :root[data-sidebar="icons"] .sidebar-link .sidebar-off { display: none; }
  /* Счётчик - маленькой плашкой на углу значка. */
  :root[data-sidebar="icons"] .sidebar-count {
    position: absolute;
    top: 2px;
    right: 2px;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    font-size: 10px;
    line-height: 16px;
  }
  :root[data-sidebar="icons"] .sidebar-footer {
    flex-direction: column;
    gap: var(--space-2);
    padding: var(--space-3) 0;
  }
  :root[data-sidebar="icons"] .sidebar-footer > div:not(.avatar) { display: none; }
  :root[data-sidebar="icons"] .sidebar-footer .btn { margin-left: 0 !important; }

  /* --- Скрыто: страница во всю ширину, меню - поверх неё по кнопке --- */
  :root[data-sidebar="hidden"] .sidebar {
    transform: translateX(-100%);
    visibility: hidden;
    transition: transform var(--transition-base), visibility 0s linear var(--transition-base);
  }
  :root[data-sidebar="hidden"] .sidebar.open {
    transform: translateX(0);
    visibility: visible;
    transition: transform var(--transition-base);
    box-shadow: var(--shadow-xl);
    z-index: calc(var(--z-header) + 2);
  }
  :root[data-sidebar="hidden"] .main-content { margin-left: 0; }
  :root[data-sidebar="hidden"] .hamburger-btn { display: inline-flex; }
  :root[data-sidebar="hidden"] .topbar-brand { display: inline-flex; }
  :root[data-sidebar="hidden"] .sidebar-backdrop {
    position: fixed;
    inset: 0;
    background: var(--bg-overlay);
    z-index: calc(var(--z-header) + 1);
  }
}

/* ============================================================
   Стиль «Пульт» (тема 9, 9-1): каркас и общие элементы
   ============================================================
   Всё ниже действует при любом стиле, кроме «Классического»
   (:root:not([data-style="classic"])): «Пульт» и «Доска» - одна семья,
   «Доска» (тема 9-3) берёт общие правила и экраны «Пульта» и меняет только
   своё - раздел «Стиль Доска» в конце файла и токены design-system.css.
   Атрибут ставит скрипт в <head> до первой отрисовки, поэтому
   «Классический» эти правила не видит вовсе и выглядит ровно как раньше. Цвета - только
   токенами из design-system.css (там же светлая и тёмная палитры).

   Селекторы обёрнуты в :where(): у правила остаётся вес самого класса, и
   стили конкретной страницы (leaves.css, orders.css и т. п., они
   подключаются позже) по-прежнему перекрывают общий вид, как и в
   «Классическом». Без обёртки «Пульт» перебивал бы их приставкой :root.
   Исключение - полоски календаря: их правило живёт в leaves.css, и цвет
   акцента обязан взять верх над ним. */

/* --- Боковое меню: тёмная панель с группами --- */
:where(:root:not([data-style="classic"])) .sidebar {
  background: var(--sidebar-bg);
  border-right: none;
}
:where(:root:not([data-style="classic"])) .sidebar {
  --logo-ink: var(--sidebar-strong);
}
:where(:root:not([data-style="classic"])) .sidebar .brand-name { font-size: 18px; font-weight: 700; }
:where(:root:not([data-style="classic"])) .sidebar .brand-tagline { font-size: 12px; color: var(--sidebar-text); }
:where(:root:not([data-style="classic"])) .sidebar-nav { gap: 2px; padding: var(--space-1) var(--space-3) var(--space-3); }
:where(:root:not([data-style="classic"])) .sidebar-group { display: flex; flex-direction: column; gap: 2px; }
:where(:root:not([data-style="classic"])) .sidebar-group + .sidebar-group { margin-top: var(--space-3); }
:where(:root:not([data-style="classic"])) .sidebar-group-label {
  padding: var(--space-2) 12px var(--space-1);
  font-size: 12px;
  font-weight: 600;
  color: var(--sidebar-group);
}
:where(:root:not([data-style="classic"])) .sidebar-link {
  padding: 9px 12px;
  border-radius: var(--radius-control);
  font-size: 15px;
  color: var(--sidebar-text);
}
:where(:root:not([data-style="classic"])) .sidebar-link:hover {
  background: var(--sidebar-hover-bg);
  color: var(--sidebar-strong);
}
:where(:root:not([data-style="classic"])) .sidebar-link.active {
  background: var(--sidebar-active-bg);
  color: var(--sidebar-active-text);
}
:where(:root:not([data-style="classic"])) .sidebar-link.is-off { color: var(--sidebar-group); }
:where(:root:not([data-style="classic"])) .sidebar-link.is-off:hover,
:where(:root:not([data-style="classic"])) .sidebar-link.is-off.active {
  background: var(--sidebar-hover-bg);
  color: var(--sidebar-text);
}
/* Счётчик - плашка акцента справа. На активном пункте фон пункта тоже
   акцентный, поэтому там плашка меняется местами с текстом. */
:where(:root:not([data-style="classic"])) .sidebar-count {
  background: var(--color-primary);
  color: var(--color-on-brand);
}
:where(:root:not([data-style="classic"])) .sidebar-link.active .sidebar-count {
  background: var(--sidebar-active-text);
  color: var(--sidebar-active-bg);
}
:where(:root:not([data-style="classic"])) .sidebar-footer { border-top: 1px solid var(--sidebar-line); }
:where(:root:not([data-style="classic"])) .sidebar-footer .avatar {
  width: 36px;
  height: 36px;
  border-radius: var(--radius-avatar);
  background: var(--color-primary);
  color: var(--color-on-brand);
  font-size: 13px;
}
:where(:root:not([data-style="classic"])) .sidebar-footer .user-name { color: var(--sidebar-strong); }
:where(:root:not([data-style="classic"])) .sidebar-footer .user-role { color: var(--sidebar-text); }
:where(:root:not([data-style="classic"])) .sidebar .btn-ghost { color: var(--sidebar-text); }
:where(:root:not([data-style="classic"])) .sidebar .btn-ghost:hover:not(:disabled) {
  background: var(--sidebar-hover-bg);
  color: var(--sidebar-strong);
}

/* --- Шапка страницы: крошки и заголовок на фоне страницы --- */
/* Шапка остаётся прилипающей (на ней язык, тема и колокольчик), но без
   своей плашки и линии - её фон совпадает с фоном страницы. Высота по
   содержимому: при переносе на узком экране ряд растёт, а не налезает на
   заголовок страницы под ним. */
:where(:root:not([data-style="classic"])) .topbar {
  height: auto;
  min-height: 64px;
  padding: 22px 32px 8px;
  background: var(--bg-app);
  border-bottom: none;
}
:where(:root:not([data-style="classic"])) .breadcrumbs,
:where(:root:not([data-style="classic"])) .breadcrumbs .current {
  font-size: 14px;
  font-weight: 400;
  color: var(--text-secondary);
}
:where(:root:not([data-style="classic"])) .page-content { padding: 8px 32px 32px; }
/* Крошки через «/», как в макетах: шеврон прячется, разделитель - текстом. */
:where(:root:not([data-style="classic"])) .breadcrumbs > i,
:where(:root:not([data-style="classic"])) .breadcrumbs > svg { display: none; }
:where(:root:not([data-style="classic"])) .breadcrumbs { gap: 0.35em; }
:where(:root:not([data-style="classic"])) .breadcrumbs .current::before { content: "/\00a0"; }
/* Юрлицо, колокольчик, язык и тема - отдельные кнопки с рамкой на фоне
   страницы (макеты, правый верхний угол каждой страницы). */
:where(:root:not([data-style="classic"])) .topbar-actions { gap: var(--space-2); }
:where(:root:not([data-style="classic"])) .topbar-actions .entity-chip,
:where(:root:not([data-style="classic"])) .topbar-actions .nb-btn,
:where(:root:not([data-style="classic"])) .topbar-actions #langToggleBtn,
:where(:root:not([data-style="classic"])) .topbar-actions #themeToggleBtn {
  height: 40px;
  min-width: 40px;
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-control);
  color: var(--text-primary);
}
:where(:root:not([data-style="classic"])) .page-title { font-size: 28px; font-weight: 700; }

/* --- Карточки и контейнеры --- */
:where(:root:not([data-style="classic"])) .card,
:where(:root:not([data-style="classic"])) .table-wrap {
  background: var(--bg-surface);
  border: var(--container-border);
  border-radius: var(--radius-container);
  box-shadow: none;
}
/* Таблица внутри карточки - часть карточки, второй рамки ей не нужно. */
:where(:root:not([data-style="classic"])) .card .table-wrap { border-radius: 0; }

/* --- Кнопки --- */
:where(:root:not([data-style="classic"])) .btn {
  border-radius: var(--radius-button);
  font-size: 15px;
  font-weight: 600;
}
:where(:root:not([data-style="classic"])) .btn-sm { font-size: 13px; border-radius: var(--radius-control); }
:where(:root:not([data-style="classic"])) .btn-secondary { border-color: var(--border-default); }

/* --- Поля ввода и подписи над ними --- */
:where(:root:not([data-style="classic"])) .input { border-radius: var(--radius-control); border-color: var(--border-default); }
:where(:root:not([data-style="classic"])) .label,
:where(:root:not([data-style="classic"])) .filter-field label {
  font-size: 13px;
  font-weight: 500;
  color: var(--text-secondary);
}

/* --- Вкладки: черта акцента под активной (макеты 9-2, стр. 3-12) ---
   В 9-1 активная вкладка была акцентной плашкой; утверждённые макеты
   (docs/design/pult) рисуют её жирной подписью с чертой акцента снизу на
   общей линии - так и сделано. */
:where(:root:not([data-style="classic"])) .tabs {
  gap: var(--space-6);
  border-bottom: 1px solid var(--border-default);
}
:where(:root:not([data-style="classic"])) .tab {
  padding: 8px 4px 10px;
  font-size: 15px;
  font-weight: 500;
  color: var(--text-secondary);
}
:where(:root:not([data-style="classic"])) .tab:hover { color: var(--text-primary); }
:where(:root:not([data-style="classic"])) .tab-active,
:where(:root:not([data-style="classic"])) .tab-active:hover {
  color: var(--text-primary);
  font-weight: 700;
}
:where(:root:not([data-style="classic"])) .tab-active::after {
  height: 3px;
  background: var(--color-primary);
}

/* --- Таблицы --- */
:where(:root:not([data-style="classic"])) .table { font-size: 15px; }
:where(:root:not([data-style="classic"])) .table th {
  font-size: 13px;
  font-weight: 500;
  text-transform: none;
  letter-spacing: 0;
  color: var(--text-secondary);
  background: transparent;
  border-bottom: 1px solid var(--border-default);
}
:where(:root:not([data-style="classic"])) .table td { border-bottom: 1px solid var(--border-default); }
/* Без прокрутки вбок (правило владельца): колонки ужимаются переносом по
   пробелам; не хватает и этого - таблица становится карточками (ниже). */
/* min-width снимается и с самой таблицы, и с ячеек: страницы задают его
   («Классическому» он включает прокрутку, hr.css .employees-table 760px),
   а «Пульту» прокрутка запрещена. Вес .page-content .table выше одиночного
   класса страницы, поэтому снимается без !important. */
:where(:root:not([data-style="classic"])) .page-content .table { min-width: 0; }
:where(:root:not([data-style="classic"])) .table th,
:where(:root:not([data-style="classic"])) .table td {
  min-width: 0;
  white-space: normal;
  overflow-wrap: normal;
  word-break: normal;
}
/* Обычные слова переносятся только по пробелам - и на ноутбуке тоже
   (замечание владельца к #91: «Специалист», «Акт|ивн|а», «SampCor|p» на
   1100-1280px). Внутри слова рвутся только длинные e-mail, логины и коды:
   такую ячейку отмечает layout.js (data-long). */
:where(:root:not([data-style="classic"])) .table td[data-long] { overflow-wrap: anywhere; }
/* Плашки (статус, категория, «Не переведено») - всегда одной строкой. */
:where(:root:not([data-style="classic"])) .table .badge,
:where(:root:not([data-style="classic"])) .table .status-badge { white-space: nowrap; }
/* Ноутбук: колонкам тесно - сначала плотнее строка, а не рваные слова. */
@media (max-width: 1365px) {
  :where(:root:not([data-style="classic"])) .table { font-size: 14px; }
  :where(:root:not([data-style="classic"])) .table th,
  :where(:root:not([data-style="classic"])) .table td { padding: 12px 10px; }
}
/* Строка - карточка «подпись: значение». Всегда уже 900px, а шире - если
   таблица не помещается даже со словами целиком: тогда layout.js ставит ей
   .pult-cards (замер ширины на каждой перерисовке и смене размера окна).
   Подписи ставит layout.js из заголовка столбца (data-label). */
:where(:root:not([data-style="classic"])) .page-content .table.pult-cards thead { display: none; }
:where(:root:not([data-style="classic"])) .page-content .table.pult-cards,
:where(:root:not([data-style="classic"])) .page-content .table.pult-cards tbody,
:where(:root:not([data-style="classic"])) .page-content .table.pult-cards tr,
:where(:root:not([data-style="classic"])) .page-content .table.pult-cards td { display: block; width: 100%; }
:where(:root:not([data-style="classic"])) .page-content .table.pult-cards tbody tr {
  border-bottom: 1px solid var(--border-default);
  padding: var(--space-3) var(--space-4);
}
:where(:root:not([data-style="classic"])) .page-content .table.pult-cards tbody tr:last-child { border-bottom: none; }
:where(:root:not([data-style="classic"])) .page-content .table.pult-cards tbody td {
  border-bottom: none;
  padding: var(--space-1) 0;
  display: flex;
  /* Не помещается в строку с подписью - значение уходит под неё:
     плашки и слова при этом целые (замечание владельца к #91). */
  flex-wrap: wrap;
  gap: var(--space-3);
  justify-content: space-between;
  text-align: right;
}
:where(:root:not([data-style="classic"])) .page-content .table.pult-cards tbody td[data-label]::before {
  content: attr(data-label);
  color: var(--text-secondary);
  font-size: 13px;
  text-align: left;
  flex-shrink: 0;
  max-width: 45%;
}
:where(:root:not([data-style="classic"])) .page-content .table.pult-cards tbody td.table-state-cell { display: block; text-align: left; }
@media (max-width: 899px) {
  :where(:root:not([data-style="classic"])) .page-content .table thead { display: none; }
  :where(:root:not([data-style="classic"])) .page-content .table,
  :where(:root:not([data-style="classic"])) .page-content .table tbody,
  :where(:root:not([data-style="classic"])) .page-content .table tr,
  :where(:root:not([data-style="classic"])) .page-content .table td { display: block; width: 100%; }
  :where(:root:not([data-style="classic"])) .page-content .table tbody tr {
    border-bottom: 1px solid var(--border-default);
    padding: var(--space-3) var(--space-4);
  }
  :where(:root:not([data-style="classic"])) .page-content .table tbody tr:last-child { border-bottom: none; }
  :where(:root:not([data-style="classic"])) .page-content .table tbody td {
    border-bottom: none;
    padding: var(--space-1) 0;
    display: flex;
    /* Не помещается в строку с подписью - значение уходит под неё:
       плашки и слова при этом целые (замечание владельца к #91). */
    flex-wrap: wrap;
    gap: var(--space-3);
    justify-content: space-between;
    text-align: right;
  }
  :where(:root:not([data-style="classic"])) .page-content .table tbody td[data-label]::before {
    content: attr(data-label);
    color: var(--text-secondary);
    font-size: 13px;
    text-align: left;
    flex-shrink: 0;
    max-width: 45%;
  }
  :where(:root:not([data-style="classic"])) .page-content .table tbody td.table-state-cell { display: block; text-align: left; }
  /* Конструктор заявок (список типов + редактор): в «Пульте» шрифт крупнее, и
     на 768-899px редактору рядом со списком не хватает места - он вылезал за
     край. Как на телефоне: список над редактором. Без :where() - правило
     requests.css подключается позже и иначе перебило бы это. */
  :root:not([data-style="classic"]) .constructor-layout { grid-template-columns: minmax(0, 1fr); }
}

/* --- Значки статусов --- */
:where(:root:not([data-style="classic"])) .badge {
  font-size: 13px;
  font-weight: 600;
  padding: 3px 10px;
}

/* --- Списки: контейнер до низа страницы, листалка внизу ---
   Правила владельца для всех списков: контейнер списка тянется до низа
   окна, листалка прижата к низу контейнера, блок фильтров - по своему
   содержимому, без горизонтальной прокрутки. */
:where(:root:not([data-style="classic"])) .page-content {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
/* Список часто обёрнут в блок вкладки (<div id="listView">) - поэтому
   растёт вся цепочка: обёртка без своего класса, карточка, контейнер
   таблицы, до трёх уровней вглубь. Блоки с собственной раскладкой (сетки,
   ряды карточек) в цепочку не входят - их раскладку «Пульт» не ломает.
   Скрытое (.hidden, style="display:none") скрытым и остаётся: у них
   display сильнее этого правила. */
:where(:root:not([data-style="classic"])) .page-content > :is(.card, .table-wrap, div:not([class])):has(.table):not(.filters-bar),
:where(:root:not([data-style="classic"])) .page-content > :is(.card, .table-wrap, div:not([class])):has(.table) > :is(.card, .table-wrap, div:not([class])):has(.table):not(.filters-bar),
:where(:root:not([data-style="classic"])) .page-content > :is(.card, .table-wrap, div:not([class])):has(.table) > :is(.card, .table-wrap, div:not([class])):has(.table) > :is(.card, .table-wrap, div:not([class])):has(.table):not(.filters-bar) {
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
}
:where(:root:not([data-style="classic"])) .page-content .pagination { margin-top: auto; padding-top: var(--space-5); }
/* fit-content, а не align-self: фильтры часто лежат во вкладке, а не прямо
   в .page-content. Слишком длинный ряд всё равно переносится по ширине. */
:where(:root:not([data-style="classic"])) .filters-bar {
  width: fit-content;
  max-width: 100%;
}
/* Поиск с подписью «Поиск» стоит в одном ряду с фильтрами, а не над ними. */
:where(:root:not([data-style="classic"])) .filter-field-search { flex: 0 1 220px; }
:where(:root:not([data-style="classic"])) .filter-field-search .input { min-width: 0; }

/* --- Полоски календаря отпусков - цвет акцента темы --- */
:root:not([data-style="classic"]) .calendar-chip {
  background: var(--color-primary);
  color: var(--color-on-brand);
}
:root:not([data-style="classic"]) .calendar-chip.manager_approved {
  background: var(--color-primary-subtle-bg);
  color: var(--color-primary);
}

/* --- Разметка только одного стиля (9-2а) ---
   .pult-only - блоки, которых в «Классическом» нет вовсе (приветствие
   главной, шапка карточки сотрудника); .classic-only - то, что «Пульт»
   заменяет своим. Ячейки таблиц: .col-console / .col-classic. */
:root[data-style="classic"] .pult-only,
:root[data-style="classic"] .col-console { display: none !important; }
:root:not([data-style="classic"]) .classic-only,
:root:not([data-style="classic"]) .col-classic { display: none !important; }

/* --- Общие куски экранов «Пульта» (макеты 02-60) --- */
:where(:root:not([data-style="classic"])) .pult-muted { color: var(--text-secondary); font-size: 14px; }
:where(:root:not([data-style="classic"])) .cell-main { display: block; font-weight: 600; color: var(--text-primary); }
:where(:root:not([data-style="classic"])) .cell-sub { display: block; margin-top: 2px; font-size: 13px; color: var(--text-secondary); }
/* Номер документа, дата, период «с - по» - одной строкой на любой ширине
   (замечание владельца к #93: «LC9-|86569», «21.10.|2026»). Колонка не
   ужимается уже такого значения: место уступают колонки с текстом (перенос
   по пробелам), а не хватит и его - таблица становится карточками. */
:where(:root:not([data-style="classic"])) .cell-keep { white-space: nowrap; overflow-wrap: normal; }
/* Плитки с числом (главные, отпуска): белая, акцентная и тёмная. */
:where(:root:not([data-style="classic"])) .pult-kpis {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--space-4);
}
:where(:root:not([data-style="classic"])) .pult-kpi {
  padding: 20px 18px;
  border: var(--container-border);
  border-radius: var(--radius-container);
  background: var(--bg-surface);
  color: var(--text-primary);
}
:where(:root:not([data-style="classic"])) .pult-kpi__value { font-size: 40px; font-weight: 700; line-height: 1.1; }
:where(:root:not([data-style="classic"])) .pult-kpi__label { margin-top: var(--space-2); font-size: 14px; color: var(--text-secondary); }
:where(:root:not([data-style="classic"])) .pult-kpi__note { margin-top: var(--space-1); font-size: 12px; color: var(--text-secondary); }
:where(:root:not([data-style="classic"])) .pult-kpi.is-accent { background: var(--color-primary); color: var(--color-on-brand); }
:where(:root:not([data-style="classic"])) .pult-kpi.is-accent .pult-kpi__label,
:where(:root:not([data-style="classic"])) .pult-kpi.is-accent .pult-kpi__note { color: var(--color-on-brand); }
:where(:root:not([data-style="classic"])) .pult-actions { display: flex; flex-wrap: wrap; gap: var(--space-2); }

/* --- Главная (стр. 2, 55, 56, 60) --- */
/* Подсказка об обучении - под заголовком страницы, как в макетах 55 и 60
   (в разметке она стоит первой, .page-content у «Пульта» - флекс-колонка). */
:where(:root:not([data-style="classic"])) .page-content > .page-header { order: -2; }
:where(:root:not([data-style="classic"])) .page-content > .training-hint { order: -1; }
:where(:root:not([data-style="classic"])) .training-hint {
  border: var(--container-border);
  border-radius: var(--radius-container);
  background: var(--color-primary-subtle-bg);
}
:where(:root:not([data-style="classic"])) #dashboardWidgets {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--space-4);
  align-items: stretch;
}
:where(:root:not([data-style="classic"])) #dashboardWidgets > * { grid-column: 1 / -1; margin-top: 0; }
/* Блок аналитики раскладывает свои карточки прямо в сетку главной. */
:where(:root:not([data-style="classic"])) #dashboardWidgets > #analyticsWidget { display: contents; }
:where(:root:not([data-style="classic"])) #employeeWidgets { display: flex; flex-direction: column; gap: var(--space-4); }
:where(:root:not([data-style="classic"])) .pult-dash-card { margin: 0; padding: 22px 24px; }
:where(:root:not([data-style="classic"])) .pult-dash-card .card-title { margin-bottom: var(--space-4); font-size: 18px; font-weight: 700; }
:where(:root:not([data-style="classic"])) .pult-dash-card__title { font-size: 17px; font-weight: 600; }
:where(:root:not([data-style="classic"])) .pult-dash-card__row { display: flex; align-items: flex-end; justify-content: space-between; gap: var(--space-3); }
:where(:root:not([data-style="classic"])) .pult-dash-card__row.is-start { justify-content: flex-start; align-items: baseline; }
:where(:root:not([data-style="classic"])) .pult-dash-card__link { color: inherit; font-size: 14px; font-weight: 600; text-decoration: underline; }
:where(:root:not([data-style="classic"])) .pult-dash-card__more { display: inline-block; margin-top: var(--space-3); font-size: 14px; }
:where(:root:not([data-style="classic"])) .pult-dash-card__caption {
  padding-bottom: var(--space-2);
  margin-bottom: var(--space-2);
  border-bottom: 1px solid currentColor;
  font-size: 14px;
}
:where(:root:not([data-style="classic"])) .pult-hero-number { font-size: 120px; font-weight: 700; line-height: 1; letter-spacing: -0.03em; }
:where(:root:not([data-style="classic"])) .pult-big-number { font-size: 64px; font-weight: 700; line-height: 1.05; }
:where(:root:not([data-style="classic"])) .pult-big-number.is-accent { color: var(--color-primary); }
:where(:root:not([data-style="classic"])) .pult-dash-card.is-dark {
  display: flex;
  flex-direction: column;
  background: var(--sidebar-bg);
  color: var(--sidebar-strong);
}
:where(:root:not([data-style="classic"])) .pult-dash-card.is-dark .pult-dash-card__foot { margin-top: auto; padding-top: var(--space-6); }
:where(:root:not([data-style="classic"])) .pult-dash-card.is-accent { background: var(--color-primary); color: var(--color-on-brand); }
:where(:root:not([data-style="classic"])) .pult-kv { display: flex; justify-content: space-between; gap: var(--space-3); padding: 4px 0; font-size: 15px; }
:where(:root:not([data-style="classic"])) .pult-kv.is-muted { color: var(--sidebar-text); }
:where(:root:not([data-style="classic"])) .pult-person-list { display: flex; flex-direction: column; }
:where(:root:not([data-style="classic"])) .pult-person-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: 12px 0;
  border-top: 1px solid var(--border-default);
  color: var(--text-primary);
  text-decoration: none;
}
:where(:root:not([data-style="classic"])) .pult-person-row__text { display: flex; flex-direction: column; min-width: 0; }
:where(:root:not([data-style="classic"])) .pult-person-row__days { display: flex; flex-direction: column; align-items: flex-end; font-size: 12px; color: var(--text-secondary); }
:where(:root:not([data-style="classic"])) .pult-person-row__days strong { font-size: 26px; line-height: 1.1; color: var(--text-primary); }
:where(:root:not([data-style="classic"])) .pult-person-row__days.is-accent strong { color: var(--color-primary); }
:where(:root:not([data-style="classic"])) .pult-mini-stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-3); margin-bottom: var(--space-4); }
:where(:root:not([data-style="classic"])) .pult-mini-stat {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: 12px 14px;
  border-top: 3px solid var(--border-default);
  border-radius: var(--radius-button);
  background: var(--bg-pale);
  color: var(--text-secondary);
  font-size: 14px;
  text-decoration: none;
}
:where(:root:not([data-style="classic"])) .pult-mini-stat.is-accent { border-top-color: var(--color-primary); }
:where(:root:not([data-style="classic"])) .pult-mini-stat strong { font-size: 30px; line-height: 1; color: var(--text-primary); }
:where(:root:not([data-style="classic"])) .pult-bar { display: flex; gap: 4px; height: 10px; margin: var(--space-4) 0 var(--space-2); }
:where(:root:not([data-style="classic"])) .pult-bar__part { border-radius: var(--radius-full); background: var(--sidebar-bg); }
:where(:root:not([data-style="classic"])) .pult-bar__part:nth-child(2n) { background: var(--color-primary); }
:where(:root:not([data-style="classic"])) .pult-bar__part.is-empty { flex: 1; background: var(--border-default); }
:where(:root:not([data-style="classic"])) .pult-legend { display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--space-2); font-size: 14px; color: var(--text-secondary); }
:where(:root:not([data-style="classic"])) .pult-legend strong { color: var(--text-primary); }
/* Уже 1100px блоки сводки - во всю ширину. Они лежат в #analyticsWidget
   (display: contents), и правило для прямых детей сетки их не касается: без
   этого каждый занимал одну двенадцатую (48px на 800 и 375). Медиазапросы
   ниже - с тем же весом и позже, поэтому на ноутбуке и планшете берут верх. */
:where(:root:not([data-style="classic"])) #pultHeadcount,
:where(:root:not([data-style="classic"])) #pultUnack,
:where(:root:not([data-style="classic"])) #pultExpiring,
:where(:root:not([data-style="classic"])) #pultRequests,
:where(:root:not([data-style="classic"])) #pultLeavesToday { grid-column: 1 / -1; }
/* Раскладка главной кадровика - как на стр. 2. */
@media (min-width: 1100px) {
  :where(:root:not([data-style="classic"])) #dashboardWidgets > #probationMineWidget { grid-column: 1 / -1; }
  :where(:root:not([data-style="classic"])) #pultHeadcount { grid-column: 1 / 6; grid-row: 1 / 3; }
  :where(:root:not([data-style="classic"])) #pultUnack { grid-column: 6 / 10; grid-row: 1; }
  :where(:root:not([data-style="classic"])) #pultExpiring { grid-column: 10 / 13; grid-row: 1; }
  :where(:root:not([data-style="classic"])) #dashboardWidgets > #probationEndingWidget { grid-column: 6 / 13; grid-row: 2; }
  :where(:root:not([data-style="classic"])) #dashboardWidgets > #hrTasksWidget { grid-column: 1 / 8; grid-row: 3; }
  :where(:root:not([data-style="classic"])) #pultRequests { grid-column: 8 / 13; grid-row: 3; }
  :where(:root:not([data-style="classic"])) #pultLeavesToday { grid-column: 1 / 13; grid-row: 4; }
}
@media (min-width: 700px) and (max-width: 1099px) {
  :where(:root:not([data-style="classic"])) #pultUnack,
  :where(:root:not([data-style="classic"])) #pultExpiring,
  :where(:root:not([data-style="classic"])) #pultRequests { grid-column: span 6; }
}
/* Главные руководителя и директора (стр. 55, 56): плитки, под ними - две
   колонки блоков, каждая своей высоты. Не ряды общей сетки: короткий блок
   рядом с длинным оставлял под собой пустую полосу до следующего ряда
   (замечание владельца к #106). Блок идёт первым - раньше блока
   испытательного срока, который грузится отдельно. Плитки - ровным рядом:
   четыре в строку от 1100px, уже - по две; на узком экране блоки - одной
   колонкой в порядке важности. */
:where(:root:not([data-style="classic"])) #dashboardWidgets > #roleHomeWidget { display: flex; flex-direction: column; gap: var(--space-4); order: -1; }
:where(:root:not([data-style="classic"])) #roleHomeWidget > #homeTiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
:where(:root:not([data-style="classic"])) #roleHomeWidget .home-columns { display: flex; flex-direction: column; gap: var(--space-4); }
:where(:root:not([data-style="classic"])) #roleHomeWidget .home-column { display: contents; }
:where(:root:not([data-style="classic"])) #roleHomeWidget #homeAwaiting { order: 1; }
:where(:root:not([data-style="classic"])) #roleHomeWidget #homeTeam { order: 2; }
:where(:root:not([data-style="classic"])) #roleHomeWidget #homeFigures { order: 2; }
:where(:root:not([data-style="classic"])) #roleHomeWidget #homeProbations { order: 3; }
:where(:root:not([data-style="classic"])) #roleHomeWidget #homeTurnover { order: 4; }
:where(:root:not([data-style="classic"])) #roleHomeWidget #homeUpcoming { order: 5; }
/* Статус, срок, «до» - по содержимому и одной строкой: место достаётся ФИО
   и тексту «Что». */
:where(:root:not([data-style="classic"])) #roleHomeWidget .table .col-fit { width: 1%; white-space: nowrap; }
:where(:root:not([data-style="classic"])) #roleHomeWidget .home-more { display: flex; flex-wrap: wrap; gap: 0 var(--space-4); }
:where(:root:not([data-style="classic"])) .home-figures .pult-kv { padding: 10px 0; border-top: 1px solid var(--border-default); }
/* Старый блок «Ожидают вашего заключения» на этих главных не нужен: у
   руководителя заключения уже строками «Ждут вашего решения», у директора
   блок повторял «Испытательный срок заканчивается». */
:where(:root:not([data-style="classic"])) #dashboardWidgets:has(> #roleHomeWidget) > #probationMineWidget { display: none; }
@media (min-width: 1100px) {
  :where(:root:not([data-style="classic"])) #roleHomeWidget > #homeTiles { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  :where(:root:not([data-style="classic"])) #roleHomeWidget .home-columns { display: grid; align-items: start; }
  :where(:root:not([data-style="classic"])) #roleHomeWidget[data-role="manager"] .home-columns { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  :where(:root:not([data-style="classic"])) #roleHomeWidget[data-role="director"] .home-columns { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); }
  :where(:root:not([data-style="classic"])) #roleHomeWidget .home-column { display: flex; flex-direction: column; gap: var(--space-4); }
}

/* --- Пачка 2 (9-2б): общее для всех экранов ---
   Утверждённые макеты одинаковы во всех разделах: под заголовком страницы
   нет подзаголовка, кнопки страницы стоят строкой под заголовком слева, у
   вкладок раздела нет повторного заголовка, окна - с рамкой акцента, а
   поля записи в окне - строками «подпись - значение» через линию. */
:where(:root:not([data-style="classic"])) .page-header {
  flex-direction: column;
  align-items: flex-start;
}
:where(:root:not([data-style="classic"])) .page-header .page-subtitle { display: none; }
/* Выбор в ряду кнопок страницы (год графика) - по содержимому, а не во всю
   строку: иначе кнопка рядом уезжает на следующую. */
:where(:root:not([data-style="classic"])) .page-actions .input { width: auto; }
/* Поля окна идут столбиком: между полем и подписью следующего - воздух. */
:where(:root:not([data-style="classic"])) .modal > .form-group + .form-group { margin-top: var(--space-3); }
:where(:root:not([data-style="classic"])) .view-section > .section-header .section-title { display: none; }
:where(:root:not([data-style="classic"])) .modal {
  border: 2px solid var(--color-primary);
  border-radius: var(--radius-container);
  box-shadow: none;
  background: var(--bg-surface);
}
:where(:root:not([data-style="classic"])) .modal-title { font-size: 18px; font-weight: 700; }
:where(:root:not([data-style="classic"])) .detail-grid {
  grid-template-columns: minmax(0, 1fr);
  gap: 0;
}
:where(:root:not([data-style="classic"])) .detail-item {
  display: grid;
  grid-template-columns: minmax(120px, 45%) minmax(0, 1fr);
  gap: var(--space-3);
  padding: 12px 0;
  border-bottom: 1px solid var(--border-default);
}
:where(:root:not([data-style="classic"])) .detail-item .label {
  margin: 0;
  font-size: 15px;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  color: var(--text-secondary);
}
:where(:root:not([data-style="classic"])) .detail-item .value { margin: 0; font-size: 15px; }
:where(:root:not([data-style="classic"])) .detail-section-title {
  margin-top: var(--space-4);
  font-size: 18px;
  font-weight: 700;
  letter-spacing: 0;
  text-transform: none;
  color: var(--text-primary);
}
/* Подпись под списком (макеты 17, 19, 48): мелкий текст на фоне страницы. */
:where(:root:not([data-style="classic"])) .pult-footnote { margin: var(--space-3) 0 0; font-size: 14px; color: var(--text-secondary); }

/* --- Отделы (стр. 16): «Список / Дерево» - переключатель-плашка --- */
:where(:root:not([data-style="classic"])) .page-tabs:has(#tabTree) {
  display: inline-flex;
  align-self: flex-start;
  gap: 0;
  padding: 3px;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-button);
  background: var(--bg-surface);
}
:where(:root:not([data-style="classic"])) .page-tabs:has(#tabTree) .tab {
  padding: 7px 14px;
  border-radius: var(--radius-control);
  font-weight: 600;
  color: var(--text-primary);
}
:where(:root:not([data-style="classic"])) .page-tabs:has(#tabTree) .tab-active {
  background: var(--sidebar-bg);
  color: var(--sidebar-strong);
}
:where(:root:not([data-style="classic"])) .page-tabs:has(#tabTree) .tab-active::after { display: none; }

/* --- График отпусков (стр. 20): кнопки графика - над его сведениями --- */
:where(:root:not([data-style="classic"])) #scheduleCard { display: flex; flex-direction: column; }
:where(:root:not([data-style="classic"])) #scheduleCard > #scheduleActions { order: -1; margin-bottom: var(--space-3); }
:where(:root:not([data-style="classic"])) #scheduleCard > #scheduleActions:empty { display: none; }

/* --- Телефон: те же отступы, что у «Классического» --- */
@media (max-width: 767px) {
  :where(:root:not([data-style="classic"])) .topbar { min-height: 56px; padding: var(--space-2) var(--space-3); }
  :where(:root:not([data-style="classic"])) .page-content { padding: var(--space-2) var(--space-4) var(--space-4); }
  :where(:root:not([data-style="classic"])) .page-title { font-size: 24px; }
}

/* --- Пачка 3 (9-2в): таблица в окне - в своей рамке (макеты 52, 77, 78) --- */
:where(:root:not([data-style="classic"])) .modal .table-wrap {
  border: 1px solid var(--border-default);
  border-radius: var(--radius-container);
  overflow: hidden;
}
/* Флажки и переключатели - цвета акцента, как в макетах (24, 28, 75, 84, 85). */
:where(:root:not([data-style="classic"])) :is(input[type="checkbox"], input[type="radio"]) { accent-color: var(--color-primary); }
/* Узкий экран: в окне подпись - над значением (плашка статуса одной строкой
   в половину ширины не помещалась), кнопки шапки окна переносятся под
   заголовок, а не уходят за край. */
@media (max-width: 599px) {
  :where(:root:not([data-style="classic"])) .detail-item { grid-template-columns: minmax(0, 1fr); gap: 2px; }
  :where(:root:not([data-style="classic"])) .modal-header { flex-wrap: wrap; }
}
/* Вкладки, которых больше, чем помещается в строку (справочники - 15),
   переносятся рядами без промежутка между ними (9-2д). */
:where(:root:not([data-style="classic"])) .tabs { row-gap: 0; }
/* Плитки .summary-row (сводка администрирования, стр. 62; журнал аудита) -
   как плитки «Пульта»: без полосы сверху, число над подписью и крупно. */
:where(:root:not([data-style="classic"])) .summary-row .stat-card {
  border: var(--container-border);
  border-radius: var(--radius-container);
  box-shadow: none;
  padding: 20px 18px;
  flex: 1 1 200px;
}
:where(:root:not([data-style="classic"])) .summary-row .stat-card .stat-value { order: -1; }

/* ============================================================
   Стиль «Доска» (тема 9, 9-3): каркас и общие элементы
   ============================================================
   «Доска» - из одной семьи с «Пультом»: все правила выше (список до низа,
   листалка внизу, фильтры по содержимому, «Поиск» в ряду фильтров, без
   прокрутки вбок, номера и даты одной строкой, карточки на узком экране,
   цвет акцента у графиков и полос календаря) действуют и здесь. Ниже -
   только то, чем каркас «Доски» отличается (макеты docs/design/doska, стр.
   02, 03, 16, 18, 22). Шрифт, скругления, рамка контейнеров и цвета -
   токенами design-system.css. Раскладка экранов (доски-канбан) - 9-4. */

/* --- Боковое меню: плоский список без групп (порядок - layout.js) --- */
:where(:root[data-style="board"]) .sidebar { width: 232px; }
@media (min-width: 768px) {
  :where(:root[data-style="board"]) .main-content { margin-left: 232px; }
}
:where(:root[data-style="board"]) .sidebar-brand { padding: 22px 18px 16px; }
:where(:root[data-style="board"]) .sidebar .brand-logo { width: 30px; height: 30px; }
:where(:root[data-style="board"]) .sidebar .brand-name { font-size: 18px; font-weight: 700; }
:where(:root[data-style="board"]) .sidebar .brand-tagline { display: none; }
:where(:root[data-style="board"]) .sidebar-nav { gap: 2px; padding: var(--space-1) 12px 12px; }
:where(:root[data-style="board"]) .sidebar-link {
  gap: 10px;
  padding: 9px 10px;
  border-radius: var(--radius-menu);
  font-size: 15px;
  font-weight: 400;
}
:where(:root[data-style="board"]) .sidebar-link.active { font-weight: 600; }
/* Счётчик - круглая плашка акцента; на активном пункте (фон - акцент)
   общее правило семьи меняет цвета местами. */
:where(:root[data-style="board"]) .sidebar-count {
  min-width: 20px;
  height: 20px;
  padding: 0 6px;
  font-size: 12px;
  line-height: 20px;
}
:where(:root[data-style="board"]) .sidebar-footer { border-top: none; }
:where(:root[data-style="board"]) .sidebar-footer .avatar {
  width: 34px;
  height: 34px;
  border-radius: var(--radius-avatar);
  font-size: 13px;
  font-weight: 700;
}

/* --- Шапка: крошки слева, юрлицо, колокольчик, язык и тема справа;
   заголовок 28px/600 под ними. Поля основной области 22px 30px 40px. --- */
:where(:root[data-style="board"]) .topbar { padding: 22px 30px 8px; }
:where(:root[data-style="board"]) .page-content { padding: 8px 30px 40px; }
:where(:root[data-style="board"]) .page-title { font-size: 28px; font-weight: 600; }
@media (max-width: 767px) {
  :where(:root[data-style="board"]) .topbar { padding: var(--space-2) var(--space-3); }
  :where(:root[data-style="board"]) .page-content { padding: var(--space-2) var(--space-4) var(--space-4); }
  :where(:root[data-style="board"]) .page-title { font-size: 24px; }
}

/* --- Общие элементы --- */
:where(:root[data-style="board"]) .btn { font-size: 14px; }
:where(:root[data-style="board"]) .tab-active,
:where(:root[data-style="board"]) .tab-active:hover { font-weight: 600; }
:where(:root[data-style="board"]) .badge { font-size: 12px; padding: 3px 9px; border-radius: var(--radius-full); }
/* Переключатель «Дерево / Таблица» отделов: активная половина - тёмная
   (цвет текста), как у остальных переключателей «Доски». */
:where(:root[data-style="board"]) .page-tabs:has(#tabTree) .tab-active {
  background: var(--text-primary);
  color: var(--bg-surface);
}

/* Чипы - переключатели-фильтры («Все / Отпуска / Командировки», стр. 02):
   кнопка с рамкой, выбранная - тёмная (фон - цвет текста, текст - цвет
   карточки). Выбор отмечается aria-pressed="true" (или .is-active). */
:where(:root[data-style="board"]) .chips { display: flex; flex-wrap: wrap; gap: var(--space-2); }
:where(:root[data-style="board"]) .chip {
  display: inline-flex;
  align-items: center;
  height: 38px;
  padding: 0 14px;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-button);
  background: var(--bg-surface);
  color: var(--text-primary);
  font: inherit;
  font-size: 14px;
  font-weight: 500;
  white-space: nowrap;
  cursor: pointer;
}
:where(:root[data-style="board"]) .chip:hover { border-color: var(--border-strong); }
:where(:root[data-style="board"]) .chip:is([aria-pressed="true"], .is-active) {
  border-color: var(--text-primary);
  background: var(--text-primary);
  color: var(--bg-surface);
}
:where(:root[data-style="board"]) .chip:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 2px; }

/* «Вид: Доска / Таблица» (стр. 18) - две сросшиеся кнопки в общей рамке;
   рисует layout.js (HRViewSwitch). Подключается к экранам в 9-4. Доска
   бывает только в «Доске», поэтому в других стилях переключателя нет. */
:root:not([data-style="board"]) .view-switch { display: none !important; }
:where(:root[data-style="board"]) .view-switch {
  display: inline-flex;
  flex: 0 0 auto;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-button);
  background: var(--bg-surface);
  overflow: hidden;
}
:where(:root[data-style="board"]) .view-switch .chip {
  height: 36px;
  border: none;
  border-radius: 0;
}

/* --- Доска-канбан (9-4): колонки по статусам, в колонке - карточки ---
   Колонка - серая подложка (--board-column), шапка - точка статуса,
   название и число; карточка - белая с рамкой и открывает запись целиком
   (rowOpen). Раскладка - всегда ровная (замечание владельца к #98: на
   1280px было 3+1): от 1100px все колонки доски в один ряд, ширина поровну;
   уже - по две в ряд (четыре - 2×2); на телефоне - одна под другой.
   Число колонок доски ставит её скрипт в --board-cols. Высота колонки - по карточкам: длинную
   колонку обрезает «Ещё N» (страница), а не прокрутка. Вне «Доски» доски
   нет: её контейнер пуст, а прячет его страница. */
:where(:root[data-style="board"]) .board-columns {
  display: grid;
  grid-template-columns: repeat(var(--board-cols, 4), minmax(0, 1fr));
  gap: var(--space-4);
  align-items: start;
}
/* Пять колонок и больше (заявки, стр. 22; сотрудники с приостановленными):
   в один ряд - от 1200px (замечание владельца к #102: на 1280 было 3+2),
   колонки и карточки - плотнее; уже 1200px - по три (3+2). */
:where(:root[data-style="board"]) .board-columns[data-many] { gap: var(--space-3); }
:where(:root[data-style="board"]) .board-columns[data-many] .board-column { padding: 10px; }
:where(:root[data-style="board"]) .board-columns[data-many] .board-card { padding: 10px 12px; }
@media (max-width: 1199px) {
  :where(:root[data-style="board"]) .board-columns[data-many] { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 1099px) {
  :where(:root[data-style="board"]) .board-columns,
  :where(:root[data-style="board"]) .board-columns[data-many] { grid-template-columns: repeat(min(var(--board-cols, 4), 2), minmax(0, 1fr)); }
}
@media (max-width: 599px) {
  :where(:root[data-style="board"]) .board-columns,
  :where(:root[data-style="board"]) .board-columns[data-many] { grid-template-columns: minmax(0, 1fr); }
}
:where(:root[data-style="board"]) .board-columns > .state { grid-column: 1 / -1; }
:where(:root[data-style="board"]) .board-column {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  min-width: 0;
  padding: 12px;
  border-radius: var(--radius-container);
  background: var(--board-column);
}
:where(:root[data-style="board"]) .board-column__head {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: 4px 4px 6px;
  font-size: 15px;
  font-weight: 600;
  color: var(--text-primary);
}
:where(:root[data-style="board"]) .board-column__title { flex: 1; min-width: 0; }
:where(:root[data-style="board"]) .board-column__count { color: var(--text-secondary); font-weight: 500; }
:where(:root[data-style="board"]) .board-column__empty { margin: 0; padding: 4px 4px 8px; font-size: 14px; color: var(--text-secondary); }
:where(:root[data-style="board"]) .board-dot {
  width: 10px;
  height: 10px;
  flex: 0 0 auto;
  border-radius: var(--radius-xs);
  background: var(--board-s1);
}
:where(:root[data-style="board"]) .board-dot.is-s2 { background: var(--board-s2); }
:where(:root[data-style="board"]) .board-dot.is-s3 { background: var(--board-s3); }
:where(:root[data-style="board"]) .board-dot.is-s4 { background: var(--board-s4); }
:where(:root[data-style="board"]) .board-card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 12px 14px;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-button);
  background: var(--bg-surface);
  color: var(--text-primary);
  text-decoration: none;
}
:where(:root[data-style="board"]) .board-card:hover { border-color: var(--border-strong); }
:where(:root[data-style="board"]) .board-card__top {
  display: flex;
  justify-content: space-between;
  gap: var(--space-2);
  font-size: 12px;
  color: var(--text-secondary);
}
/* ФИО рядом с аватаркой, а не помещается слово (узкая колонка, 4-5 в ряд) -
   блок текста уходит под аватарку во всю ширину карточки: min-width у него
   по самому длинному слову, и перенос ряда срабатывает раньше, чем слово
   вылезло бы за карточку. */
:where(:root[data-style="board"]) .board-card__person { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; min-width: 0; }
:where(:root[data-style="board"]) .board-card__text { flex: 1 1 0; }
:where(:root[data-style="board"]) .board-card__title { font-size: 16px; font-weight: 600; line-height: 1.25; }
:where(:root[data-style="board"]) .board-card__line { font-size: 14px; color: var(--text-secondary); }
:where(:root[data-style="board"]) .board-card__meta {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 2px var(--space-3);
  font-size: 13px;
  color: var(--text-secondary);
}
:where(:root[data-style="board"]) .board-card__hint { font-size: 13px; color: var(--text-secondary); }
:where(:root[data-style="board"]) .board-card__hint.is-accent { color: var(--color-warning); }
:where(:root[data-style="board"]) .board-card__hint.is-ok { color: var(--color-success); }
:where(:root[data-style="board"]) .board-more {
  align-self: flex-start;
  padding: 4px;
  border: none;
  background: none;
  color: var(--text-link);
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
}
:where(:root[data-style="board"]) .board-more:hover { text-decoration: underline; }

/* --- Главная кадровика (стр. 2): доска «Заявки в работе», плитки, блоки ---
   Порядок задаётся здесь, а не порядком загрузки блоков: доска, ряд плиток,
   три блока (испытание, задачи, численность), два (заявки по статусам,
   отпуска сегодня). grid-row: auto снимает раскладку главной «Пульта» - с
   тем же весом селектора (два id), что у её правил. */
:where(:root[data-style="board"]) .board-section { display: flex; flex-direction: column; gap: var(--space-4); }
:where(:root[data-style="board"]) .board-section__head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
}
:where(:root[data-style="board"]) .board-section__title { margin: 0; font-size: 24px; font-weight: 600; }
:where(:root[data-style="board"]) .board-section .chips { align-items: center; }
:where(:root[data-style="board"]) #dashboardWidgets > #boardRequests { order: 1; }
:where(:root[data-style="board"]) #dashboardWidgets #boardTiles { order: 2; grid-column: 1 / -1; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
:where(:root[data-style="board"]) #dashboardWidgets > #probationEndingWidget { order: 3; }
:where(:root[data-style="board"]) #dashboardWidgets > #hrTasksWidget { order: 4; }
:where(:root[data-style="board"]) #dashboardWidgets #boardHeadcount { order: 5; }
:where(:root[data-style="board"]) #dashboardWidgets #boardRequestsByStatus { order: 6; }
:where(:root[data-style="board"]) #dashboardWidgets #boardLeavesToday { order: 7; }
:where(:root[data-style="board"]) #dashboardWidgets > #probationMineWidget { order: 8; }
:where(:root[data-style="board"]) #dashboardWidgets > * { grid-row: auto; }
/* Блоки сводки лежат в #analyticsWidget (display: contents) и общим правилом
   «во всю ширину» для прямых детей не задеты - на узком экране каждый занял
   бы одну двенадцатую. */
:where(:root[data-style="board"]) #dashboardWidgets :is(#boardHeadcount, #boardRequestsByStatus, #boardLeavesToday) { grid-column: 1 / -1; }
@media (min-width: 1100px) {
  :where(:root[data-style="board"]) #dashboardWidgets > #probationEndingWidget { grid-column: 1 / 5; grid-row: auto; }
  :where(:root[data-style="board"]) #dashboardWidgets > #hrTasksWidget { grid-column: 5 / 9; grid-row: auto; }
  :where(:root[data-style="board"]) #dashboardWidgets #boardHeadcount { grid-column: 9 / 13; }
  :where(:root[data-style="board"]) #dashboardWidgets #boardRequestsByStatus { grid-column: 1 / 7; }
  :where(:root[data-style="board"]) #dashboardWidgets #boardLeavesToday { grid-column: 7 / 13; }
  :where(:root[data-style="board"]) #dashboardWidgets > #probationMineWidget { grid-column: 1 / -1; grid-row: auto; }
}
:where(:root[data-style="board"]) .pult-kpi { display: block; padding: 16px 18px; text-decoration: none; }
:where(:root[data-style="board"]) .pult-kpi__value { font-size: 30px; }
:where(:root[data-style="board"]) .pult-kpi__label { margin-top: var(--space-1); font-size: 13px; }
:where(:root[data-style="board"]) .pult-kpi.is-accent-number .pult-kpi__value { color: var(--color-primary); }
:where(:root[data-style="board"]) .pult-dash-card { padding: 18px 20px; }
:where(:root[data-style="board"]) .pult-dash-card .card-title { margin-bottom: var(--space-2); font-size: 17px; font-weight: 600; }
:where(:root[data-style="board"]) .board-lines { display: flex; flex-direction: column; gap: 6px; font-size: 15px; }
:where(:root[data-style="board"]) .board-line-link { color: var(--text-primary); text-decoration: none; }
:where(:root[data-style="board"]) .board-line-link:hover { text-decoration: underline; }
:where(:root[data-style="board"]) .board-lines .is-accent,
:where(:root[data-style="board"]) .board-counts .is-accent { color: var(--color-primary); }
:where(:root[data-style="board"]) .board-counts { display: flex; flex-wrap: wrap; gap: 4px var(--space-5); margin-bottom: var(--space-2); }
:where(:root[data-style="board"]) .board-count { color: var(--text-secondary); text-decoration: none; white-space: nowrap; }
:where(:root[data-style="board"]) .board-count strong { color: var(--text-primary); }

/* --- Сверка 9-4г+д с макетами «Доски» (замечание владельца 21.10.2026) ---
   Только «Доска»: «Пульт» и «Классический» не меняются. */
/* Галочка в ряду фильтров (отчёты, стр. 54, 89) - рядом со своей подписью:
   общее min-width полей фильтра растягивало её на 160px, и подпись уезжала
   вправо. */
:where(:root[data-style="board"]) .filter-field input[type="checkbox"] { min-width: 0; }
:where(:root[data-style="board"]) .filter-field > .label:has(> input[type="checkbox"]) {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: auto;
  min-height: 40px;
}
/* «К базе знаний», «К уведомлениям» - кнопкой с рамкой, как в макетах 43-47,
   а не голым текстом под подсказкой. */
:where(:root[data-style="board"]) .page-content a.btn-ghost.kb-back-link,
:where(:root[data-style="board"]) .page-content a.btn-ghost[href="/notifications.html"] {
  align-self: flex-start;
  justify-self: start;
  border: 1px solid var(--border-default);
  background: var(--bg-surface);
  color: var(--text-primary);
}
/* Сводка администрирования (стр. 62): плитка SMTP акцентом, пока почта не
   настроена; крупно - «SMTP», под ним состояние. */
:where(:root[data-style="board"]) .summary-row .stat-card.is-alert { background: var(--color-primary); color: var(--color-on-brand); }
:where(:root[data-style="board"]) .summary-row .stat-card.is-alert .stat-label { order: -2; font-size: 30px; font-weight: 700; color: var(--color-on-brand); }
:where(:root[data-style="board"]) .summary-row .stat-card.is-alert .stat-value { font-size: 14px; font-weight: 400; color: var(--color-on-brand); }
/* Реестр ознакомлений (стр. 51): фильтры одним рядом на 1366 - поля уже. */
:where(:root[data-style="board"]) #ackFilters { gap: var(--space-3); }
:where(:root[data-style="board"]) #ackFilters .filter-field:has(> #ackFilterSearch) { flex: 0 1 200px; }
:where(:root[data-style="board"]) #ackFilters input[type="date"] { width: 140px; min-width: 0; }
:where(:root[data-style="board"]) #ackFilters select { max-width: 200px; min-width: 0; }
/* Производственный календарь, статистика поиска (стр. 36, 46): две колонки -
   от 1100px; уже страница остаётся прежней колонкой. Справочники (стр. 35) -
   во всех стилях, admin.css. */
@media (min-width: 1100px) {
/* Производственный календарь (стр. 36): календарь слева, «Сроки сдачи
   отчётов» карточкой справа. */
  :where(:root[data-style="board"]) body[data-breadcrumb="nav.admin > nav.calendar"] .page-content {
    display: grid;
    grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
    grid-auto-flow: row dense;
    column-gap: var(--space-4);
    align-content: start;
  }
  :where(:root[data-style="board"]) body[data-breadcrumb="nav.admin > nav.calendar"] .page-content > * { grid-column: 1 / -1; }
  :where(:root[data-style="board"]) body[data-breadcrumb="nav.admin > nav.calendar"] .page-content > .filters-bar,
  :where(:root[data-style="board"]) body[data-breadcrumb="nav.admin > nav.calendar"] .page-content > #calContainer,
  :where(:root[data-style="board"]) body[data-breadcrumb="nav.admin > nav.calendar"] .page-content > .cal-legend { grid-column: 1; }
  :where(:root[data-style="board"]) body[data-breadcrumb="nav.admin > nav.calendar"] .page-content > .cal-deadlines-section {
    grid-column: 2;
    grid-row: span 3;
    align-self: start;
    margin-top: 0;
    padding: 18px 20px;
    border: var(--container-border);
    border-radius: var(--radius-container);
    background: var(--bg-surface);
  }
/* Статистика поиска (стр. 46): «Топ-20 запросов» и «Ничего не найдено» -
   двумя таблицами рядом; диаграммы в макете нет. */
  :where(:root[data-style="board"]) body[data-breadcrumb="nav.kb > page.kb_search_stats"] .page-content {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-auto-flow: row dense;
    column-gap: var(--space-4);
    align-content: start;
  }
  :where(:root[data-style="board"]) body[data-breadcrumb="nav.kb > page.kb_search_stats"] .page-content > * { grid-column: 1 / -1; }
  :where(:root[data-style="board"]) body[data-breadcrumb="nav.kb > page.kb_search_stats"] .page-content > .chart-card,
  :where(:root[data-style="board"]) body[data-breadcrumb="nav.kb > page.kb_search_stats"] .page-content > #topQueriesTable { grid-column: 1; }
  :where(:root[data-style="board"]) body[data-breadcrumb="nav.kb > page.kb_search_stats"] .page-content > .kb-section-title,
  :where(:root[data-style="board"]) body[data-breadcrumb="nav.kb > page.kb_search_stats"] .page-content > #unresolvedTable { grid-column: 2; }
  :where(:root[data-style="board"]) body[data-breadcrumb="nav.kb > page.kb_search_stats"] .page-content > .chart-card {
    margin: 0;
    padding: 0;
    border: none;
    background: none;
  }
  :where(:root[data-style="board"]) body[data-breadcrumb="nav.kb > page.kb_search_stats"] .chart-card .chart-wrap { display: none; }
  :where(:root[data-style="board"]) body[data-breadcrumb="nav.kb > page.kb_search_stats"] .page-content > .chart-card,
  :where(:root[data-style="board"]) body[data-breadcrumb="nav.kb > page.kb_search_stats"] .page-content > .kb-section-title { margin: 0 0 var(--space-3); font-size: 17px; }
  :where(:root[data-style="board"]) body[data-breadcrumb="nav.kb > page.kb_search_stats"] .chart-card h3 { margin: 0; font-size: 17px; font-weight: 600; }
}

