/* ==========================================================================
   sb-primitives.css - компоненты дизайн-системы status-board.

   Требует sb-tokens.css, подключённый ВЫШЕ. Ни одного литерального цвета,
   кегля, радиуса или отступа: всё через токены. Это и есть проверка
   системы - если для компонента не нашлось токена, не хватает токена,
   а не повода написать число. Проверяет design-system/lint-tokens.js.

   Это единственное место, где описаны общие компоненты разделов: панель,
   поля, кнопки, плитки, таблицы, пилюли, статус, окно. theme.css их больше
   не дублирует - там остались оболочка и то, что относится к одной
   конкретной странице.

   Визуальный язык: поверхности отделяются светом, а не рамками. Рамка
   тонкая и тихая, у карточки есть блик по верхнему краю (--sb-highlight)
   и мягкая тень со смещением. Движение сообщает о состоянии: наведение,
   нажатие, появление слоя. Декоративной анимации нет.
   ========================================================================== */

/* ==========================================================================
   База
   ========================================================================== */

html,
body,
input,
select,
textarea,
button,
table {
    font-family: var(--sb-font);
}

/* Файл подключается ПОСЛЕ встроенного <style> страницы, то есть при равной
   специфичности побеждает он. Глобально меняем только то, что безопасно:
   гарнитуру, сглаживание, цифры, фон и цвет текста. Размеры страница
   включает явно: <body class="sb-app">. */
body {
    background: var(--sb-surface-page);
    color: var(--sb-text-primary);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
    /* Доска обновляется по Socket.IO. Без табличных цифр время и счётчики
       дёргаются при каждой перерисовке. */
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1;
    /* У Manrope узкий пробел (0.23em): короткие предлоги слипаются со
       словом - «В офисе» читалось как «Вофисе». */
    word-spacing: 0.08em;
    caret-color: var(--sb-accent);
}

body.sb-app {
    margin: 0;
    font-size: var(--sb-text-md);
    font-weight: var(--sb-weight-regular);
    line-height: var(--sb-leading-normal);
}

.sb-app h1, .sb-app h2, .sb-app h3, .sb-app h4,
.sb-page h1, .sb-page h2, .sb-page h3, .sb-page h4 {
    font-weight: var(--sb-weight-bold);
    letter-spacing: var(--sb-tracking-tight);
    line-height: var(--sb-leading-snug);
    text-wrap: balance;
}
.sb-app h1, .sb-page h1 { font-size: var(--sb-text-xl); letter-spacing: var(--sb-tracking-tighter); }
.sb-app h2, .sb-page h2 { font-size: var(--sb-text-lg); }
.sb-app h3, .sb-app h4, .sb-page h3, .sb-page h4 { font-size: var(--sb-text-md); }

code, kbd, samp, pre { font-family: var(--sb-font-mono); }

/* Поверхности браузера - тоже часть интерфейса: выделение, полосы
   прокрутки и каретка по умолчанию принадлежат ни одной теме. */
::selection { background: var(--sb-selection); color: var(--sb-text-primary); }

html { scrollbar-color: var(--sb-scrollbar) transparent; }
* { scrollbar-width: thin; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
    background: var(--sb-scrollbar);
    border: 2px solid transparent;
    border-radius: var(--sb-radius-full);
    background-clip: padding-box;
}
::-webkit-scrollbar-thumb:hover { background-color: var(--sb-scrollbar-hover); }
::-webkit-scrollbar-corner { background: transparent; }

/* Фокус виден всегда и везде одинаково. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible {
    outline: var(--sb-focus-outline);
    outline-offset: 2px;
    border-radius: var(--sb-radius-xs);
}

/* Мягкая смена страниц. Боковая панель и шапка объявлены отдельными
   слоями (см. theme.css) и не мигают при переходе - меняется только
   рабочая область. Браузер без поддержки просто перейдёт как раньше. */
@view-transition { navigation: auto; }

::view-transition-old(root) {
    animation: sb-vt-out var(--sb-duration-fast) var(--sb-ease-in) both;
}
::view-transition-new(root) {
    animation: sb-vt-in var(--sb-duration-base) var(--sb-ease-out) both;
}

@keyframes sb-vt-out { to { opacity: 0; } }
@keyframes sb-vt-in { from { opacity: 0; transform: translateY(6px); } }

@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
    /* Спиннер - единственное исключение: он сообщает, что работа идёт,
       и остановленный кружок читается как зависание. */
    .sb-spinner {
        animation-duration: 3s !important;
        animation-iteration-count: infinite !important;
    }
    ::view-transition-old(root),
    ::view-transition-new(root) { animation: none !important; }
}

/* Утилита: заглавная микроподпись. Только для подписей колонок сетки -
   над заголовками разделов её не ставим. */
.sb-caps {
    font-size: var(--sb-text-micro);
    font-weight: var(--sb-weight-bold);
    letter-spacing: var(--sb-tracking-caps);
    text-transform: uppercase;
    color: var(--sb-text-muted);
}

