/* ============================================================================
   Shmailer — компоненты и мост к легаси-разметке (слой 3 из 3)
   ----------------------------------------------------------------------------
   Порядок подключения: tokens.css → ui.css → style.css

   Здесь два рода правил:
   1. НОВЫЕ компоненты данных: метрики, таблицы, бейджи, диалог подтверждения,
      тосты, полосы прогресса, скелетоны, сегментные переключатели.
   2. МОСТ: старые имена классов из шаблонов (.stat, .rep-metric, .pf-item,
      .btn-green, .seg, .tab …) приведены к тем же визуалам, что и новые.
      Это позволяет обновлять шаблоны постранично, не ломая остальные.
      Каждый такой блок помечен «легаси».
============================================================================ */

/* ============================================================================
   КНОПКИ — легаси-алиасы
   ----------------------------------------------------------------------------
   .btn-green      → главное действие (было синим, несмотря на имя)
   .btn-secondary  → нейтральное
   .btn-red        → необратимое
   Имена оставлены живыми, потому что используются в 14 шаблонах; новые
   экраны пишутся уже на .btn-primary / .btn-default / .btn-danger.
============================================================================ */

/* Повторная фиксация фона .btn: строка нужна как страж (tests/test_web.py::
   test_bare_btn_has_background) — раньше `.btn` без варианта не имел фона и
   давал белый текст на белой карточке. Значения те же, что в ui.css. */
.btn { background: var(--btn-bg); border-color: var(--btn-border); }

.btn-green {
    --btn-bg: var(--brand);
    --btn-fg: var(--brand-fg);
    --btn-border: var(--brand);
    --btn-bg-hover: var(--brand-hover);
    --btn-bg-active: var(--brand-pressed);
    box-shadow: var(--shadow-1);
}
.btn-secondary { --btn-bg: var(--surface-card); --btn-fg: var(--fg); --btn-border: var(--border-strong); }
.btn-red, .btn-danger {
    --btn-bg: var(--danger-solid);
    --btn-fg: #fff;
    --btn-border: var(--danger-solid);
    --btn-bg-hover: var(--danger-hover);
    --btn-bg-active: var(--danger-pressed);
}

/* ============================================================================
   БЕЙДЖИ И СТАТУСЫ
   ----------------------------------------------------------------------------
   Один компонент .badge + тон. Легаси-варианты (.badge-HIGH, .badge-sent,
   .badge-bounce …) отображены на те же тона: класс в шаблонах собирается
   интерполяцией `badge-{{ status }}`, поэтому важен и фолбэк — неизвестное
   значение остаётся нейтральным, а не пропадает.
============================================================================ */

.badge, .tag {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 2px 9px;
    font-size: var(--text-sm);
    font-weight: 600;
    line-height: 1.5;
    white-space: nowrap;
    color: var(--fg-muted);
    background: var(--neutral-bg);
    border: 1px solid var(--neutral-border);
    border-radius: var(--radius-pill);
}
.badge .icon { width: 12px; height: 12px; }

.badge-success, .badge-green, .badge-sent, .badge-HIGH {
    color: var(--success-text); background: var(--success-bg); border-color: var(--success-border);
}
.badge-warning, .badge-bounce, .badge-MEDIUM {
    color: var(--warning-text); background: var(--warning-bg); border-color: var(--warning-border);
}
.badge-danger, .badge-failed, .badge-complaint, .badge-LOW {
    color: var(--danger-text); background: var(--danger-bg); border-color: var(--danger-border);
}
.badge-info, .badge-sending, .badge-ses {
    color: var(--info-text); background: var(--info-bg); border-color: var(--info-border);
}
.badge-accent, .badge-validation, .badge-unsubscribe {
    color: var(--brand-text); background: var(--brand-bg); border-color: var(--brand-border);
}
.badge-neutral, .badge-pending, .badge-manual, .badge-skipped,
.badge-local, .badge-unchecked {
    color: var(--fg-muted); background: var(--neutral-bg); border-color: var(--neutral-border);
}
.badge-skipped { opacity: .8; }

/* Статус кампании: точка + подпись. Точка «дышит», пока кампания реально
   выполняется — статичный текст «идёт» ничего не говорит о том, живой ли
   процесс. */
.status {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 3px 11px;
    font-size: var(--text-sm);
    font-weight: 600;
    line-height: 1.5;
    white-space: nowrap;
    border: 1px solid transparent;
    border-radius: var(--radius-pill);
}
.status::before {
    content: "";
    width: 7px; height: 7px;
    flex: none;
    border-radius: 50%;
    background: currentColor;
}
.status-draft   { color: var(--fg-muted);     background: var(--neutral-bg);  border-color: var(--neutral-border); }
.status-running { color: var(--brand-text);   background: var(--brand-bg);    border-color: var(--brand-border); }
.status-paused  { color: var(--warning-text); background: var(--warning-bg);  border-color: var(--warning-border); }
.status-done    { color: var(--success-text); background: var(--success-bg);  border-color: var(--success-border); }
.status-stopped { color: var(--danger-text);  background: var(--danger-bg);   border-color: var(--danger-border); }
.status-lg { font-size: var(--text-base); padding: 4px 13px; }

.status-running.is-active::before { animation: pulse 1.6s var(--ease) infinite; }
@keyframes pulse {
    0%, 100% { opacity: 1; transform: scale(1); box-shadow: 0 0 0 0 currentColor; }
    50%      { opacity: .45; transform: scale(1.15); box-shadow: 0 0 0 4px transparent; }
}

/* ============================================================================
   МЕТРИКИ
   ----------------------------------------------------------------------------
   Один компонент вместо трёх (.stat / .rep-metric / .pf-item), которые
   отличались размером цифры (30/26/26px), радиусом (10/8/10px) и фоном
   (карточка / врезка / прозрачный) — на соседних экранах одна и та же по
   смыслу плитка выглядела тремя разными вещами.
============================================================================ */

.metric-grid {
    display: grid;
    gap: var(--s3);
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    margin: var(--s3) 0;
}
.metric-grid-lg { grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: var(--s4); }

.metric {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: var(--s3) var(--s4);
    background: var(--surface-inset);
    border: 1px solid var(--border);
    border-left: 3px solid var(--border-strong);
    border-radius: var(--radius-md);
    transition: border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
}
.metric-value {
    font-size: var(--text-3xl);
    font-weight: 650;
    line-height: 1.1;
    letter-spacing: -.02em;
    color: var(--fg-strong);
    font-variant-numeric: tabular-nums;
}
.metric-value .unit, .metric-value .muted { font-size: var(--text-lg); font-weight: 500; color: var(--fg-muted); }
.metric-value-text { font-size: var(--text-lg); font-weight: 650; line-height: 1.3; }
.metric-label { font-size: var(--text-base); color: var(--fg-muted); }
.metric-sub { margin-top: var(--s1); font-size: var(--text-xs); color: var(--fg-subtle); }
.metric-foot { margin-top: var(--s2); display: flex; align-items: center; gap: 6px; font-size: var(--text-xs); }

/* Тона: цветом окрашивается засечка слева и цифра, а не вся подложка —
   четыре залитых плитки в ряд превращали экран в «светофорную ёлку». */
.metric-ok      { border-left-color: var(--success-solid); }
.metric-ok      .metric-value { color: var(--success-text); }
.metric-warn    { border-left-color: var(--warning-solid); }
.metric-warn    .metric-value { color: var(--warning-text); }
.metric-danger  { border-left-color: var(--danger-solid); }
.metric-danger  .metric-value { color: var(--danger-text); }
.metric-accent  { border-left-color: var(--brand); }
.metric-accent  .metric-value { color: var(--brand-text); }
.metric-unknown { opacity: .72; }

/* KPI первого уровня (дашборд): крупнее, на карточке, со слотом тренда. */
.metric-kpi {
    background: var(--surface-card);
    padding: var(--s4) var(--s5);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-1);
}
.metric-kpi .metric-value { font-size: var(--text-4xl); }
.metric-kpi:hover { box-shadow: var(--shadow-2); }

.trend { display: inline-flex; align-items: center; gap: 3px; font-weight: 600; }
.trend-up   { color: var(--success-text); }
.trend-down { color: var(--danger-text); }
.trend-flat { color: var(--fg-subtle); }

/* Спарклайн рядом с KPI */
.sparkline { display: block; width: 100%; height: 34px; margin-top: var(--s2); overflow: visible; }
.sparkline path { fill: none; stroke: var(--brand); stroke-width: 1.75; stroke-linejoin: round; stroke-linecap: round; }
.sparkline .area { fill: var(--brand-bg); stroke: none; }

/* ─── Легаси: .stat / .rep-metric / .pf-item ─── */
.stat-grid, .rep-grid, .preflight-grid {
    display: grid;
    gap: var(--s3);
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    margin: var(--s3) 0;
}
.stat, .rep-metric, .pf-item {
    display: flex;
    flex-direction: column;
    gap: 2px;
    text-align: left;
    padding: var(--s3) var(--s4);
    background: var(--surface-inset);
    border: 1px solid var(--border);
    border-left: 3px solid var(--border-strong);
    border-radius: var(--radius-md);
    min-width: 0;
}
.stat-num, .rep-num, .pf-num {
    font-size: var(--text-3xl);
    font-weight: 650;
    line-height: 1.1;
    letter-spacing: -.02em;
    color: var(--fg-strong);
    font-variant-numeric: tabular-nums;
}
.stat-lbl, .rep-lbl, .pf-lbl { font-size: var(--text-base); color: var(--fg-muted); }
.rep-sub { margin-top: var(--s1); font-size: var(--text-xs); color: var(--fg-subtle); }
.stat-num.green, .rep-ok .rep-num { color: var(--success-text); }
.stat-num.red { color: var(--danger-text); }
/* Не ошибка, но требует внимания: например «уже отправляли» на экране
   загрузки базы — эти контакты сохранятся, но письма не получат. */