.sb-spacer { flex: 1 1 auto; }
.sb-hidden-control { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }

/* ==========================================================================
   Каркас раздела
   ========================================================================== */

.sb-page {
    display: flex;
    flex-direction: column;
    gap: var(--sb-space-4);
    max-width: 100%;
    min-width: 0;
}

.sb-lead {
    margin: 0;
    font-size: var(--sb-text-md);
    line-height: var(--sb-leading-normal);
    color: var(--sb-text-secondary);
    max-width: 72ch;
    text-wrap: pretty;
}

/* Появление содержимого раздела: одно короткое движение при первой
   отрисовке, чтобы данные не «выпрыгивали». Без каскадов и задержек. */
.sb-page > * {
    animation: sb-rise var(--sb-duration-slow) var(--sb-ease-out) both;
}

@keyframes sb-rise {
    from { opacity: 0; transform: translateY(8px); }
}

/* ==========================================================================
   Панель
   ========================================================================== */

.sb-panel {
    position: relative;
    background: var(--sb-surface-card);
    border: 1px solid var(--sb-border-soft);
    border-radius: var(--sb-radius-md);
    box-shadow: var(--sb-highlight), var(--sb-elev-1);
    padding: var(--sb-space-4) var(--sb-space-5) var(--sb-space-5);
    min-width: 0;
}

.sb-panel-head {
    display: flex;
    align-items: baseline;
    gap: var(--sb-space-2) var(--sb-space-3);
    flex-wrap: wrap;
    margin-bottom: var(--sb-space-4);
}

.sb-panel-head h2,
.sb-panel > h2 {
    margin: 0;
    font-size: var(--sb-text-lg);
    font-weight: var(--sb-weight-bold);
    letter-spacing: var(--sb-tracking-tight);
    text-transform: none;
    color: var(--sb-text-primary);
}

.sb-panel-note {
    font-size: var(--sb-text-sm);
    line-height: var(--sb-leading-normal);
    color: var(--sb-text-muted);
}

.sb-panel-head .sb-spacer { flex: 1 1 auto; }

/* ==========================================================================
   Панель фильтров и поля
   ========================================================================== */

.sb-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: var(--sb-space-3) var(--sb-space-4);
    padding: var(--sb-space-3) var(--sb-space-4) var(--sb-space-4);
    background: var(--sb-surface-card);
    border: 1px solid var(--sb-border-soft);
    border-radius: var(--sb-radius-md);
    box-shadow: var(--sb-highlight), var(--sb-elev-1);
}

.sb-field {
    display: flex;
    flex-direction: column;
    gap: var(--sb-space-1);
    min-width: 0;
    flex: 1 1 160px;
}

.sb-field.is-wide { flex: 2 1 240px; max-width: 460px; }
.sb-field.is-tight { flex: 0 0 auto; max-width: none; }

.sb-toolbar > .sb-field { max-width: 300px; }

.sb-field > label,
.sb-field > .sb-field-label {
    font-size: var(--sb-text-sm);
    font-weight: var(--sb-weight-medium);
    letter-spacing: 0;
    text-transform: none;
    color: var(--sb-text-secondary);
}

/* Поля оформляются внутри .sb-page и .sb-modal-body: раздел подписывается
   на общие примитивы явно. Типы не перечисляем - у части полей атрибута
   type нет вовсе. */
.sb-page input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not([type="range"]):not([type="color"]),
.sb-page select,
.sb-page textarea,
.sb-modal-body input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not([type="range"]):not([type="color"]),
.sb-modal-body select,
.sb-modal-body textarea {
    width: 100%;
    min-height: var(--sb-control-md);
    padding: 0 var(--sb-space-3);
    box-sizing: border-box;
    border: 1px solid var(--sb-border);
    border-radius: var(--sb-radius-sm);
    background-color: var(--sb-surface-input);
    color: var(--sb-text-primary);
    font-family: inherit;
    font-size: var(--sb-text-md);
    font-weight: var(--sb-weight-regular);
    font-variant-numeric: tabular-nums;
    transition: border-color var(--sb-duration-fast) var(--sb-ease),
                box-shadow var(--sb-duration-fast) var(--sb-ease),
                background-color var(--sb-duration-fast) var(--sb-ease);
}

/* Стрелка select рисуется двумя градиентами цвета роли: картинка-данные
   не умеет currentColor, а системная стрелка разная в каждом браузере. */
.sb-page select,
.sb-modal-body select {
    appearance: none;
    -webkit-appearance: none;
    padding-right: var(--sb-space-6);
    background-image:
        linear-gradient(45deg, transparent 50%, var(--sb-text-muted) 50%),
        linear-gradient(135deg, var(--sb-text-muted) 50%, transparent 50%);
    background-position: calc(100% - 17px) 52%, calc(100% - 12px) 52%;
    background-size: 5px 5px, 5px 5px;
    background-repeat: no-repeat;
    cursor: pointer;
}