.stat-num.amber { color: var(--warning-text); }
.stat-num .muted, .rep-num .muted { font-size: var(--text-lg); font-weight: 500; }
.rep-ok      { border-left-color: var(--success-solid); background: var(--surface-inset); }
.rep-warn    { border-left-color: var(--warning-solid); }
.rep-warn    .rep-num { color: var(--warning-text); }
.rep-stop    { border-left-color: var(--danger-solid); }
.rep-stop    .rep-num { color: var(--danger-text); }
.rep-unknown { opacity: .72; }

/* ============================================================================
   ТАБЛИЦЫ
   ----------------------------------------------------------------------------
   Главный рабочий инструмент панели: 400 контактов × 18 колонок. Что
   добавлено против прежней версии:
   - прилипающая шапка (раньше при скролле было непонятно, что за колонка);
   - выраженный фон шапки и hover строки;
   - числовые колонки по правому краю монопропорциональными цифрами;
   - обрезка длинных значений (.cell-clip) вместо разъезжающейся вёрстки;
   - колонка действий фиксированной ширины справа.
============================================================================ */

.scroll-x {
    overflow-x: auto;
    overscroll-behavior-x: contain;
    /* тень-подсказка «таблица шире экрана» */
    background:
        linear-gradient(to right, var(--surface-card) 30%, transparent),
        linear-gradient(to left,  var(--surface-card) 30%, transparent),
        linear-gradient(to right, rgba(0,0,0,.08), transparent 12px),
        linear-gradient(to left,  rgba(0,0,0,.08), transparent 12px);
    background-repeat: no-repeat;
    background-size: 40px 100%, 40px 100%, 14px 100%, 14px 100%;
    background-position: 0 0, 100% 0, 0 0, 100% 0;
    background-attachment: local, local, scroll, scroll;
}

.table {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    margin-top: var(--s3);
    font-size: var(--text-base);
}
.table th, .table td {
    text-align: left;
    padding: 9px var(--s3);
    border-bottom: 1px solid var(--border);
    vertical-align: middle;
}
.table thead th {
    position: sticky;
    top: 0;
    z-index: var(--z-sticky);
    padding-top: 8px;
    padding-bottom: 8px;
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--fg-muted);
    white-space: nowrap;
    background: var(--surface-inset);
    border-bottom: 1px solid var(--border-strong);
}
.table thead th:first-child { border-radius: var(--radius) 0 0 0; }
.table thead th:last-child  { border-radius: 0 var(--radius) 0 0; }
.table tbody tr { transition: background var(--dur-fast) var(--ease); }
.table tbody tr:hover { background: var(--surface-hover); }
/* Строка, которую человек сейчас и открыл: в истории писем по одному адресу
   без подсветки непонятно, какая из записей на экране. */
.table tbody tr.is-current { background: var(--brand-bg); }
.table tbody tr.is-current td, .table tbody tr.is-current th { font-weight: 600; }
.table tbody tr:last-child td { border-bottom: none; }
.table a { font-weight: 600; }
.table code { background: transparent; border: none; padding: 0; }

/* Компактный режим для больших списков */
.table-compact th, .table-compact td { padding: 5px var(--s2); }
.table-compact { font-size: var(--text-sm); }

/* Числа */
.table .num, .table .cell-num, .table th.num { text-align: right; font-variant-numeric: tabular-nums; }

/* Обрезка длинных значений (SES message id, тексты ошибок SMTP) */
.cell-clip {
    max-width: 260px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.cell-wrap { max-width: 320px; white-space: normal; overflow-wrap: anywhere; }
.cell-empty { color: var(--fg-subtle); }
.cell-shrink { width: 1%; white-space: nowrap; }

/* Колонка действий: справа, одинаковой ширины во всех строках */
.row-actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--s1);
}
.table td:last-child .row-actions { margin-left: auto; }

/* Первая колонка «имя» — с подзаголовком */
.cell-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.cell-main .cell-sub { font-size: var(--text-sm); color: var(--fg-muted); }

/* Ключ-значение */
.table-kv { margin-top: 0; }
.table-kv th {
    width: 32%;
    position: static;
    background: transparent;
    border-bottom: 1px solid var(--border);
    font-size: var(--text-base);
    font-weight: 600;
    color: var(--fg-muted);
    vertical-align: top;
    white-space: normal;
}
.table-kv td { vertical-align: top; }
.table-kv tbody tr:hover { background: transparent; }

/* Выбор строк + панель массовых действий */
.table-select th:first-child, .table-select td:first-child { width: 36px; padding-right: 0; }
.bulk-bar {
    position: sticky;
    top: var(--appbar-h);
    z-index: calc(var(--z-sticky) + 1);
    display: flex;
    align-items: center;
    gap: var(--s3);
    flex-wrap: wrap;
    margin: var(--s3) 0;
    padding: var(--s2) var(--s3);
    font-size: var(--text-base);
    background: var(--brand-bg);
    border: 1px solid var(--brand-border);
    border-radius: var(--radius);
}
.bulk-bar[hidden] { display: none; }
.bulk-count { font-weight: 650; color: var(--brand-text); }

/* Пагинация */
.pager {
    display: flex;
    align-items: center;
    gap: var(--s3);
    flex-wrap: wrap;
    margin-top: var(--s4);
    padding-top: var(--s3);
    border-top: 1px solid var(--border);
    font-size: var(--text-base);
    color: var(--fg-muted);
}
.pager-info { margin-right: auto; font-variant-numeric: tabular-nums; }

/* ============================================================================
   СООБЩЕНИЯ (MessageBar)
============================================================================ */

.alert {
    display: flex;
    align-items: flex-start;
    gap: var(--s3);
    padding: var(--s3) var(--s4);
    margin-bottom: var(--s4);
    font-size: var(--text-md);
    line-height: var(--leading-normal);
    text-align: left;
    color: var(--fg);
    background: var(--surface-inset);
    border: 1px solid var(--border);
    border-left: 3px solid var(--neutral-solid);
    border-radius: var(--radius);
}
.alert:last-child { margin-bottom: 0; }
.alert > .icon { margin-top: 2px; color: var(--fg-muted); }
.alert b, .alert strong { color: var(--fg-strong); }
.alert ul { margin: var(--s2) 0 0; padding-left: 20px; }
.alert ul li + li { margin-top: 4px; }
.alert p { max-width: var(--measure); }

.alert-error, .alert-danger {
    background: var(--danger-bg); border-color: var(--danger-border); border-left-color: var(--danger-solid);
}
.alert-error > .icon { color: var(--danger); }
.alert-warn, .alert-warning {
    background: var(--warning-bg); border-color: var(--warning-border); border-left-color: var(--warning-solid);
}
.alert-warn > .icon { color: var(--warning); }
.alert-ok, .alert-success {
    background: var(--success-bg); border-color: var(--success-border); border-left-color: var(--success-solid);
}
.alert-ok > .icon { color: var(--success); }
.alert-info {
    background: var(--info-bg); border-color: var(--info-border); border-left-color: var(--info-solid);
}
.alert-info > .icon { color: var(--info); }

/* Результат AJAX-проверки рядом с кнопкой. Раньше это был `.alert` без
   варианта: прозрачный фон + прозрачная рамка = невидимая плашка, в которой
   висел текст «Проверяем…». */
.result-box {
    display: flex;
    align-items: flex-start;
    gap: var(--s2);
    margin-top: var(--s3);
    padding: var(--s3);
    font-size: var(--text-base);
    background: var(--surface-inset);
    border: 1px solid var(--border);
    border-left: 3px solid var(--neutral-solid);
    border-radius: var(--radius);
    white-space: pre-wrap;
}
.result-box[hidden] { display: none; }
.result-box.is-pending { border-left-color: var(--brand); color: var(--fg-muted); }
.result-box.is-ok    { background: var(--success-bg); border-color: var(--success-border); border-left-color: var(--success-solid); }
.result-box.is-error { background: var(--danger-bg);  border-color: var(--danger-border);  border-left-color: var(--danger-solid); }

/* Врезка-пояснение */
.hint-info {
    margin-top: var(--s3);
    padding: var(--s3) var(--s4);
    font-size: var(--text-base);
    color: var(--fg-muted);
    background: var(--surface-inset);
    border-left: 3px solid var(--border-strong);
    border-radius: 0 var(--radius) var(--radius) 0;
    max-width: var(--measure);
}

/* ============================================================================
   МОДАЛЬНЫЙ ДИАЛОГ ПОДТВЕРЖДЕНИЯ
   ----------------------------------------------------------------------------
   Замена девяти нативных confirm(), в которые заталкивали по два абзаца
   текста через \n\n. Нативное окно нельзя оформить, нельзя показать список
   затронутых объектов и нельзя потребовать ввод имени для необратимых
   операций.
============================================================================ */

.dialog {
    width: min(92vw, 480px);
    padding: 0;
    color: var(--fg);
    background: var(--surface-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-4);
}
.dialog::backdrop {
    background: var(--surface-overlay);
    backdrop-filter: blur(2px);
}
.dialog[open] { animation: dialog-in var(--dur) var(--ease-out); }
@keyframes dialog-in {
    from { opacity: 0; transform: translateY(8px) scale(.985); }
    to   { opacity: 1; transform: none; }
}

.dialog-head {
    display: flex;
    align-items: flex-start;
    gap: var(--s3);
    padding: var(--s5) var(--s5) var(--s3);
}
.dialog-ico {
    display: grid;
    place-items: center;
    width: 36px; height: 36px;
    flex: 0 0 auto;
    border-radius: 50%;
    color: var(--fg-muted);
    background: var(--neutral-bg);
}
.dialog-danger .dialog-ico { color: var(--danger); background: var(--danger-bg); }
.dialog-warn   .dialog-ico { color: var(--warning); background: var(--warning-bg); }
.dialog-title { margin: 0; font-size: var(--text-lg); font-weight: 650; }
.dialog-body {
    padding: 0 var(--s5) var(--s4);
    font-size: var(--text-md);
    color: var(--fg-muted);
}
.dialog-body p { max-width: none; }
.dialog-body strong { color: var(--fg); }
.dialog-list {
    margin: var(--s3) 0 0;
    padding: var(--s2) var(--s3);
    max-height: 180px;
    overflow: auto;
    font-size: var(--text-base);
    background: var(--surface-inset);
    border: 1px solid var(--border);
    border-radius: var(--radius);
}
.dialog-foot {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--s2);
    padding: var(--s4) var(--s5);
    background: var(--surface-inset);
    border-top: 1px solid var(--border);
    border-radius: 0 0 var(--radius-xl) var(--radius-xl);
}
.dialog-foot .spacer { flex: 1 1 auto; }