.sb-page select[multiple],
.sb-modal-body select[multiple] { background-image: none; padding: var(--sb-space-1); }

.sb-page input:not([type="checkbox"]):not([type="radio"]):hover,
.sb-page select:hover,
.sb-page textarea:hover,
.sb-modal-body input:not([type="checkbox"]):not([type="radio"]):hover,
.sb-modal-body select:hover,
.sb-modal-body textarea:hover { border-color: var(--sb-border-strong); }

.sb-page textarea,
.sb-modal-body textarea {
    min-height: 72px;
    padding: var(--sb-space-2) var(--sb-space-3);
    resize: vertical;
    line-height: var(--sb-leading-normal);
}

.sb-page input:focus-visible,
.sb-page select:focus-visible,
.sb-page textarea:focus-visible,
.sb-modal-body input:focus-visible,
.sb-modal-body select:focus-visible,
.sb-modal-body textarea:focus-visible {
    outline: none;
    border-color: var(--sb-accent);
    box-shadow: var(--sb-focus-ring);
}

.sb-page input.is-invalid,
.sb-page select.is-invalid,
.sb-page textarea.is-invalid,
.sb-modal-body input.is-invalid,
.sb-modal-body select.is-invalid,
.sb-modal-body textarea.is-invalid {
    border-color: var(--sb-bad-line);
    background-color: var(--sb-bad-bg);
}

.sb-field-error {
    font-size: var(--sb-text-xs);
    color: var(--sb-bad-ink);
}

.sb-page input::placeholder,
.sb-page textarea::placeholder,
.sb-modal-body input::placeholder,
.sb-modal-body textarea::placeholder { color: var(--sb-text-muted); opacity: 1; }

.sb-page input:disabled,
.sb-page select:disabled,
.sb-page textarea:disabled,
.sb-modal-body input:disabled,
.sb-modal-body select:disabled,
.sb-modal-body textarea:disabled { opacity: 0.55; cursor: not-allowed; }

/* Флажки и переключатели в цвет акцента - системный синий у каждого свой. */
input[type="checkbox"],
input[type="radio"],
input[type="range"] { accent-color: var(--sb-accent); }

.sb-page input[type="checkbox"],
.sb-modal-body input[type="checkbox"] {
    width: 16px;
    height: 16px;
    cursor: pointer;
}

/* Иконка календаря и часов у полей даты: в тёмной теме системная чёрная. */
[data-theme="dark"] input[type="date"]::-webkit-calendar-picker-indicator,
[data-theme="dark"] input[type="time"]::-webkit-calendar-picker-indicator,
[data-theme="dark"] input[type="month"]::-webkit-calendar-picker-indicator,
:root:not([data-theme]) input[type="date"]::-webkit-calendar-picker-indicator,
:root:not([data-theme]) input[type="time"]::-webkit-calendar-picker-indicator {
    filter: invert(0.8);
    opacity: 0.7;
    cursor: pointer;
}

/* ==========================================================================
   Кнопки
   ========================================================================== */

.sb-btn {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--sb-space-2);
    min-height: var(--sb-control-md);
    padding: 0 var(--sb-space-4);
    box-sizing: border-box;
    border: 1px solid var(--sb-border);
    border-radius: var(--sb-radius-sm);
    background: var(--sb-surface-raised);
    box-shadow: var(--sb-highlight), var(--sb-elev-1);
    color: var(--sb-text-primary);
    font-family: inherit;
    font-size: var(--sb-text-md);
    font-weight: var(--sb-weight-medium);
    line-height: 1;
    white-space: nowrap;
    cursor: pointer;
    text-decoration: none;
    user-select: none;
    transition: border-color var(--sb-duration-fast) var(--sb-ease),
                background-color var(--sb-duration-fast) var(--sb-ease),
                box-shadow var(--sb-duration-fast) var(--sb-ease),
                transform var(--sb-duration-instant) var(--sb-ease),
                color var(--sb-duration-fast) var(--sb-ease);
}

.sb-btn:hover { background: var(--sb-surface-hover); border-color: var(--sb-border-strong); }
.sb-btn:active { transform: scale(0.97); }
.sb-btn svg { flex: 0 0 auto; }

.sb-btn.is-primary {
    background: var(--sb-accent);
    border-color: transparent;
    color: var(--sb-accent-ink);
    font-weight: var(--sb-weight-bold);
    box-shadow: var(--sb-highlight), 0 6px 18px -8px var(--sb-accent-glow);
}
.sb-btn.is-primary:hover {
    background: var(--sb-accent-hover);
    box-shadow: var(--sb-highlight), 0 10px 24px -8px var(--sb-accent-glow);
}

.sb-btn.is-quiet {
    background: transparent;
    border-color: transparent;
    box-shadow: none;
    color: var(--sb-text-secondary);
}
.sb-btn.is-quiet:hover { background: var(--sb-surface-hover); color: var(--sb-text-primary); }