/* ============================================================================
   ТОСТЫ
============================================================================ */

#toast-wrap {
    position: fixed;
    top: calc(var(--appbar-h) + var(--s3));
    right: var(--s5);
    z-index: var(--z-toast);
    display: flex;
    flex-direction: column;
    gap: var(--s2);
    max-width: min(92vw, 400px);
    pointer-events: none;
}
.toast {
    display: flex;
    align-items: flex-start;
    gap: var(--s3);
    padding: var(--s3) var(--s4);
    font-size: var(--text-md);
    color: var(--fg);
    background: var(--surface-card);
    border: 1px solid var(--border);
    border-left: 3px solid var(--neutral-solid);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-3);
    cursor: pointer;
    pointer-events: auto;
    animation: toast-in var(--dur) var(--ease-out);
}
.toast.ok  { border-left-color: var(--success-solid); }
.toast.err { border-left-color: var(--danger-solid); }
.toast .toast-ico { flex: 0 0 auto; color: var(--fg-muted); line-height: 1.4; font-weight: 700; }
.toast.ok .toast-ico  { color: var(--success); }
.toast.err .toast-ico { color: var(--danger); }
.toast .toast-msg { flex: 1 1 auto; overflow-wrap: anywhere; }
.toast.hide { animation: toast-out var(--dur) var(--ease) forwards; }
@keyframes toast-in  { from { opacity: 0; transform: translateX(16px); } to { opacity: 1; transform: none; } }
@keyframes toast-out { to { opacity: 0; transform: translateX(16px); } }

/* ============================================================================
   ПУСТЫЕ СОСТОЯНИЯ
============================================================================ */

.empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--s3);
    padding: var(--s8) var(--s5);
    text-align: center;
    color: var(--fg-muted);
}
.empty .empty-ico {
    display: grid;
    place-items: center;
    width: 52px; height: 52px;
    color: var(--fg-subtle);
    background: var(--surface-inset);
    border: 1px solid var(--border);
    border-radius: 50%;
    font-size: 22px;
}
.empty .empty-ico .icon { width: 24px; height: 24px; }
.empty h3 { margin: 0; color: var(--fg); }
.empty p { margin: 0; max-width: 56ch; }
.empty-sm { padding: var(--s5) var(--s4); }

/* ============================================================================
   ПРОГРЕСС, СКЕЛЕТОНЫ
============================================================================ */

.progress-bar {
    height: 8px;
    margin: var(--s3) 0;
    overflow: hidden;
    background: var(--surface-sunken);
    border-radius: var(--radius-pill);
}
.progress-fill {
    height: 100%;
    background: var(--brand);
    border-radius: var(--radius-pill);
    transition: width var(--dur-slow) var(--ease);
}
/* Пока кампания реально отправляет — полоса «движется»: статичная полоса
   не отличает «идёт» от «залипло». */
.progress-bar.is-running .progress-fill {
    background-image: linear-gradient(90deg,
        rgba(255,255,255,.28) 25%, transparent 25%, transparent 50%,
        rgba(255,255,255,.28) 50%, rgba(255,255,255,.28) 75%, transparent 75%);
    background-size: 18px 18px;
    animation: stripes 1s linear infinite;
}
@keyframes stripes { to { background-position: 18px 0; } }

.progress-mini {
    width: 120px; height: 6px;
    overflow: hidden;
    background: var(--surface-sunken);
    border-radius: var(--radius-pill);
}
.progress-mini > span {
    display: block; height: 100%;
    background: var(--brand);
    border-radius: var(--radius-pill);
    transition: width var(--dur-slow) var(--ease);
}
.progress-cell { display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap; }

.skeleton {
    display: block;
    min-height: 1em;
    border-radius: var(--radius-sm);
    background: linear-gradient(90deg,
        var(--surface-inset) 25%, var(--surface-hover) 37%, var(--surface-inset) 63%);
    background-size: 400% 100%;
    animation: shimmer 1.4s ease-in-out infinite;
    color: transparent !important;
}
@keyframes shimmer { 0% { background-position: 100% 0; } 100% { background-position: 0 0; } }

/* Индикатор «живых» данных: цифра мигает при обновлении */
.is-updated { animation: flash-accent .9s var(--ease); }
@keyframes flash-accent {
    from { background: var(--brand-bg); }
    to   { background: transparent; }
}
.live-dot {
    display: inline-flex; align-items: center; gap: 6px;
    font-size: var(--text-xs); color: var(--fg-subtle);
}
.live-dot::before {
    content: ""; width: 6px; height: 6px; border-radius: 50%;
    background: var(--success-solid);
    animation: pulse 1.6s var(--ease) infinite;
}

/* ============================================================================
   ПЕРЕКЛЮЧАТЕЛИ НАБОРА (сегменты, вкладки, чип-фильтры)
   ----------------------------------------------------------------------------
   Раньше одну и ту же задачу решали три разных компонента: .tabs/.tab,
   .filter-row/.chip-btn и .seg-filter/.seg. Визуал у них теперь общий.
============================================================================ */

.segmented, .tabs {
    display: inline-flex;
    gap: 2px;
    padding: 3px;
    background: var(--surface-inset);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
}
.segmented-item, .tab {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 13px;
    font: inherit;
    font-size: var(--text-base);
    font-weight: 500;
    color: var(--fg-muted);
    background: transparent;
    border: none;
    border-radius: var(--radius-sm);
    cursor: pointer;
    white-space: nowrap;
    transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.segmented-item:hover, .tab:hover { color: var(--fg); background: var(--surface-hover); text-decoration: none; }
.segmented-item.is-on, .tab.is-on, .segmented-item[aria-selected="true"] {
    color: var(--fg-strong);
    background: var(--surface-card);
    border: none;
    box-shadow: var(--shadow-1);
    font-weight: 600;
}
.segmented-count {
    padding: 0 5px;
    font-size: var(--text-xs);
    font-weight: 600;
    color: var(--fg-muted);
    background: var(--neutral-bg);
    border-radius: var(--radius-pill);
}
.segmented-item.is-on .segmented-count { color: var(--brand-text); background: var(--brand-bg); }

/* Фильтр-чипы (очередь кампании) */
.filter-row { display: flex; gap: var(--s2); flex-wrap: wrap; margin: var(--s3) 0; }

/* Панель фильтров журнала отправок.
   .field рассчитан на вертикальную форму (max-width 640px и отступ снизу),
   поэтому шесть фильтров в одну строку растянулись бы каждый на всю ширину.
   .field-inline сжимает поле до размера содержимого, сохраняя подпись над
   ним: фильтр без подписи («что это за выпадашка?») бесполезен. */
.filter-form { margin: var(--s3) 0; }
.filter-form .filter-row { align-items: flex-end; margin: 0; }
.field-inline { margin-bottom: 0; max-width: 240px; flex: 0 1 auto; }
.field-inline select, .field-inline input { width: auto; min-width: 150px; }
.field-inline .field-hint { margin: 2px 0 0; }
.chip-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 12px;
    font-family: var(--font-sans);
    font-size: var(--text-base);
    font-weight: 500;
    color: var(--fg);
    background: var(--surface-card);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-pill);
    cursor: pointer;
    white-space: nowrap;
}
.chip-btn:hover { border-color: var(--brand); color: var(--brand-text); background: var(--brand-bg); text-decoration: none; }
.chip-on {
    color: var(--brand-fg);
    background: var(--brand);
    border-color: var(--brand);
    font-weight: 600;
}
.chip-on:hover { color: var(--brand-fg); background: var(--brand-hover); border-color: var(--brand-hover); }

/* Сегменты качества базы (recipient_detail) */
.seg-filter { display: flex; gap: var(--s2); flex-wrap: wrap; margin: var(--s3) 0; }
.seg {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 5px 13px;
    font-size: var(--text-base);
    line-height: 1.3;
    color: var(--fg);
    background: var(--surface-card);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-pill);
    white-space: nowrap;
}
.seg:hover { border-color: var(--brand); text-decoration: none; }
.seg b { font-variant-numeric: tabular-nums; }
.seg-on { border-color: var(--brand); box-shadow: inset 0 0 0 1px var(--brand); font-weight: 600; }
.seg::before {
    content: ""; width: 9px; height: 9px; flex: none;
    border-radius: 50%; background: var(--verdict-unknown);
}
.seg-HIGH::before      { background: var(--verdict-high); }
.seg-MEDIUM::before    { background: var(--verdict-medium); }
.seg-LOW::before       { background: var(--verdict-low); }
.seg-unchecked::before { background: var(--verdict-unknown); }

.seg-actions {
    display: flex;
    align-items: center;
    gap: var(--s3);
    flex-wrap: wrap;
    margin-bottom: var(--s3);
    padding: var(--s3) var(--s4);
    font-size: var(--text-base);
    background: var(--surface-inset);
    border: 1px solid var(--border);
    border-radius: var(--radius);
}

/* ============================================================================
   ЖУРНАЛ СОБЫТИЙ
============================================================================ */

.event-log {
    list-style: none;
    margin: var(--s3) 0 0;
    padding: 0;
    max-height: 440px;
    overflow-y: auto;
    overscroll-behavior: contain;
    background: var(--surface-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
}
.event-log .ev {
    display: flex;
    gap: var(--s3);
    padding: 7px var(--s3);
    font-size: var(--text-base);
    line-height: 1.45;
    border-bottom: 1px solid var(--border);
    border-left: 3px solid transparent;
}
.event-log .ev:last-child { border-bottom: none; }
.ev-time {
    flex: 0 0 auto;
    min-width: 92px;
    color: var(--fg-subtle);
    font-variant-numeric: tabular-nums;
    font-size: var(--text-sm);
    padding-top: 1px;
}
.ev-msg { flex: 1 1 auto; overflow-wrap: anywhere; }
.ev-mail { font-size: var(--text-sm); color: var(--fg-muted); }
.ev-warning { background: var(--warning-bg); border-left-color: var(--warning-solid); }
.ev-error   { background: var(--danger-bg);  border-left-color: var(--danger-solid); }
.ev-new     { animation: ev-in .8s var(--ease); }
@keyframes ev-in { from { background: var(--brand-bg); } to { background: transparent; } }
.event-log .ev[hidden] { display: none; }

/* Состояние рабочего окна */
.window-state {
    display: flex;
    align-items: flex-start;
    gap: var(--s3);
    margin: var(--s4) 0;
    padding: var(--s3) var(--s4);
    font-size: var(--text-md);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
}
.window-state.is-open   { background: var(--success-bg); border-color: var(--success-border); }
.window-state.is-closed { background: var(--surface-inset); }
.window-ico { flex: 0 0 auto; line-height: 1.4; }
.window-state.is-open .window-ico   { color: var(--success); }
.window-state.is-closed .window-ico { color: var(--fg-muted); }

/* ============================================================================
   ЧИПЫ-ТОКЕНЫ, ПРОВЕРКИ, ВЕРДИКТЫ
============================================================================ */

/* .chip — именно «токен-код» (адрес ящика, имя шаблона, колонка CSV).
   Роли «кнопка» и «фильтр» у этого класса забраны: для них .chip-btn/.seg. */
.chip {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 2px 8px;
    margin: 2px 0;
    font-family: var(--font-mono);
    font-size: var(--text-sm);
    color: var(--fg);
    background: var(--surface-inset);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    white-space: nowrap;
}
.chip-off { opacity: .6; text-decoration: line-through; }
.chip-warn { border-color: var(--warning-border); background: var(--warning-bg); }

/* Шкала вердиктов базы */
.verdict-bar {
    display: flex;
    height: 24px;
    margin: var(--s3) 0;
    overflow: hidden;
    border-radius: var(--radius);
    background: var(--surface-sunken);
}
.verdict-bar > span {
    display: flex;
    align-items: center;
    justify-content: center;
    min-width: 0;
    overflow: hidden;
    font-size: var(--text-xs);
    font-weight: 700;
    color: #fff;
    white-space: nowrap;
}
.verdict-bar .v-HIGH      { background: var(--verdict-high); }
.verdict-bar .v-MEDIUM    { background: var(--verdict-medium); color: #2b1d00; }
.verdict-bar .v-LOW       { background: var(--verdict-low); }
.verdict-bar .v-unchecked { background: var(--verdict-unknown); }

.verdict-legend, .checks-legend { display: flex; gap: var(--s4); flex-wrap: wrap; font-size: var(--text-base); }
.verdict-legend i {
    display: inline-block;
    width: 10px; height: 10px;
    margin-right: 5px;
    vertical-align: middle;
    border-radius: 3px;
}
.verdict-legend .v-HIGH      { background: var(--verdict-high); }
.verdict-legend .v-MEDIUM    { background: var(--verdict-medium); }
.verdict-legend .v-LOW       { background: var(--verdict-low); }
.verdict-legend .v-unchecked { background: var(--verdict-unknown); }

/* Полоска шести проверок адреса */
.check-strip { display: inline-flex; gap: 3px; }
.check-box {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px; height: 20px;
    font-size: var(--text-xs);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    background: var(--surface-inset);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    cursor: help;
    user-select: none;
}
.check-box.q-good { color: var(--success-text); background: var(--success-bg); border-color: var(--success-border); }
.check-box.q-mid  { color: var(--warning-text); background: var(--warning-bg); border-color: var(--warning-border); }
.check-box.q-bad  { color: var(--danger-text);  background: var(--danger-bg);  border-color: var(--danger-border); }
.check-box.q-na   { opacity: .45; }

.note-tag {
    display: inline-block;
    margin: 1px 3px 1px 0;
    padding: 1px 7px;
    font-size: var(--text-xs);
    font-weight: 600;
    color: var(--warning-text);
    background: var(--warning-bg);
    border: 1px solid var(--warning-border);
    border-radius: var(--radius-pill);
}
.notes-cell { max-width: 220px; white-space: normal; }
.table-contacts td { vertical-align: middle; }

/* ============================================================================
   ЛЕГАСИ-ХЕЛПЕРЫ РАСКЛАДКИ
   ----------------------------------------------------------------------------
   Классы из первой версии вёрстки. Сохранены, пока шаблоны переводятся на
   .field / .section-head / .row.
============================================================================ */

.stack { display: flex; flex-direction: column; gap: 4px; }
.stack > label {
    margin-top: var(--s3);
    font-size: var(--text-base);
    font-weight: 600;
    color: var(--fg);
}
.stack > label:first-child { margin-top: 0; }
.stack input, .stack select, .stack textarea { max-width: 640px; }
.stack .btn { align-self: flex-start; margin-top: var(--s4); }
.stack .hint { margin: 2px 0 0; }

.row-between {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s3);
    flex-wrap: wrap;
    margin-bottom: var(--s3);
}
.row-between h2, .row-between h3 { margin: 0; }
.row-inline { display: flex; gap: var(--s5); flex-wrap: wrap; align-items: flex-start; }
.row-inline > div { display: flex; flex-direction: column; gap: 4px; }
.time-row { display: flex; gap: 6px; align-items: center; }
.time-row .mini { width: 62px; text-align: center; }
.time-sep { color: var(--fg-subtle); }
.inline-label { color: var(--fg-muted); font-size: var(--text-base); margin-right: 6px; }

.controls { display: flex; gap: var(--s2); flex-wrap: wrap; align-items: center; margin-top: var(--s4); }
.controls form { margin: 0; }
.reports { display: flex; gap: var(--s2); flex-wrap: wrap; margin-top: var(--s3); }

.macro-hint, .macro-label { font-size: var(--text-base); color: var(--fg-muted); }
.macro-hint { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin: 6px 0; }

.attention-list, .setup-list { margin: var(--s3) 0 0; padding-left: 20px; line-height: 1.9; }
.attention-list li::marker { color: var(--warning); }

.checklist-status { list-style: none; margin: var(--s3) 0 0; padding: 0; }
.checklist-status li {
    display: flex;
    align-items: flex-start;
    gap: var(--s2);
    padding: 5px 0;
    border-bottom: 1px solid var(--border);
}
.checklist-status li:last-child { border-bottom: none; }
.checklist-status .ok  { color: var(--success-text); }
.checklist-status .bad { color: var(--danger-text); }

.notes { padding-left: 20px; margin: var(--s2) 0 0; }
.notes li { margin-bottom: 5px; }

/* <details> как раскрывающийся блок документации */
details {
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface-inset);
    padding: 0;
    margin-bottom: var(--s3);
}
details > summary, .summary-btn {
    padding: var(--s2) var(--s3);
    font-size: var(--text-base);
    font-weight: 600;
    color: var(--fg);
    cursor: pointer;
    list-style: none;
    display: flex;
    align-items: center;
    gap: var(--s2);
    border-radius: var(--radius);
}
details > summary::-webkit-details-marker { display: none; }
details > summary::before {
    content: "";
    width: 0; height: 0;
    flex: 0 0 auto;
    border-left: 5px solid var(--fg-subtle);
    border-top: 4px solid transparent;
    border-bottom: 4px solid transparent;
    transition: transform var(--dur-fast) var(--ease);
}
details[open] > summary::before { transform: rotate(90deg); }
details > summary:hover { background: var(--surface-hover); }
details > *:not(summary) { margin-left: var(--s3); margin-right: var(--s3); }
details > *:not(summary):last-child { margin-bottom: var(--s3); }
details[open] > summary { border-bottom: 1px solid var(--border); border-radius: var(--radius) var(--radius) 0 0; }
details .table { margin-top: var(--s2); }

/* Диаграмма на дашборде */
.chart-wrap { position: relative; height: 340px; margin-top: var(--s2); }

/* Предпросмотр письма */
.preview-controls { margin-top: var(--s4); align-items: flex-end; }
.preview-item {
    padding: var(--s4);
    margin-bottom: var(--s3);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    background: var(--surface-card);
}
.preview-meta { font-size: var(--text-md); margin-bottom: var(--s1); }
.preview-html { margin-top: var(--s3); padding-top: var(--s3); border-top: 1px dashed var(--border-strong); }
.preview-frame {
    width: 100%;
    min-height: 160px;
    display: block;
    background: #fff;
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
}
.preview-text {
    max-height: 420px;
    overflow: auto;
    padding: var(--s3) var(--s4);
    font-family: var(--font-mono);
    font-size: var(--text-base);
    line-height: 1.55;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    background: var(--surface-inset);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
}

/* Подтверждение запуска кампании */
.confirm-chk {
    display: flex;
    align-items: flex-start;
    gap: var(--s3);
    padding: var(--s3) var(--s4);
    background: var(--surface-inset);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    cursor: pointer;
}
.confirm-chk:has(input:checked) { border-color: var(--success-border); background: var(--success-bg); }