/* Разрушающее действие красное в наведении и фокусе, а не в покое: ряд
   красных кнопок "Удалить" перетягивает на себя весь раздел. */
.sb-btn.is-danger { color: var(--sb-bad-ink); }
.sb-btn.is-danger:hover,
.sb-btn.is-danger:focus-visible {
    background: var(--sb-bad-bg);
    border-color: var(--sb-bad-line);
}

.sb-btn.is-small { min-height: var(--sb-control-sm); padding: 0 var(--sb-space-3); font-size: var(--sb-text-sm); }
.sb-btn.is-large { min-height: var(--sb-control-lg); padding: 0 var(--sb-space-5); font-size: var(--sb-text-lg); }

.sb-btn:disabled,
.sb-btn[aria-disabled="true"] { opacity: 0.45; cursor: not-allowed; transform: none; box-shadow: none; }

/* Загрузка. Кнопка держит ширину и не даёт нажать себя второй раз. */
.sb-btn.is-loading { color: transparent; pointer-events: none; }
.sb-btn.is-loading::after {
    content: "";
    position: absolute;
    width: 14px;
    height: 14px;
    border: 2px solid currentColor;
    border-top-color: transparent;
    border-radius: 50%;
    color: var(--sb-text-secondary);
    animation: sb-spin 0.8s linear infinite;
}
.sb-btn.is-primary.is-loading::after { color: var(--sb-accent-ink); }

.sb-btn-row {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sb-space-2);
    align-items: center;
}

.sb-icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--sb-control-md);
    height: var(--sb-control-md);
    box-sizing: border-box;
    padding: 0;
    border: 1px solid var(--sb-border);
    border-radius: var(--sb-radius-sm);
    background: var(--sb-surface-raised);
    color: var(--sb-text-secondary);
    cursor: pointer;
    transition: color var(--sb-duration-fast) var(--sb-ease),
                background-color var(--sb-duration-fast) var(--sb-ease),
                transform var(--sb-duration-instant) var(--sb-ease);
}
.sb-icon-btn:hover { color: var(--sb-text-primary); background: var(--sb-surface-hover); }
.sb-icon-btn:active { transform: scale(0.94); }

/* ==========================================================================
   Сегментный переключатель: вкладки раздела, режим отчёта, период.
   ========================================================================== */

.sb-seg {
    display: inline-flex;
    gap: var(--sb-space-0);
    padding: var(--sb-space-0);
    border: 1px solid var(--sb-border-soft);
    border-radius: var(--sb-radius-sm);
    background: var(--sb-surface-rail);
}

.sb-seg > button,
.sb-seg > a {
    min-height: var(--sb-control-sm);
    padding: 0 var(--sb-space-3);
    border: 0;
    border-radius: var(--sb-radius-sm);
    background: transparent;
    color: var(--sb-text-secondary);
    font-family: inherit;
    font-size: var(--sb-text-sm);
    font-weight: var(--sb-weight-medium);
    text-decoration: none;
    cursor: pointer;
    transition: background-color var(--sb-duration-fast) var(--sb-ease), color var(--sb-duration-fast) var(--sb-ease);
}
.sb-seg > button:hover,
.sb-seg > a:hover { color: var(--sb-text-primary); }
.sb-seg > .is-active,
.sb-seg > [aria-selected="true"] {
    background: var(--sb-surface-card);
    color: var(--sb-text-primary);
    box-shadow: var(--sb-highlight), var(--sb-elev-1);
}

/* ==========================================================================
   Плитки показателей
   ========================================================================== */

.sb-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(168px, 100%), 1fr));
    gap: var(--sb-space-3);
}

.sb-stat {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: var(--sb-space-1);
    padding: var(--sb-space-4);
    background: var(--sb-surface-card);
    border: 1px solid var(--sb-border-soft);
    border-radius: var(--sb-radius-md);
    box-shadow: var(--sb-highlight), var(--sb-elev-1);
    min-width: 0;
    overflow: hidden;
    transition: border-color var(--sb-duration-base) var(--sb-ease), transform var(--sb-duration-base) var(--sb-ease-out);
}

.sb-stat b {
    order: 1;
    font-size: var(--sb-text-2xl);
    font-weight: var(--sb-weight-heavy);
    line-height: var(--sb-leading-tight);
    letter-spacing: var(--sb-tracking-tighter);
    color: var(--sb-text-primary);
    font-variant-numeric: tabular-nums;
}

.sb-stat span {
    order: 2;
    font-size: var(--sb-text-sm);
    font-weight: var(--sb-weight-medium);
    letter-spacing: 0;
    text-transform: none;
    line-height: var(--sb-leading-snug);
    color: var(--sb-text-secondary);
}

.sb-stat i {
    order: 3;
    font-style: normal;
    font-size: var(--sb-text-xs);
    color: var(--sb-text-muted);
    line-height: var(--sb-leading-normal);
}

/* Плитка кричит только когда есть о чём: ноль опозданий красным цветом
   ничего не сообщает, а внимание забирает. Когда есть - окрашивается
   число и появляется тонкая сигнальная полоса по верхнему краю. */
.sb-stat.is-ok[data-nonzero="true"] b { color: var(--sb-ok-ink); }
.sb-stat.is-warn[data-nonzero="true"] b { color: var(--sb-warn-ink); }
.sb-stat.is-bad[data-nonzero="true"] b { color: var(--sb-bad-ink); }

.sb-stat[data-nonzero="true"]::before {
    content: "";
    position: absolute;
    inset: 0 0 auto 0;
    height: 2px;
    background: transparent;
}
.sb-stat.is-ok[data-nonzero="true"]::before { background: var(--sb-ok-line); }
.sb-stat.is-warn[data-nonzero="true"]::before { background: var(--sb-warn-line); }
.sb-stat.is-bad[data-nonzero="true"]::before { background: var(--sb-bad-line); }

/* ==========================================================================
   Таблицы
   ========================================================================== */

.sb-table-wrap {
    overflow: auto;
    max-height: 64vh;
    border: 1px solid var(--sb-border-soft);
    border-radius: var(--sb-radius-md);
    background: var(--sb-surface-card);
    box-shadow: var(--sb-highlight), var(--sb-elev-1);
}

.sb-table {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    font-size: var(--sb-text-md);
}

.sb-table th,
.sb-table td {
    padding: var(--sb-space-2) var(--sb-space-3);
    text-align: left;
    border-bottom: 1px solid var(--sb-border-soft);
    vertical-align: middle;
    white-space: nowrap;
}

.sb-table td { padding-top: var(--sb-space-3); padding-bottom: var(--sb-space-3); }

.sb-table th {
    position: sticky;
    top: 0;
    z-index: var(--sb-z-sticky);
    background: var(--sb-surface-rail);
    font-size: var(--sb-text-sm);
    font-weight: var(--sb-weight-medium);
    letter-spacing: 0;
    text-transform: none;
    color: var(--sb-text-muted);
    border-bottom: 1px solid var(--sb-border);
}

.sb-table td { color: var(--sb-text-secondary); font-variant-numeric: tabular-nums; transition: background-color var(--sb-duration-fast) var(--sb-ease); }
.sb-table td.is-name,
.sb-table td strong { color: var(--sb-text-primary); font-weight: var(--sb-weight-medium); }
.sb-table td.is-num,
.sb-table th.is-num { text-align: right; }
.sb-table td.is-wrap { white-space: normal; min-width: 200px; }
.sb-table tbody tr:last-child td { border-bottom: 0; }
.sb-table tbody tr:hover td { background: var(--sb-surface-hover); }

/* ==========================================================================
   Пилюли состояния
   ========================================================================== */

.sb-pill {
    display: inline-flex;
    align-items: center;
    gap: var(--sb-space-1);
    padding: var(--sb-space-0) var(--sb-space-2);
    border-radius: var(--sb-radius-full);
    border: 1px solid var(--sb-border);
    background: var(--sb-surface-raised);
    color: var(--sb-text-secondary);
    font-size: var(--sb-text-xs);
    font-weight: var(--sb-weight-medium);
    line-height: var(--sb-leading-normal);
    white-space: nowrap;
}

.sb-pill.ok { background: var(--sb-ok-bg); border-color: var(--sb-ok-line); color: var(--sb-ok-ink); }
.sb-pill.warn { background: var(--sb-warn-bg); border-color: var(--sb-warn-line); color: var(--sb-warn-ink); }
.sb-pill.bad { background: var(--sb-bad-bg); border-color: var(--sb-bad-line); color: var(--sb-bad-ink); }
.sb-pill.info { background: var(--sb-accent-soft); border-color: var(--sb-accent-line); color: var(--sb-accent); }

/* ==========================================================================
   Иконка. SVG из общего набора (window.sbIcon в app-shell.js) рисуется
   штрихом currentColor и берёт цвет у родителя.
   ========================================================================== */

.sb-ico {
    display: inline-block;
    flex: 0 0 auto;
    width: 1.15em;
    height: 1.15em;
    vertical-align: -0.2em;
    stroke: currentColor;
    fill: none;
    stroke-width: 1.8;
    stroke-linecap: round;
    stroke-linejoin: round;
}

/* ==========================================================================
   Статус присутствия.

   Один класс с пятью модификаторами. Иконку (или подпись) убирать нельзя:
   при дальтонизме пары статусов держатся именно на ней (A11Y-2).
   ========================================================================== */

.sb-status {
    display: inline-flex;
    align-items: center;
    gap: var(--sb-space-1);
    padding: var(--sb-space-0) var(--sb-space-2);
    border: 1px solid var(--sb-border);
    border-radius: var(--sb-radius-sm);
    background: var(--sb-surface-raised);
    color: var(--sb-text-secondary);
    font-size: var(--sb-text-xs);
    font-weight: var(--sb-weight-medium);
    white-space: nowrap;
}