/* Редактор Quill */
#editor { height: 300px; background: var(--surface-card); border-radius: 0 0 var(--radius) var(--radius); }
.ql-toolbar.ql-snow { border-radius: var(--radius) var(--radius) 0 0; border-color: var(--border-strong) !important; }
.ql-container.ql-snow { border-color: var(--border-strong) !important; }
.ql-editor { font-family: var(--font-sans); font-size: var(--text-md); }
:root[data-theme="dark"] .ql-editor { color: var(--fg); }
:root[data-theme="dark"] .ql-editor.ql-blank::before { color: var(--fg-subtle); }
:root[data-theme="dark"] .ql-snow .ql-stroke { stroke: var(--fg-muted); }
:root[data-theme="dark"] .ql-snow .ql-fill { fill: var(--fg-muted); }
:root[data-theme="dark"] .ql-snow .ql-picker { color: var(--fg); }
:root[data-theme="dark"] .ql-snow .ql-picker-options { background: var(--surface-card); border-color: var(--border-strong); }
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .ql-editor { color: var(--fg); }
    :root:not([data-theme="light"]) .ql-editor.ql-blank::before { color: var(--fg-subtle); }
    :root:not([data-theme="light"]) .ql-snow .ql-stroke { stroke: var(--fg-muted); }
    :root:not([data-theme="light"]) .ql-snow .ql-fill { fill: var(--fg-muted); }
    :root:not([data-theme="light"]) .ql-snow .ql-picker { color: var(--fg); }
    :root:not([data-theme="light"]) .ql-snow .ql-picker-options { background: var(--surface-card); border-color: var(--border-strong); }
}

/* ============================================================================
   ВХОД
============================================================================ */

.login-wrap {
    min-height: 100vh;
    display: grid;
    place-items: center;
    padding: var(--s5);
    background:
        radial-gradient(120% 90% at 50% -20%, var(--brand-bg) 0%, transparent 60%),
        var(--surface-app);
}
.login-card {
    width: 100%;
    max-width: 400px;
    padding: var(--s7) var(--s6);
    text-align: center;
    box-shadow: var(--shadow-3);
    border-radius: var(--radius-xl);
}
.logo-img {
    display: block;
    width: 64px; height: 64px;
    margin: 0 auto var(--s3);
    object-fit: contain;
}
.logo { margin: 0 0 var(--s1); font-size: var(--text-2xl); font-weight: 650; }
.subtitle { margin: 0 0 var(--s6); color: var(--fg-muted); }
.login-card form { text-align: left; }
.login-card label { display: block; margin-bottom: 6px; font-size: var(--text-base); font-weight: 600; }
.login-card input[type="password"] { margin-bottom: var(--s4); }
.login-card .btn { width: 100%; }
.login-hint { margin-top: var(--s4); font-size: var(--text-sm); color: var(--fg-muted); text-align: center; }

/* Поле пароля с кнопкой «показать» */
.password-field { position: relative; }
.password-field input { padding-right: 40px; }
.password-toggle {
    position: absolute;
    top: 50%; right: 4px;
    transform: translateY(-50%);
    color: var(--fg-muted);
}

/* ============================================================================
   СТРАНИЦА ОШИБКИ
============================================================================ */

.error-card { max-width: 520px; margin: var(--s8) auto; padding: var(--s7) var(--s6); text-align: center; }
.error-code { font-size: 64px; font-weight: 750; line-height: 1; color: var(--border-strong); }
.error-card .controls { justify-content: center; }

/* ============================================================================
   АДАПТИВНОСТЬ
============================================================================ */

@media (max-width: 760px) {
    .card { padding: var(--s4); }
    .metric-grid, .stat-grid, .rep-grid, .preflight-grid { grid-template-columns: repeat(auto-fit, minmax(128px, 1fr)); gap: var(--s2); }
    .metric, .stat, .rep-metric, .pf-item { padding: var(--s3); }
    .metric-value, .stat-num, .rep-num, .pf-num { font-size: var(--text-2xl); }
    .metric-kpi .metric-value { font-size: var(--text-3xl); }
    .table th, .table td { padding: 7px var(--s2); }
    .table-kv th { width: 40%; }
    .row-inline { gap: var(--s3); }
    #toast-wrap { right: var(--s3); left: var(--s3); max-width: none; }
    .action-bar { margin-inline: calc(-1 * var(--s4)); padding-inline: var(--s4); }
    .dialog { width: min(96vw, 480px); }
}

/* ============================================================================
   РЕДАКТОР ШАБЛОНА: две колонки
   ----------------------------------------------------------------------------
   Раньше карточка предпросмотра появлялась МЕЖДУ формой и блоком тестовой
   отправки: после нажатия страница меняла длину, блоки уезжали вниз, и
   приходилось прокручивать туда-обратно между текстом и его результатом.
   Теперь предпросмотр — закреплённая правая колонка: правишь слева, видишь
   справа.
============================================================================ */

.editor-layout {
    display: grid;
    gap: var(--s4);
    grid-template-columns: minmax(0, 1.45fr) minmax(320px, 1fr);
    align-items: start;
}
.editor-main { min-width: 0; }
.editor-side {
    position: sticky;
    top: calc(var(--appbar-h) + var(--s4));
    min-width: 0;
    max-height: calc(100vh - var(--appbar-h) - var(--s6));
    overflow-y: auto;
    overscroll-behavior: contain;
    display: flex;
    flex-direction: column;
    gap: var(--s4);
}
.editor-side .card { margin-bottom: 0; }
.editor-side .preview-frame { min-height: 320px; }
.editor-side .preview-item { padding: var(--s3); }

/* На узких экранах колонка уходит под форму: держать 320px рядом с
   редактором Quill бессмысленно. */
@media (max-width: 1100px) {
    .editor-layout { grid-template-columns: minmax(0, 1fr); }
    .editor-side { position: static; max-height: none; overflow: visible; }
}

/* ============================================================================
   ДОСТУПНОСТЬ
   ----------------------------------------------------------------------------
   Состояние вердиктов и шести проверок адреса передавалось ТОЛЬКО цветом и
   атрибутом title: скринридер зачитывал «H», «M», «L» без смысла, а при
   цветовой слепоте зелёный и красный индикаторы неразличимы.

   Решение: у каждого индикатора появляется текстовый дубль в .sr-only
   (видим только скринридеру) плюс различимая форма/символ, а не один цвет.
============================================================================ */

.sr-only {
    position: absolute !important;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}
/* Для ссылок «пропустить»: становится видимым при фокусе с клавиатуры. */
.sr-only-focusable:focus-visible {
    position: static !important;
    width: auto; height: auto;
    margin: 0; padding: var(--s2) var(--s3);
    clip: auto;
    background: var(--surface-card);
    border: 1px solid var(--brand);
    border-radius: var(--radius);
}

/* Полоска шести проверок: к цвету добавляется символ состояния, поэтому
   индикатор различим и без восприятия цвета. */
.check-box::after {
    content: "";
    position: absolute;
    right: 1px; bottom: 0;
    font-size: 9px;
    line-height: 1;
    opacity: .85;
}
.check-box { position: relative; }
.check-box.q-good::after { content: "+"; }
.check-box.q-bad::after  { content: "−"; }
.check-box.q-mid::after  { content: "?"; }

/* Шкала вердиктов: у сегментов есть подпись для скринридера, а визуально
   различимость усиливается штриховкой у «неизвестно». */
.verdict-bar .v-unchecked {
    background-image: repeating-linear-gradient(45deg,
        rgba(255,255,255,.22) 0 4px, transparent 4px 8px);
}

/* ============================================================================
   НАПРАВЛЕНИЯ, НАВИГАЦИЯ v2, ОБЩИЕ КОМПОНЕНТЫ РЕДИЗАЙНА
   ----------------------------------------------------------------------------
   Направление — верхний уровень организации (страна). Цвет направления —
   единственный «декоративный» цвет панели: по нему глаз находит свою страну
   в списке кампаний, ящиков и текстов. Поэтому палитра ограничена восемью
   хорошо различимыми тонами и всегда идёт вместе с текстовой меткой (DE/IT),
   а не одна — цвет не должен быть единственным носителем смысла.
============================================================================ */