.sb-status[data-icon]::before { content: attr(data-icon); font-size: var(--sb-text-sm); line-height: 1; }

.sb-status.office { background: var(--sb-status-office-bg); border-color: var(--sb-status-office-line); color: var(--sb-status-office-ink); }
.sb-status.home { background: var(--sb-status-home-bg); border-color: var(--sb-status-home-line); color: var(--sb-status-home-ink); }
.sb-status.field { background: var(--sb-status-field-bg); border-color: var(--sb-status-field-line); color: var(--sb-status-field-ink); }
.sb-status.vacation { background: var(--sb-status-vacation-bg); border-color: var(--sb-status-vacation-line); color: var(--sb-status-vacation-ink); }
.sb-status.sick { background: var(--sb-status-sick-bg); border-color: var(--sb-status-sick-line); color: var(--sb-status-sick-ink); }

.sb-status.is-choice {
    padding: var(--sb-space-2) var(--sb-space-3);
    border-radius: var(--sb-radius-md);
    font-size: var(--sb-text-md);
    cursor: pointer;
}

/* ==========================================================================
   Карточка сотрудника (витрина и будущие страницы; доска пока строит
   свою разметку - см. theme.css, раздел «Доска»).
   ========================================================================== */

.sb-employee {
    display: flex;
    flex-direction: column;
    gap: var(--sb-space-2);
    padding: var(--sb-space-3);
    background: var(--sb-surface-card);
    border: 1px solid var(--sb-border-soft);
    border-radius: var(--sb-radius-md);
    box-shadow: var(--sb-highlight), var(--sb-elev-1);
    min-width: 0;
}

.sb-employee-head {
    display: flex;
    align-items: flex-start;
    gap: var(--sb-space-2);
    width: 100%;
    min-width: 0;
}

.sb-employee-avatar {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    flex: 0 0 auto;
    border-radius: var(--sb-radius-sm);
    border: 1px solid var(--sb-border);
    background: var(--sb-surface-raised);
    color: var(--sb-text-secondary);
    font-size: var(--sb-text-xs);
    font-weight: var(--sb-weight-bold);
}

.sb-employee[data-status="office"] .sb-employee-avatar { background: var(--sb-status-office-bg); color: var(--sb-status-office-ink); border-color: var(--sb-status-office-line); }
.sb-employee[data-status="home"] .sb-employee-avatar { background: var(--sb-status-home-bg); color: var(--sb-status-home-ink); border-color: var(--sb-status-home-line); }
.sb-employee[data-status="field"] .sb-employee-avatar { background: var(--sb-status-field-bg); color: var(--sb-status-field-ink); border-color: var(--sb-status-field-line); }
.sb-employee[data-status="vacation"] .sb-employee-avatar { background: var(--sb-status-vacation-bg); color: var(--sb-status-vacation-ink); border-color: var(--sb-status-vacation-line); }
.sb-employee[data-status="sick"] .sb-employee-avatar { background: var(--sb-status-sick-bg); color: var(--sb-status-sick-ink); border-color: var(--sb-status-sick-line); }

.sb-employee > .sb-status {
    align-self: stretch;
    justify-content: center;
}

.sb-employee-info {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 1px;
}