.dir-c-blue   { --dir: #2f6fde; --dir-bg: #e6efff; --dir-fg: #1d4fa8; }
.dir-c-green  { --dir: #1f8a4c; --dir-bg: #e2f5ea; --dir-fg: #156438; }
.dir-c-amber  { --dir: #c77700; --dir-bg: #fff1d6; --dir-fg: #8a5200; }
.dir-c-purple { --dir: #7c4dcc; --dir-bg: #efe8fb; --dir-fg: #5a33a0; }
.dir-c-teal   { --dir: #0f8a8a; --dir-bg: #dff4f4; --dir-fg: #0a6464; }
.dir-c-red    { --dir: #c9372c; --dir-bg: #fde7e5; --dir-fg: #9c2219; }
.dir-c-pink   { --dir: #c2397a; --dir-bg: #fbe6f0; --dir-fg: #941f5a; }
.dir-c-slate  { --dir: #5b6675; --dir-bg: #e9edf2; --dir-fg: #3d4652; }
:root[data-theme="dark"] [class*="dir-c-"] { --dir-bg: color-mix(in srgb, var(--dir) 22%, transparent); --dir-fg: color-mix(in srgb, var(--dir) 55%, white); }
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) [class*="dir-c-"] { --dir-bg: color-mix(in srgb, var(--dir) 22%, transparent); --dir-fg: color-mix(in srgb, var(--dir) 55%, white); }
}

/* Чип-метка направления: «DE» на цветной подложке */
.dir-chip {
    display: inline-grid;
    place-items: center;
    min-width: 26px;
    height: 20px;
    padding: 0 5px;
    border-radius: 5px;
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: .03em;
    line-height: 1;
    color: #fff;
    background: var(--dir);
    flex: 0 0 auto;
    font-variant-numeric: tabular-nums;
}
.dir-chip-lg { min-width: 40px; height: 32px; font-size: 13px; border-radius: 8px; }
.dir-chip-xl { min-width: 52px; height: 44px; font-size: 16px; border-radius: 11px; }

/* Ссылка-тег направления в таблицах: [DE Германия] */
.dir-tag {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 2px 8px 2px 3px;
    border-radius: var(--radius-pill);
    background: var(--dir-bg);
    color: var(--dir-fg);
    font-size: var(--text-sm);
    font-weight: 600;
    white-space: nowrap;
    max-width: 100%;
}
.dir-tag .dir-chip { height: 18px; min-width: 22px; font-size: 9.5px; border-radius: var(--radius-pill); }
a.dir-tag:hover { text-decoration: none; filter: brightness(.97); }
.dir-tag-none { background: var(--surface-inset); color: var(--fg-subtle); padding-left: 8px; font-weight: 500; }

/* ─── Сайдбар: поиск, направления, счётчики ─── */
.nav-search {
    display: flex; align-items: center; gap: var(--s2);
    width: 100%;
    margin: 0 0 var(--s3);
    padding: 7px var(--s3);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface-inset);
    color: var(--fg-subtle);
    font: inherit;
    font-size: var(--text-base);
    cursor: pointer;
    text-align: left;
    transition: border-color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
}
.nav-search:hover { border-color: var(--border-strong); background: var(--surface-hover); color: var(--fg-muted); }
.nav-search:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.nav-search span { flex: 1 1 auto; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.nav-search kbd, .kbd {
    font: 600 10px/1 var(--font-sans);
    padding: 3px 5px;
    border: 1px solid var(--border-strong);
    border-bottom-width: 2px;
    border-radius: 4px;
    color: var(--fg-muted);
    background: var(--surface-card);
    white-space: nowrap;
}
.shell.is-collapsed .nav-search { justify-content: center; padding-inline: 0; }
.shell.is-collapsed .nav-search span,
.shell.is-collapsed .nav-search kbd,
.shell.is-collapsed .nav-dir-name,
.shell.is-collapsed .nav-title-add,
.shell.is-collapsed .nav-dir .live-dot { display: none; }
.shell.is-collapsed .nav-dir { justify-content: center; }
@media (max-width: 900px) {
    .shell.is-collapsed .nav-search span, .shell.is-collapsed .nav-search kbd,
    .shell.is-collapsed .nav-dir-name, .shell.is-collapsed .nav-title-add { display: revert; }
}

.nav-section-title-act { display: flex; align-items: center; justify-content: space-between; gap: var(--s2); }
.nav-title-link { color: inherit; }
.nav-title-link:hover { color: var(--fg); text-decoration: none; }
.nav-title-add {
    display: inline-grid; place-items: center;
    width: 20px; height: 20px;
    border-radius: 5px;
    color: var(--fg-subtle);
}
.nav-title-add:hover { background: var(--surface-hover); color: var(--brand); }

.nav-dir { padding-block: 6px; }
.nav-dir-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.nav-dir .live-dot { margin-left: auto; }
.nav-dir .live-dot + .nav-count { margin-left: 4px; }
.nav-dir.is-current { background: var(--dir-bg, var(--brand-bg)); }
.nav-dir-empty { color: var(--fg-muted); font-size: var(--text-base); }
.nav-count-live { color: var(--success-text); background: var(--success-bg); border-color: var(--success-border); }
.nav-count-warn { color: var(--warning-text); background: var(--warning-bg); border-color: var(--warning-border); }

/* ─── Подвкладки раздела (подчёркивание) ───
   Для переключения ВИДОВ одного объекта: Ящики | Провайдеры,
   Обзор | Ящики | Тексты… у направления. Отличаются от .segmented
   (фильтр внутри списка): это навигация, она ведёт на другой адрес. */
.subnav {
    display: flex;
    gap: var(--s1);
    margin: calc(-1 * var(--s2)) 0 var(--s5);
    border-bottom: 1px solid var(--border);
    overflow-x: auto;
    scrollbar-width: none;
}
.subnav::-webkit-scrollbar { display: none; }
.subnav a {
    position: relative;
    display: inline-flex; align-items: center; gap: 7px;
    padding: 10px var(--s3) 11px;
    color: var(--fg-muted);
    font-weight: 500;
    white-space: nowrap;
    border-radius: var(--radius) var(--radius) 0 0;
}
.subnav a:hover { color: var(--fg); background: var(--surface-hover); text-decoration: none; }
.subnav a.is-on { color: var(--fg-strong); font-weight: 600; }
.subnav a.is-on::after {
    content: ""; position: absolute; left: var(--s2); right: var(--s2); bottom: -1px;
    height: 2px; border-radius: 2px; background: var(--dir, var(--brand));
}
.subnav .subnav-count {
    font-size: var(--text-xs); font-weight: 600; color: var(--fg-subtle);
    background: var(--surface-inset); border-radius: var(--radius-pill); padding: 1px 6px;
}
.subnav a.is-on .subnav-count { color: var(--fg-muted); background: var(--surface-active); }

/* ─── Шапка направления ─── */
.dir-hero {
    display: flex; align-items: center; gap: var(--s4);
    margin-bottom: var(--s4);
}
.dir-hero-main { min-width: 0; flex: 1 1 auto; }
.dir-hero h2 { margin: 0; font-size: var(--text-2xl); letter-spacing: -.02em; }
.dir-hero-meta {
    display: flex; flex-wrap: wrap; gap: 4px var(--s4);
    margin-top: 4px; color: var(--fg-muted); font-size: var(--text-base);
}
.dir-hero-meta > span { display: inline-flex; align-items: center; gap: 5px; }
.dir-hero-actions { display: flex; gap: var(--s2); flex-wrap: wrap; }

/* ─── Карточки направлений (страница /directions) ─── */
.dir-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: var(--s4);
}
.dir-card {
    position: relative;
    display: flex; flex-direction: column; gap: var(--s3);
    padding: var(--s5);
    background: var(--surface-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-1);
    color: var(--fg);
    overflow: hidden;
    transition: box-shadow var(--dur) var(--ease), transform var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.dir-card::before {
    content: ""; position: absolute; inset: 0 0 auto 0; height: 3px; background: var(--dir);
}
a.dir-card:hover { text-decoration: none; box-shadow: var(--shadow-2); transform: translateY(-1px); border-color: var(--border-strong); }
.dir-card-head { display: flex; align-items: center; gap: var(--s3); }
.dir-card-head h3 { margin: 0; font-size: var(--text-lg); }
.dir-card-head .live-dot { margin-left: auto; }
.dir-card-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--s2); }
.dir-card-stats div { display: flex; flex-direction: column; }
.dir-card-stats b { font-size: var(--text-lg); font-variant-numeric: tabular-nums; color: var(--fg-strong); }
.dir-card-stats span { font-size: var(--text-xs); color: var(--fg-muted); }
.dir-card-foot { color: var(--fg-muted); font-size: var(--text-sm); display: flex; gap: var(--s3); flex-wrap: wrap; }
.dir-card-new {
    align-items: center; justify-content: center; text-align: center;
    border-style: dashed; box-shadow: none; color: var(--fg-muted); min-height: 160px;
    background: transparent;
}
.dir-card-new::before { display: none; }
a.dir-card-new:hover { color: var(--brand-text); border-color: var(--brand); background: var(--brand-bg); }

/* ─── Боковая панель (drawer) ───
   Правка объекта, не уводящая со страницы списка. Это <dialog>: фокус
   заперт внутри, Esc закрывает, фон затемнён. */
.drawer {
    position: fixed;
    inset: 0 0 0 auto;
    margin: 0;
    width: min(100vw, 460px);
    max-width: 100vw;
    height: 100vh;
    max-height: 100vh;
    padding: 0;
    border: none;
    border-left: 1px solid var(--border);
    background: var(--surface-card);
    color: var(--fg);
    box-shadow: var(--shadow-4);
    z-index: var(--z-dialog);
}
.drawer-wide { width: min(100vw, 640px); }
.drawer::backdrop { background: var(--surface-overlay); backdrop-filter: blur(1px); }
.drawer[open] { display: flex; flex-direction: column; animation: drawer-in var(--dur-slow) var(--ease-out); }
@keyframes drawer-in { from { transform: translateX(24px); opacity: 0; } to { transform: none; opacity: 1; } }
.drawer > form:first-of-type { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; height: auto; }
.drawer-head {
    display: flex; align-items: flex-start; gap: var(--s3);
    padding: var(--s5) var(--s5) var(--s4);
    border-bottom: 1px solid var(--border);
}
.drawer-head h2 { margin: 0; font-size: var(--text-lg); }
.drawer-head p { margin: 2px 0 0; color: var(--fg-muted); font-size: var(--text-base); word-break: break-all; }
.drawer-head .drawer-close { margin-left: auto; }
.drawer-body { flex: 1 1 auto; overflow: auto; padding: var(--s5); display: flex; flex-direction: column; gap: var(--s4); }
.drawer-foot {
    display: flex; gap: var(--s2); align-items: center;
    padding: var(--s4) var(--s5);
    border-top: 1px solid var(--border);
    background: var(--surface-inset);
}
.drawer-foot .spacer { flex: 1 1 auto; }
.drawer-section-title {
    margin: var(--s2) 0 calc(-1 * var(--s2));
    font-size: var(--text-xs); font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
    color: var(--fg-subtle);
}

/* ─── Палитра команд (Ctrl+K) ─── */
.palette {
    width: min(94vw, 640px);
    margin: 12vh auto auto;
    padding: 0;
    border: 1px solid var(--border);
    border-radius: var(--radius-xl);
    background: var(--surface-card);
    color: var(--fg);
    box-shadow: var(--shadow-4);
    overflow: hidden;
}
.palette::backdrop { background: var(--surface-overlay); backdrop-filter: blur(2px); }
.palette[open] { animation: dialog-in var(--dur) var(--ease-out); }
.palette-input {
    display: flex; align-items: center; gap: var(--s3);
    padding: var(--s3) var(--s4);
    border-bottom: 1px solid var(--border);
}
.palette-input .icon { color: var(--fg-subtle); width: 18px; height: 18px; }
.palette-input input {
    flex: 1 1 auto;
    border: none; outline: none; background: transparent; box-shadow: none;
    font-size: var(--text-lg); padding: 6px 0; color: var(--fg);
}
.palette-input input:focus { box-shadow: none; }
.palette-list { max-height: min(60vh, 460px); overflow: auto; padding: var(--s2); margin: 0; list-style: none; }
.palette-group { padding: var(--s2) var(--s3) 4px; font-size: var(--text-xs); font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--fg-subtle); }
.palette-item {
    display: flex; align-items: center; gap: var(--s3);
    padding: 8px var(--s3);
    border-radius: var(--radius);
    color: var(--fg);
    cursor: pointer;
}
.palette-item:hover { text-decoration: none; }
.palette-item.is-active { background: var(--brand-bg); color: var(--brand-text); }
.palette-item .icon { color: var(--fg-muted); }
.palette-item.is-active .icon { color: var(--brand); }
.palette-item-main { min-width: 0; flex: 1 1 auto; display: flex; flex-direction: column; }
.palette-item-main b { font-weight: 550; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.palette-item-main small { color: var(--fg-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.palette-empty { padding: var(--s6) var(--s4); text-align: center; color: var(--fg-muted); }
.palette-foot {
    display: flex; gap: var(--s4); padding: var(--s2) var(--s4);
    border-top: 1px solid var(--border); background: var(--surface-inset);
    font-size: var(--text-xs); color: var(--fg-subtle);
}

/* ─── Баннер состояния («Всё в порядке» / «Есть проблемы») ─── */
.status-banner {
    display: flex; align-items: center; gap: var(--s4);
    padding: var(--s4) var(--s5);
    margin-bottom: var(--s5);
    border-radius: var(--radius-lg);
    border: 1px solid var(--success-border);
    background: var(--success-bg);
}
.status-banner-ico {
    display: grid; place-items: center;
    width: 40px; height: 40px; border-radius: 50%;
    background: var(--success-solid); color: #fff; flex: 0 0 auto;
}
.status-banner-ico .icon { width: 20px; height: 20px; stroke-width: 2.2; }
.status-banner-main { min-width: 0; flex: 1 1 auto; }
.status-banner-main h2 { margin: 0; font-size: var(--text-lg); }
.status-banner-main p { margin: 2px 0 0; color: var(--fg-muted); max-width: none; }
.status-banner.is-warn { border-color: var(--warning-border); background: var(--warning-bg); }
.status-banner.is-warn .status-banner-ico { background: var(--warning-solid); }
.status-banner.is-danger { border-color: var(--danger-border); background: var(--danger-bg); }
.status-banner.is-danger .status-banner-ico { background: var(--danger-solid); }
.status-banner-issues { margin: var(--s2) 0 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 4px; }
.status-banner-issues li { display: flex; gap: var(--s2); align-items: baseline; font-size: var(--text-base); }
.status-banner-issues li b { white-space: nowrap; }

/* ─── Горизонтальная лента KPI ─── */
.kpi-strip {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 1px;
    background: var(--border);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    overflow: hidden;
    margin-bottom: var(--s5);
    box-shadow: var(--shadow-1);
}
.kpi {
    display: flex; flex-direction: column; gap: 2px;
    padding: var(--s4) var(--s5);
    background: var(--surface-card);
    min-width: 0;
}
.kpi-label { font-size: var(--text-sm); color: var(--fg-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kpi-value { font-size: var(--text-3xl); font-weight: 650; letter-spacing: -.03em; line-height: 1.15; color: var(--fg-strong); font-variant-numeric: tabular-nums; }
.kpi-value small { font-size: var(--text-md); font-weight: 500; color: var(--fg-muted); letter-spacing: 0; }
.kpi-sub { font-size: var(--text-sm); color: var(--fg-subtle); }
.kpi-ok .kpi-value { color: var(--success-text); }
.kpi-warn .kpi-value { color: var(--warning-text); }
.kpi-danger .kpi-value { color: var(--danger-text); }
.kpi a { color: inherit; }

/* ─── Живые карточки кампаний ─── */
.live-list { display: flex; flex-direction: column; gap: var(--s2); }
.live-row {
    display: grid;
    grid-template-columns: auto minmax(0, 1.4fr) minmax(140px, 1fr) auto;
    align-items: center;
    gap: var(--s4);
    padding: var(--s3) var(--s4);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    background: var(--surface-card);
    color: var(--fg);
}
a.live-row:hover { text-decoration: none; border-color: var(--border-strong); background: var(--surface-hover); }
.live-row-main { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.live-row-main b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.live-row-main small { color: var(--fg-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.live-row-progress { display: flex; flex-direction: column; gap: 4px; font-size: var(--text-sm); color: var(--fg-muted); font-variant-numeric: tabular-nums; }
.live-row-state { display: flex; align-items: center; gap: var(--s2); justify-content: flex-end; }
@media (max-width: 760px) {
    .live-row { grid-template-columns: auto minmax(0, 1fr); }
    .live-row-progress, .live-row-state { grid-column: 1 / -1; justify-content: flex-start; }
}

/* ─── Пошаговый мастер ─── */
.stepper {
    display: flex; gap: var(--s1);
    margin: 0 0 var(--s5);
    padding: 0; list-style: none;
    counter-reset: step;
    overflow-x: auto;
}
.stepper li { flex: 1 1 0; min-width: 110px; }
.stepper a, .stepper span.step {
    display: flex; align-items: center; gap: var(--s2);
    padding: var(--s2) var(--s3);
    border-radius: var(--radius);
    color: var(--fg-muted);
    font-size: var(--text-base);
    font-weight: 500;
    white-space: nowrap;
    border-bottom: 2px solid var(--border);
    border-radius: var(--radius) var(--radius) 0 0;
}
.stepper a:hover { text-decoration: none; background: var(--surface-hover); color: var(--fg); }
.stepper .step-num {
    display: inline-grid; place-items: center;
    width: 22px; height: 22px; border-radius: 50%;
    font-size: var(--text-xs); font-weight: 700;
    background: var(--surface-inset); border: 1px solid var(--border-strong); color: var(--fg-muted);
    flex: 0 0 auto;
}
.stepper .is-on a, .stepper .is-on span.step { color: var(--fg-strong); border-bottom-color: var(--brand); font-weight: 600; }
.stepper .is-on .step-num { background: var(--brand); border-color: var(--brand); color: var(--brand-fg); }
.stepper .is-done .step-num { background: var(--success-bg); border-color: var(--success-border); color: var(--success-text); }
.stepper .is-error .step-num { background: var(--danger-bg); border-color: var(--danger-border); color: var(--danger-text); }

/* ─── Полоса качества базы ─── */
.quality-bar {
    display: flex; height: 8px; width: 100%; min-width: 90px;
    border-radius: var(--radius-pill);
    overflow: hidden;
    background: var(--surface-sunken);
}
.quality-bar span { display: block; height: 100%; }
.quality-bar .q-ok { background: var(--success-solid); }
.quality-bar .q-dup { background: var(--neutral-solid); }
.quality-bar .q-bad { background: var(--danger-solid); }
.quality-bar .q-supp { background: var(--warning-solid); }
.quality-bar .q-sent { background: var(--chart-5); }
.quality-legend { display: flex; flex-wrap: wrap; gap: 2px var(--s3); margin-top: 4px; font-size: var(--text-xs); color: var(--fg-muted); }
.quality-legend i { display: inline-block; width: 8px; height: 8px; border-radius: 2px; margin-right: 4px; vertical-align: 0; }

/* ─── Компактные списки (строка = объект) ─── */
.obj-group { margin-bottom: var(--s5); }
.obj-group > summary {
    display: flex; align-items: center; gap: var(--s3);
    padding: var(--s2) var(--s1);
    cursor: pointer;
    list-style: none;
    font-weight: 600;
    color: var(--fg);
    user-select: none;
}
.obj-group > summary::-webkit-details-marker { display: none; }
.obj-group > summary .chev { transition: transform var(--dur) var(--ease); color: var(--fg-subtle); }
.obj-group:not([open]) > summary .chev { transform: rotate(-90deg); }
.obj-group > summary small { color: var(--fg-muted); font-weight: 500; }
.obj-group > summary .spacer { flex: 1 1 auto; }

.obj-list {
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    background: var(--surface-card);
    overflow: hidden;
    box-shadow: var(--shadow-1);
}
.obj-row {
    display: grid;
    grid-template-columns: 28px minmax(0, 2.2fr) minmax(0, 1.2fr) minmax(0, 1fr) auto;
    align-items: center;
    gap: var(--s3);
    padding: 9px var(--s4);
    border-bottom: 1px solid var(--border);
    transition: background var(--dur-fast) var(--ease);
}
.obj-row:last-child { border-bottom: none; }
.obj-row:hover { background: var(--surface-hover); }
.obj-row.is-off { color: var(--fg-subtle); }
.obj-row.is-off .obj-title { text-decoration: line-through; text-decoration-color: var(--border-strong); }
.obj-main { min-width: 0; display: flex; flex-direction: column; gap: 1px; cursor: pointer; }
.obj-title { font-weight: 550; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.obj-sub { font-size: var(--text-sm); color: var(--fg-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.obj-cell { min-width: 0; font-size: var(--text-base); color: var(--fg-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.obj-actions { display: flex; align-items: center; gap: var(--s1); justify-content: flex-end; }
.obj-row .row-hover { opacity: 0; transition: opacity var(--dur-fast) var(--ease); }
.obj-row:hover .row-hover, .obj-row:focus-within .row-hover { opacity: 1; }
@media (hover: none) { .obj-row .row-hover { opacity: 1; } }
@media (max-width: 760px) {
    .obj-row { grid-template-columns: 28px minmax(0, 1fr) auto; }
    .obj-row .obj-cell { display: none; }
}

/* ─── Зона загрузки файла ─── */
.dropzone {
    position: relative;
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--s2);
    padding: var(--s6) var(--s4);
    border: 2px dashed var(--border-strong);
    border-radius: var(--radius-lg);
    background: var(--surface-inset);
    color: var(--fg-muted);
    text-align: center;
    cursor: pointer;
    transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.dropzone:hover, .dropzone.is-over { border-color: var(--brand); background: var(--brand-bg); color: var(--brand-text); }
.dropzone input[type="file"] { position: absolute; inset: 0; opacity: 0; cursor: pointer; }
.dropzone .icon { width: 28px; height: 28px; }
.dropzone b { color: var(--fg); }
.dropzone.has-file { border-style: solid; border-color: var(--success-border); background: var(--success-bg); color: var(--success-text); }

/* ─── «Подробнее» — пояснение, свёрнутое по умолчанию ─── */
.more { margin-top: var(--s2); }
.more > summary {
    display: inline-flex; align-items: center; gap: 4px;
    cursor: pointer; list-style: none;
    font-size: var(--text-sm); color: var(--brand-text); font-weight: 500;
}
.more > summary::-webkit-details-marker { display: none; }
.more[open] > summary { margin-bottom: var(--s2); }
.more > div, .more > p {
    font-size: var(--text-sm); color: var(--fg-muted);
    padding: var(--s3); border-radius: var(--radius); background: var(--surface-inset);
    border: 1px solid var(--border); max-width: var(--measure);
}

/* ─── Пресеты (крупные карточки-радио) ─── */
.preset-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: var(--s3); }
.preset {
    position: relative;
    display: flex; flex-direction: column; gap: 4px;
    padding: var(--s4);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-md);
    background: var(--surface-card);
    cursor: pointer;
    transition: border-color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
}
.preset:hover { border-color: var(--brand); }
.preset input { position: absolute; opacity: 0; pointer-events: none; }
.preset b { font-size: var(--text-md); }
.preset small { color: var(--fg-muted); font-size: var(--text-sm); }
.preset:has(input:checked) { border-color: var(--brand); background: var(--brand-bg); box-shadow: 0 0 0 1px var(--brand); }
.preset:has(input:focus-visible) { box-shadow: var(--focus-ring); }

/* Выбор цвета направления */
.color-pick { display: flex; flex-wrap: wrap; gap: var(--s2); }
.color-pick label { position: relative; cursor: pointer; }
.color-pick input { position: absolute; opacity: 0; }
.color-pick span {
    display: block; width: 26px; height: 26px; border-radius: 50%;
    background: var(--dir); border: 2px solid var(--surface-card); box-shadow: 0 0 0 1px var(--border-strong);
}
.color-pick input:checked + span { box-shadow: 0 0 0 2px var(--surface-card), 0 0 0 4px var(--dir); }
.color-pick input:focus-visible + span { outline: 2px solid var(--brand); outline-offset: 3px; }

/* Глобальная полоса-предупреждение (безопасность) */
.global-banner {
    display: flex; align-items: center; gap: var(--s3);
    padding: 8px var(--content-pad);
    background: var(--danger-bg);
    color: var(--danger-text);
    border-bottom: 1px solid var(--danger-border);
    font-size: var(--text-base);
}
.global-banner a { color: inherit; font-weight: 600; text-decoration: underline; }

/* Таблица-тепловая карта (день × час) */
.heatmap { border-collapse: separate; border-spacing: 3px; font-size: var(--text-xs); color: var(--fg-muted); }
.heatmap th { font-weight: 500; padding: 0 4px; text-align: center; }
.heatmap td { --v: 0; width: 22px; height: 22px; border-radius: 4px; background: var(--surface-sunken); text-align: center; }
.heatmap td[data-v] { background: color-mix(in srgb, var(--brand) calc(var(--v, 0) * 1%), var(--surface-sunken)); }

/* Мелкие утилиты редизайна */
.text-right { text-align: right; }
.gap-2 { gap: var(--s2); }
.mt-0 { margin-top: 0 !important; }
.mb-0 { margin-bottom: 0 !important; }
.w-100 { width: 100%; }
.split-2 { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--s5); }
.split-main-side { display: grid; grid-template-columns: minmax(0, 1fr) 340px; gap: var(--s5); align-items: start; }
.sticky-side { position: sticky; top: calc(var(--appbar-h) + var(--s4)); }
@media (max-width: 1080px) {
    .split-2, .split-main-side { grid-template-columns: minmax(0, 1fr); }
    .sticky-side { position: static; }
}

/* Сброс оформления «документационного» <details> для компонентов,
   которым нужна своя форма: свёрнутое пояснение и группы строк. */
details.more, details.obj-group {
    border: none; background: transparent; padding: 0; margin-bottom: 0;
}
details.obj-group { margin-bottom: var(--s5); }
details.more > summary, details.obj-group > summary {
    border-bottom: none; border-radius: var(--radius); font-size: inherit;
}
details.more > summary { padding: 0; font-size: var(--text-sm); font-weight: 500; color: var(--brand-text); }
details.more > summary:hover, details.obj-group > summary:hover { background: transparent; }
details.more > summary::before { display: none; }
details.obj-group > summary::before { display: none; }
details.more > *:not(summary), details.obj-group > *:not(summary) { margin-left: 0; margin-right: 0; }
details.more > *:not(summary):last-child { margin-bottom: 0; }

/* Короткий список «название + подпись» в боковых карточках хаба */
.dir-mini-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.dir-mini-list li {
    display: flex; flex-direction: column; gap: 1px;
    padding: 7px 0; border-bottom: 1px solid var(--border);
    min-width: 0;
}
.dir-mini-list li:last-child { border-bottom: none; }
.dir-mini-list a { font-weight: 550; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dir-mini-list small { color: var(--fg-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Чек-лист «что нужно для первой рассылки» */
ul.checklist.setup-steps, .card > ul.checklist {
    max-height: none; border: none; padding: 0; background: transparent; list-style: none; margin: 0;
}
.card > ul.checklist li {
    display: flex; align-items: center; gap: var(--s2);
    padding: 8px 0; border-bottom: 1px solid var(--border);
}
.card > ul.checklist li:last-child { border-bottom: none; }
.card > ul.checklist li .icon { color: var(--fg-subtle); }
.card > ul.checklist li.is-done .icon { color: var(--success-solid); }
.card > ul.checklist li.is-done a { color: var(--fg-muted); text-decoration: line-through; }
.card > ul.checklist li .muted { margin-left: auto; }

/* ─── Отправители: панель фильтров и строки ящиков ─── */
.mb-toolbar {
    display: flex; flex-wrap: wrap; align-items: center; gap: var(--s3);
    margin-bottom: var(--s4);
}
.mb-toolbar .search-field { flex: 1 1 260px; max-width: 420px; }
.mb-select-all { margin-left: auto; color: var(--fg-muted); font-size: var(--text-base); }
.mb-row .obj-main { outline: none; border-radius: var(--radius-sm); }
.mb-row .obj-main:focus-visible { box-shadow: var(--focus-ring); }
.mb-row .obj-main:hover .obj-title { color: var(--brand-text); }
.mb-stats { display: flex; flex-direction: column; gap: 1px; font-variant-numeric: tabular-nums; }
.mb-stats .mb-bounce { font-size: var(--text-sm); }
.obj-group > summary a { color: inherit; }
.obj-group > summary .dir-chip { margin-right: 2px; }
.obj-group > summary input[type="checkbox"] { margin: 0; }

.live-row-progress .progress-bar { display: block; margin: 0; height: 6px; }
.live-row-progress .progress-fill, span.progress-fill { display: block; }

/* ─── Уведомления (колокольчик в шапке) ───
   Всё, что панель хочет сказать, — здесь, с уровнем важности. Счётчик —
   только danger + warn; «к сведению» отмечается нейтральной точкой и не
   пугает красным. */
.notif { position: relative; }
.notif-btn { position: relative; }
.notif-btn.is-danger { color: var(--danger-text); }
.notif-btn.is-warn { color: var(--warning-text); }
.notif-badge {
    position: absolute; top: -3px; right: -4px;
    min-width: 16px; height: 16px; padding: 0 4px;
    border-radius: var(--radius-pill);
    font-size: 10px; font-weight: 700; line-height: 16px; text-align: center;
    color: #fff; background: var(--warning-solid);
    box-shadow: 0 0 0 2px var(--surface-card);
}
.notif-btn.is-danger .notif-badge { background: var(--danger-solid); }
.notif-dot {
    position: absolute; top: 5px; right: 5px; width: 7px; height: 7px; border-radius: 50%;
    background: var(--brand); box-shadow: 0 0 0 2px var(--surface-card);
}
.notif-panel {
    position: absolute; right: 0; top: calc(100% + 6px);
    width: min(420px, calc(100vw - 24px));
    max-height: min(70vh, 560px); overflow: auto;
    background: var(--surface-card); color: var(--fg);
    border: 1px solid var(--border); border-radius: var(--radius-lg);
    box-shadow: var(--shadow-4);
    z-index: var(--z-dialog);
    animation: dialog-in var(--dur) var(--ease-out);
}
.notif-head {
    display: flex; align-items: baseline; justify-content: space-between; gap: var(--s3);
    padding: var(--s3) var(--s4); border-bottom: 1px solid var(--border);
    position: sticky; top: 0; background: var(--surface-card);
}
.notif-list { list-style: none; margin: 0; padding: var(--s1) 0; }
.notif-item { display: flex; gap: var(--s3); padding: var(--s3) var(--s4); border-bottom: 1px solid var(--border); }
.notif-item:last-child { border-bottom: none; }
.notif-ico { flex: 0 0 auto; padding-top: 1px; color: var(--fg-subtle); }
.notif-item.is-danger .notif-ico { color: var(--danger-solid); }
.notif-item.is-warn .notif-ico { color: var(--warning-solid); }
.notif-item.is-info .notif-ico { color: var(--brand); }
.notif-main { min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.notif-main b { font-weight: 600; }
.notif-main p { margin: 0; color: var(--fg-muted); font-size: var(--text-base); max-width: none; }
.notif-link { display: inline-flex; align-items: center; gap: 4px; font-size: var(--text-sm); font-weight: 500; margin-top: 2px; }
details.notif-more { border: none; background: transparent; margin: 0; }
details.notif-more > summary { padding: 0; font-size: var(--text-sm); font-weight: 500; color: var(--brand-text); border: none; }
details.notif-more > summary::before { display: none; }
details.notif-more > summary:hover { background: transparent; text-decoration: underline; }
details.notif-more > p { margin: 4px 0 0 !important; font-size: var(--text-sm); }
.notif-empty { display: flex; align-items: center; gap: var(--s2); padding: var(--s5) var(--s4); color: var(--fg-muted); }
.notif-empty .icon { color: var(--success-solid); }