.sb-employee-info b {
    font-size: var(--sb-text-md);
    font-weight: var(--sb-weight-bold);
    color: var(--sb-text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.sb-employee-info i {
    font-style: normal;
    font-size: var(--sb-text-xs);
    color: var(--sb-text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.sb-employee-load {
    flex: 0 0 auto;
    display: flex;
    gap: var(--sb-space-1);
    padding-top: var(--sb-space-1);
}

.sb-load-dot {
    width: 10px;
    height: 10px;
    padding: 0;
    border: 1px solid var(--sb-border-strong);
    border-radius: 50%;
    background: transparent;
    cursor: pointer;
}

.sb-load-dot.green.is-active { background: var(--sb-ok-ink); border-color: var(--sb-ok-ink); }
.sb-load-dot.yellow.is-active { background: var(--sb-warn-ink); border-color: var(--sb-warn-ink); }
.sb-load-dot.red.is-active { background: var(--sb-bad-ink); border-color: var(--sb-bad-ink); }

.sb-employee-note { display: none; flex-direction: column; gap: var(--sb-space-1); }

.sb-employee:hover .sb-employee-note,
.sb-employee:focus-within .sb-employee-note,
.sb-employee .sb-employee-note:has(textarea.has-value) { display: flex; }

@media (hover: none) {
    .sb-employee-note { display: flex; }
}

.sb-employee-note textarea {
    width: 100%;
    min-height: var(--sb-control-sm);
    padding: var(--sb-space-1) var(--sb-space-2);
    box-sizing: border-box;
    border: 1px solid var(--sb-border);
    border-radius: var(--sb-radius-sm);
    background: var(--sb-surface-input);
    color: var(--sb-text-primary);
    font-family: inherit;
    font-size: var(--sb-text-xs);
    resize: none;
}

.sb-employee-note textarea:focus-visible {
    outline: none;
    border-color: var(--sb-accent);
    box-shadow: var(--sb-focus-ring);
}

/* ==========================================================================
   Пустые состояния, загрузка, уведомления
   ========================================================================== */

.sb-empty {
    padding: var(--sb-space-7) var(--sb-space-4);
    text-align: center;
    font-size: var(--sb-text-md);
    line-height: var(--sb-leading-normal);
    color: var(--sb-text-muted);
    text-wrap: balance;
}

.sb-empty b {
    display: block;
    margin-bottom: var(--sb-space-1);
    font-size: var(--sb-text-lg);
    font-weight: var(--sb-weight-bold);
    color: var(--sb-text-primary);
}

.sb-spinner {
    width: 22px;
    height: 22px;
    margin: 0 auto var(--sb-space-3);
    border: 2px solid var(--sb-border);
    border-top-color: var(--sb-accent);
    border-radius: 50%;
    animation: sb-spin 0.8s linear infinite;
}

@keyframes sb-spin { to { transform: rotate(360deg); } }

/* Скелет строки - для таблиц и списков, которые уже знают свою высоту. */
.sb-skeleton {
    height: var(--sb-space-3);
    border-radius: var(--sb-radius-xs);
    background: linear-gradient(90deg, var(--sb-border-soft) 0%, var(--sb-border) 40%, var(--sb-border-soft) 80%);
    background-size: 220% 100%;
    animation: sb-shimmer 1.3s var(--sb-ease) infinite;
}

@keyframes sb-shimmer { from { background-position: 120% 0; } to { background-position: -120% 0; } }

.sb-note {
    padding: var(--sb-space-2) var(--sb-space-3);
    border-radius: var(--sb-radius-sm);
    border: 1px solid var(--sb-border);
    background: var(--sb-surface-raised);
    color: var(--sb-text-secondary);
    font-size: var(--sb-text-md);
    line-height: var(--sb-leading-normal);
    animation: sb-rise var(--sb-duration-base) var(--sb-ease-out) both;
}

.sb-note.ok { background: var(--sb-ok-bg); border-color: var(--sb-ok-line); color: var(--sb-ok-ink); }
.sb-note.warn { background: var(--sb-warn-bg); border-color: var(--sb-warn-line); color: var(--sb-warn-ink); }
.sb-note.bad { background: var(--sb-bad-bg); border-color: var(--sb-bad-line); color: var(--sb-bad-ink); }

/* ==========================================================================
   Степпер периода
   ========================================================================== */

.sb-stepper {
    display: inline-flex;
    align-items: stretch;
    border: 1px solid var(--sb-border);
    border-radius: var(--sb-radius-sm);
    overflow: hidden;
    background: var(--sb-surface-raised);
    box-shadow: var(--sb-highlight), var(--sb-elev-1);
    min-height: var(--sb-control-md);
}

.sb-stepper button {
    min-width: var(--sb-control-md);
    padding: 0 var(--sb-space-2);
    border: 0;
    background: transparent;
    color: var(--sb-text-secondary);
    font-family: inherit;
    font-size: var(--sb-text-lg);
    line-height: 1;
    cursor: pointer;
    transition: background-color var(--sb-duration-fast) var(--sb-ease), color var(--sb-duration-fast) var(--sb-ease);
}

.sb-stepper button:hover { background: var(--sb-surface-hover); color: var(--sb-text-primary); }
.sb-stepper button:active { background: var(--sb-accent-soft); }

.sb-stepper .sb-stepper-label {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 136px;
    padding: 0 var(--sb-space-3);
    border-left: 1px solid var(--sb-border-soft);
    border-right: 1px solid var(--sb-border-soft);
    font-size: var(--sb-text-md);
    font-weight: var(--sb-weight-bold);
    color: var(--sb-text-primary);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* ==========================================================================
   Легенда и счётчик
   ========================================================================== */

.sb-legend {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sb-space-2) var(--sb-space-4);
    align-items: center;
    font-size: var(--sb-text-sm);
    color: var(--sb-text-muted);
}

.sb-legend span {
    display: inline-flex;
    align-items: center;
    gap: var(--sb-space-2);
    white-space: nowrap;
}

.sb-legend i {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex: 0 0 auto;
}

.sb-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 20px;
    height: 20px;
    padding: 0 var(--sb-space-1);
    box-sizing: border-box;
    border-radius: var(--sb-radius-full);
    background: var(--sb-surface-raised);
    color: var(--sb-text-secondary);
    font-size: var(--sb-text-micro);
    font-weight: var(--sb-weight-bold);
    font-variant-numeric: tabular-nums;
}

/* ==========================================================================
   Модальное окно
   ========================================================================== */

.sb-modal {
    position: fixed;
    inset: 0;
    z-index: var(--sb-z-modal);
    display: none;
    align-items: center;
    justify-content: center;
    padding: var(--sb-space-4);
    background: var(--sb-scrim);
    backdrop-filter: blur(6px) saturate(120%);
    -webkit-backdrop-filter: blur(6px) saturate(120%);
}

.sb-modal.is-open {
    display: flex;
    animation: sb-fade var(--sb-duration-base) var(--sb-ease-out) both;
}

.sb-modal.is-open .sb-modal-box {
    animation: sb-pop var(--sb-duration-slow) var(--sb-ease-out) both;
}

@keyframes sb-fade { from { opacity: 0; } }
@keyframes sb-pop { from { opacity: 0; transform: translateY(10px) scale(0.97); } }
@keyframes sb-sheet { from { transform: translateY(100%); } }

.sb-modal-box {
    width: min(720px, 100%);
    max-height: 86vh;
    display: flex;
    flex-direction: column;
    background: var(--sb-surface-card);
    border: 1px solid var(--sb-border);
    border-radius: var(--sb-radius-lg);
    box-shadow: var(--sb-highlight), var(--sb-elev-3);
    overflow: hidden;
}

.sb-modal-head {
    display: flex;
    align-items: center;
    gap: var(--sb-space-2);
    padding: var(--sb-space-4) var(--sb-space-5);
    border-bottom: 1px solid var(--sb-border-soft);
}

.sb-modal-head h2 {
    margin: 0;
    flex: 1 1 auto;
    font-size: var(--sb-text-lg);
    font-weight: var(--sb-weight-bold);
    letter-spacing: var(--sb-tracking-tight);
    text-transform: none;
    color: var(--sb-text-primary);
}

.sb-modal-body { padding: var(--sb-space-5); overflow: auto; }

.sb-modal-body.sb-form {
    display: flex;
    flex-direction: column;
    gap: var(--sb-space-4);
}

.sb-modal-body.sb-form > .sb-field { flex: 0 0 auto; }

.sb-form-row {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sb-space-3);
}

.sb-modal-foot {
    display: flex;
    justify-content: flex-end;
    gap: var(--sb-space-2);
    padding: var(--sb-space-3) var(--sb-space-5);
    border-top: 1px solid var(--sb-border-soft);
    background: var(--sb-surface-rail);
}

/* ==========================================================================
   Действия раздела в верхней строке
   ========================================================================== */

.sb-topbar [data-sb-topbar] {
    display: flex;
    align-items: center;
    gap: var(--sb-space-2);
    flex-wrap: wrap;
    min-width: 0;
}

/* ==========================================================================
   Узкие экраны. Мобильные правила стоят В КОНЦЕ файла, чтобы их не
   перебивали более поздние базовые правила.
   ========================================================================== */

@media (max-width: 720px) {
    .sb-page { gap: var(--sb-space-3); }
    .sb-panel { padding: var(--sb-space-4); }
    .sb-stats { grid-template-columns: repeat(auto-fit, minmax(min(140px, 100%), 1fr)); gap: var(--sb-space-2); }
    .sb-stat { padding: var(--sb-space-3); }
    .sb-table-wrap { max-height: none; }
    .sb-field { flex: 1 1 100%; }
    .sb-toolbar > .sb-field { max-width: none; }
    .sb-modal { padding: 0; align-items: flex-end; }
    .sb-modal-box { width: 100%; max-height: 92vh; border-radius: var(--sb-radius-lg) var(--sb-radius-lg) 0 0; }
    .sb-modal.is-open .sb-modal-box { animation: sb-sheet var(--sb-duration-slow) var(--sb-ease-out) both; }

    /* Палец - не курсор: цель нажатия не меньше 40px. Поля ввода - 44px и
       16px кегль, иначе iOS увеличивает страницу при фокусе. */
    .sb-btn,
    .sb-icon-btn { min-height: var(--sb-control-lg); }
    .sb-icon-btn { width: var(--sb-control-lg); }
    .sb-btn.is-small { min-height: var(--sb-control-md); }
    .sb-seg > button,
    .sb-seg > a { min-height: var(--sb-control-md); }
    .sb-page input:not([type="checkbox"]):not([type="radio"]):not([type="file"]),
    .sb-page select,
    .sb-modal-body input:not([type="checkbox"]):not([type="radio"]):not([type="file"]),
    .sb-modal-body select { min-height: var(--sb-control-lg); font-size: var(--sb-text-touch); }
    .sb-page textarea,
    .sb-modal-body textarea { font-size: var(--sb-text-touch); }
}

/* Смена темы идёт своим переходом - раскрытием круга от кнопки (app-shell.js).
   Стандартное затухание страницы здесь только мешало бы. */
.sb-vt-theme::view-transition-old(root),
.sb-vt-theme::view-transition-new(root) {
    animation: none;
    mix-blend-mode: normal;
}
