/* Интерфейс сотрудника.

   Правило цвета: акцент — синий, он для действий и ссылок.
   Красный, оранжевый и зелёный зарезервированы под состояние сроков.
   Если красить кнопки оранжевым, «просрочено» перестанет читаться как тревога.

   Чёрно-золотая тема под логотип фирмы пробовалась 21.08.2026
   и откачена в тот же день решением заказчика: прежняя лучше. */

:root {
    --sidebar-bg: #1b2436;
    --sidebar-bg-hover: #263149;
    --accent: #2563eb;
    --accent-dark: #1d4ed8;
    --accent-soft: #eff4ff;
    /* Фон шапки карточки. Отдельно от --accent-soft: тот занят подсветкой
       фокуса и панелью с кодом доступа. Шапка заметно темнее их — иначе
       синяя панель внутри карточки сливается с синей шапкой над ней. */
    --head-bg: #d5e3fb;
    --head-border: #aec8f0;

    --danger: #d92d20;
    --danger-soft: #fef3f2;
    --warn: #b54708;
    --warn-soft: #fffaeb;
    --ok: #067647;
    --ok-soft: #ecfdf3;
    /* Зона перетаскивания файлов. Не --ok-soft: тот даёт 1,05:1 к белой
       карточке — на глаз это тот же белый, и зона снова теряется, как
       терялась серая (заказчик, 26.08.2026). Здесь 1,15:1 — зелёное
       читается как зелёное, но остаётся фоном, а не сообщением. */
    --drop-bg: #dcf5e7;
    --drop-bg-over: #c3eed6;
    --drop-border: #79c9a1;
    --drop-text: #1f5a41;

    --text: #101828;
    --text-muted: #667085;
    /* Замер 22.08.2026: прежний #98a2b3 давал 2,58:1 на белом при норме
       WCAG AA 4,5 — чуть больше половины. Им набраны «не требуется»
       в колонке заверения, даты дорожки и подписи в свёрнутых блоках,
       то есть 19 узлов на одной карточке дела. Новый — 4,6:1.
       Иерархия с --text-muted (5,3:1) сохраняется, но становится тоньше:
       faint теперь настолько светлый, насколько вообще разрешено. */
    --text-faint: #6b7688;
    /* На тёмном фоне меню шкала другая: там светлее значит контрастнее.
       --text-muted давал на нём 3,1:1, поэтому у сайдбара свой приглушённый. */
    --sidebar-muted: #98a2b3;
    --border: #e4e7ec;
    --border-strong: #d0d5dd;
    --bg: #f7f8fa;
    --surface: #ffffff;

    --radius: 10px;
    --radius-sm: 6px;
    /* Списки «подпись — значение» (.kv и строки оплаты) считались порознь:
       120 px против 80, зазор 16 против 10 — и значения в соседних карточках
       правой колонки начинались в 46 px друг от друга (замер 26.08.2026,
       замечание заказчика). Одно число на оба списка. */
    --kv-label: 150px;
    --kv-gap: 16px;
    /* Боковое поле бейджа. Отсюда же берётся сдвиг, которым текст в бейдже
       ставится на одну линию с обычными значениями. */
    --badge-pad: 9px;
    /* Тень заметная: карточки на странице дела стоят стопкой, и при едва
       видимой тени сливались в одну массу (замечание заказчика 22.08.2026). */
    --shadow: 0 1px 3px rgba(16, 24, 40, .14), 0 6px 18px rgba(16, 24, 40, .18);
    --sidebar-w: 280px;
    /* Шрифт интерфейса. Переменной — потому что на листе письма рядом
       живёт шрифт самого письма, и подписи блоков должны остаться
       интерфейсом, а не частью документа. */
    --font: -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}

* { box-sizing: border-box; }

/* Атрибут hidden обязан работать поверх любых display-правил: .hint-strip
   с display:flex уже показывал «спрятанную» полосу пустой. Тот же случай
   раньше чинился точечно для .panel[hidden]. */
[hidden] { display: none !important; }

body {
    margin: 0;
    background: var(--bg);
    color: var(--text);
    font: var(--fs-md)/1.5 var(--font);
    -webkit-font-smoothing: antialiased;
}

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

/* ---------- Каркас ---------- */

.layout { display: flex; min-height: 100vh; }

.sidebar {
    width: var(--sidebar-w);
    flex: 0 0 var(--sidebar-w);
    background: var(--sidebar-bg);
    color: #cdd5e0;
    display: flex;
    flex-direction: column;
    position: sticky;
    top: 0;
    height: 100vh;
}

.sidebar__brand {
    padding: 16px 18px 12px;
    border-bottom: 1px solid rgba(255, 255, 255, .07);
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 4px;
}
/* Логотип фирмы — крупно по центру, имя под ним: мелкий кружок в строку
   было не разглядеть. Размеры фиксированы: битая или огромная картинка
   не должна разваливать шапку — object-fit сохраняет пропорции.
   Круглой обрезки больше нет: белая подложка срезается при загрузке файла
   (logo_without_background), логотип лежит на тёмном фоне как есть. */
.sidebar__logo {
    /* 140px при кегле 16 не оставляли меню места: девять пунктов по 44px
       плюс подписи групп — 542px, а под них на экране 900px оставалось 507,
       и в меню появлялась полоса прокрутки (замер 04.09.2026). */
    width: 112px;
    height: 112px;
    object-fit: contain;
    margin-bottom: 4px;
}
.portal__logo { width: 40px; height: 40px; object-fit: contain; flex: 0 0 auto; }
.portal__brand-wrap { display: flex; align-items: center; gap: 10px; }
.portal-login__brand {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    font-weight: 650;
    font-size: var(--fs-lg);
    margin-bottom: 14px;
}
/* Логотип здесь — главный элемент, а не украшение: он опознаёт фирму
   раньше, чем прочитан заголовок. Прежние 104px терялись в тёмном поле,
   168px читались как иконка. Растёт вместе с экраном; потолок — чтобы
   на 4K он не выдавил подпись за нижний край. */
.login__logo {
    /* Размер считается и от ширины, и от ВЫСОТЫ окна. Только по ширине
       получалось так: на 1920×620 логотип брал 518px, страница вырастала
       до 798px, и до кнопки «Войти» приходилось прокручивать — на экране
       входа это недопустимо. `min()` берёт меньшее из двух ограничений. */
    width: clamp(200px, min(27vw, 50vh), 520px);
    height: clamp(200px, min(27vw, 50vh), 520px);
    object-fit: contain;
    margin: 0 auto 30px;
    display: block;
}
/* text-wrap: balance — две строки названия примерно равны, а не «длинная
   и огрызок»; форма «Sp. z o.o.» склеена неразрывными пробелами на сервере. */
.sidebar__brand-name { color: #fff; font-weight: 650; font-size: var(--fs-lg); letter-spacing: .2px; text-wrap: balance; }
.sidebar__brand-sub { color: var(--sidebar-muted); font-size: var(--fs-sm); margin-top: 2px; }

.sidebar__user {
    padding: 12px 18px;
    border-bottom: 1px solid rgba(255, 255, 255, .07);
}
.sidebar__user-name { color: #fff; font-size: var(--fs-md); font-weight: 550; }
.sidebar__user-role { color: var(--sidebar-muted); font-size: var(--fs-sm); margin-top: 1px; }

.nav { padding: 8px 8px; flex: 1; overflow-y: auto; scrollbar-width: thin; }

/* Узкий экран: меню из колонки становится полосой сверху.

   До 22.08.2026 ни один медиазапрос не трогал .sidebar, и она держала свои
   232px на любой ширине: при 768px странице оставалось 465px и она уезжала
   вбок на 388, при 375px — контенту доставалось 143px и уезжало на 766.
   Мобильное приложение по-прежнему отложено (CLAUDE.md), но 768px — это
   планшет, с которого дело открывают в urzędzie, а не телефон.

   Полоса, а не выдвижная панель: гамбургер требует JS и состояния,
   а здесь достаточно, чтобы пункты перестали быть колонкой. */
@media (max-width: 1000px) {
    .layout { flex-direction: column; }
    .sidebar {
        width: 100%;
        flex: none;
        height: auto;
        position: static;
        flex-direction: row;
        flex-wrap: wrap;
        align-items: center;
        gap: 0 8px;
        padding-right: 12px;
    }
    .sidebar__brand {
        flex-direction: row;
        gap: 10px;
        text-align: left;
        border-bottom: 0;
        padding: 10px 14px;
    }
    .sidebar__brand-sub { display: none; }
    .nav {
        display: flex;
        flex-wrap: nowrap;
        align-items: center;
        gap: 2px;
        padding: 6px 4px;
        overflow-y: visible;
        /* В строку с прокруткой, а не в перенос: девять пунктов переносом
           дают девять рядов и 411px полосы — половину экрана планшета. */
        overflow-x: auto;
        scrollbar-width: thin;
    }
    .nav__item {
        flex: 0 0 auto;
        margin-bottom: 0;
        white-space: nowrap;
    }
    /* Подписи групп в строке только мешают: они разделяли колонку. */
    .nav__caption { display: none; }
    .nav__item { padding: 7px 10px; }
    .sidebar__foot { padding: 0 6px; margin-left: auto; }
    /* Шапка перестаёт липнуть: липких полос две подряд — это половина
       экрана планшета, занятая ничем. */
    .topbar { position: static; }
    .content { padding: 18px 16px 40px; }
}


/* Шапка окна на «Сегодня»: стрелки, период, переключатель шага. */
.period-bar { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; justify-content: space-between; }
.period-bar__nav { display: flex; align-items: center; gap: 8px; }
.period-bar__label { font-weight: 650; font-size: var(--fs-lg); }
.period-bar__spans { display: flex; gap: 6px; }
.day__head {
    padding: 10px 18px 6px;
    font-weight: 650;
    font-size: var(--fs-md);
    border-top: 1px solid var(--border);
}
.day:first-of-type .day__head { border-top: none; }
.state-tier__title {
    margin: 26px 0 12px;
    font-size: var(--fs-sm);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .5px;
    color: var(--text);
}
.nav__item {
    display: flex;
    /* Иконка держится первой строки, а не середины пункта: подпись длиннее
       210px переносится (польское «Kompletowanie dokumentów» — 217), и
       центрированная иконка повисала между строками (заказчик, 05.09.2026). */
    align-items: flex-start;
    gap: 10px;
    padding: 8px 12px;
    border-radius: var(--radius-sm);
    color: #cdd5e0;
    font-size: var(--fs-md);
    margin-bottom: 2px;
}
.nav__item:hover { background: rgba(255, 255, 255, .06); color: #fff; text-decoration: none; }
.nav__item--active { background: var(--accent); color: #fff; font-weight: 550; }
.nav__item--active:hover { background: var(--accent-dark); }
.nav__item svg { width: 20px; height: 20px; flex: 0 0 20px; margin-top: 2px; }
.nav__count {
    margin-left: auto;
    background: var(--danger);
    color: #fff;
    font-size: var(--fs-xs);
    font-weight: 650;
    padding: 1px 7px;
    border-radius: 999px;
}
.nav__item--active .nav__count { background: rgba(0, 0, 0, .28); }

.sidebar__foot { padding: 12px 16px; border-top: 1px solid rgba(255, 255, 255, .07); }
.sidebar__foot a { color: #7d8aa0; font-size: var(--fs-sm); }
.sidebar__foot a:hover { color: #cdd5e0; }
.sidebar__logout {
    background: none;
    border: 0;
    padding: 0;
    color: var(--sidebar-muted);
    font: inherit;
    font-size: var(--fs-sm);
    cursor: pointer;
}
.sidebar__logout:hover { color: #cdd5e0; text-decoration: underline; }

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

.topbar {
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    padding: 16px 28px;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px 16px;
    position: sticky;
    top: 0;
    z-index: 5;
}
.topbar__title { font-size: var(--fs-xl); font-weight: 650; margin: 0; }
.topbar__sub { color: var(--text-muted); font-size: var(--fs-md); margin-top: 2px; }
.topbar__right { margin-left: auto; display: flex; flex-wrap: wrap; justify-content: flex-end; align-items: center; gap: 8px 14px; }
/* Блок заголовка берёт столько, сколько занимает его текст, но не больше
   42 % строки: длинная подстрока (приёмка документа) сворачивается в две
   строки, а «Сегодня» не претендует на лишнее. Правая часть остаётся
   на той же строке, пока ей хватает остатка, иначе переносится целиком
   (карточка клиента при 1400px: пять кнопок, поиск и дата уезжали за край
   на 344px, замер 04.09.2026). Основа 360px, стоявшая здесь сначала,
   переносила правую часть даже у «Сегодня». */
.topbar > :first-child { flex: 0 1 auto; min-width: 0; max-width: 42%; }
.topbar__date { color: var(--text-muted); font-size: var(--fs-md); text-align: right; white-space: nowrap; }
/* День недели — только на широком экране: с переключателем языка шапка
   «Сегодня» при 1400px иначе переносится на две строки (замер 05.09.2026). */
@media (max-width: 1600px) { .topbar__weekday { display: none; } }

/* Поиск по документам — в верхней панели, на каждой странице. Это действие,
   а не раздел: в меню он стоял между «Сегодня» и «Работа» и выглядел чужим.
   На странице поиска не рисуется — там своя форма. */
.topbar__search { position: relative; display: flex; align-items: center; }
.topbar__search-icon {
    position: absolute; left: 12px; width: 17px; height: 17px;
    color: var(--text-muted); pointer-events: none;
}
.topbar__search-input {
    width: 240px;
    padding: 9px 12px 9px 36px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border);
    background: var(--bg);
    color: var(--text);
    font: inherit;
    font-size: var(--fs-md);
    transition: width .15s ease;
}
.topbar__search-input:focus { outline: none; border-color: var(--accent); background: var(--surface); width: 340px; }
@media (max-width: 900px) { .topbar__search-input { width: 160px; } .topbar__search-input:focus { width: 200px; } }

/* На телефоне шапка в одну строку не помещается: заголовок, поиск на 160px
   и дата вместе выносили страницу за экран на 46px — то самое переполнение,
   которое 22.08 свели к нулю на трёх ширинах, а поиск в шапке появился
   в тот же день уже ПОСЛЕ замера. Ниже 640px шапка переносится, поиск
   занимает остаток строки. Прятать его нельзя: на всех страницах, кроме
   самого поиска, это единственный вход в него. */
@media (max-width: 640px) {
    .topbar { flex-wrap: wrap; }
    .topbar__right { margin-left: 0; width: 100%; gap: 10px; }
    .topbar__search { flex: 1; min-width: 0; }
    .topbar__search-input,
    .topbar__search-input:focus { width: 100%; }
}

/* Ширину не ограничиваем: на широком мониторе потолок оставлял пустую
   полосу справа. Читаемость держится не потолком страницы, а шириной
   отдельных блоков — см. .form-page и .cols. */
.content { padding: 24px 28px 48px; }

/* Формы не растягиваем во всю ширину: строка ввода в 1800 px не читается.
   Но и прижимать их к левому краю незачем — на широком экране справа
   оставалась пустая треть, и карточка выглядела оборванной. Предел
   поднят и блок центрируется: сетка на 12 колонок раскладывается ровно,
   а поля не превращаются в километровые строки. */
/* Форма ограничена по ширине для читаемости, но прижата к левому краю,
   а не отцентрована (заказчик, 26.08.2026: «почему всё по середине»).
   Отцентрованная карточка начиналась в 391 px, когда полоса вкладок над
   ней начиналась в 260, — и страница выглядела разъехавшейся. Общий левый
   край держит вертикаль на всех экранах. */
.form-page { max-width: 1440px; }

/* ---------- Сообщения ---------- */

.messages { margin-bottom: 20px; }
.message {
    padding: 12px 16px;
    border-radius: var(--radius-sm);
    font-size: var(--fs-md);
    border: 1px solid transparent;
    margin-bottom: 8px;
}
.message--success { background: var(--ok-soft); color: var(--ok); border-color: #abefc6; }
.message--warning { background: var(--warn-soft); color: var(--warn); border-color: #fedf89; }
.message--error { background: var(--danger-soft); color: var(--danger); border-color: #fecdca; }
/* Информационное — синим: акцент свободен, он не занят состояниями сроков.
   Без этого правила десять вызовов messages.info выводились текстом
   на фоне страницы, в том числе рассказ о выученном якоре на приёмке —
   ровно то сообщение, которое не должно быть сюрпризом. */
.message--info { background: var(--accent-soft); color: var(--accent-dark); border-color: #c7d7f5; }

/* ---------- Очередь на сегодня ----------
   Одна лента вместо шести одинаковых карточек: группа задаётся заголовком
   и цветной полосой слева, строка делится на две зоны — «что и по кому»
   слева, «срок и действие» справа. Шесть колонок таблицы взгляду не за что
   зацепиться, две — читаются по диагонали. */

.queue { list-style: none; margin: 0; padding: 0; }

.queue__group-title {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 11px 18px;
    background: #f8f9fb;
    border-top: 1px solid var(--border);
    border-bottom: 1px solid var(--border);
    font-size: var(--fs-xs);
    font-weight: 680;
    text-transform: uppercase;
    letter-spacing: .6px;
    color: var(--text-muted);
}
.queue__group-title:first-child { border-top: none; }
.queue__group-title .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--border-strong); }
.queue__group-title .count {
    margin-left: auto;
    font-size: var(--fs-sm);
    letter-spacing: 0;
    text-transform: none;
    font-weight: 550;
}
.queue__group--overdue .dot { background: var(--danger); }
.queue__group--overdue { color: var(--danger); }

.queue__row {
    display: flex;
    align-items: center;
    gap: 18px;
    padding: 14px 18px 14px 15px;
    border-bottom: 1px solid var(--border);
    border-left: 3px solid transparent;
}
.queue__row:hover { background: #fafbfc; }
.queue__row--overdue { border-left-color: var(--danger); background: #fffbfa; }
.queue__row--overdue:hover { background: #fff5f4; }
.queue__row--call { border-left-color: var(--border-strong); }

.queue__main { min-width: 0; flex: 1; }
.queue__name { font-size: var(--fs-lg); font-weight: 600; }
.queue__meta { color: var(--text-muted); font-size: var(--fs-sm); margin-top: 3px; }
.queue__meta a { color: var(--text-muted); text-decoration: underline; text-underline-offset: 2px; }
.queue__meta a:hover { color: var(--accent); }
.queue__right { display: flex; align-items: center; gap: 12px; flex: 0 0 auto; }
.queue__deadline { min-width: 130px; text-align: right; }
/* Мета-строка не переносится: три строки под названием превращают ленту
   в стену текста, ради которой всё и переделывалось. */
.queue__meta { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ---------- Компактные панели правой колонки ---------- */

.panel-list { list-style: none; margin: 0; padding: 0; }
.panel-list li { padding: 11px 18px; border-bottom: 1px solid var(--border); font-size: var(--fs-md); }
.panel-list li:last-child { border-bottom: none; }
.panel-list__title { font-weight: 550; }
.panel-list__meta { color: var(--text-muted); font-size: var(--fs-sm); margin-top: 2px; }

/* ---------- Формы ---------- */

.control {
    width: 100%;
    padding: 8px 11px;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    font: inherit;
    font-size: var(--fs-md);
    background: #fff;
    color: var(--text);
}
.control:focus { outline: 2px solid var(--accent-soft); border-color: var(--accent); }
textarea.control { resize: vertical; }

/* Нативный `select` не переносит текст и не сокращает его сам: пункт, который
   не влез, обрезается по букве — «Вызов на собеседован». Многоточие говорит,
   что текст длиннее поля, а целиком он виден в раскрытом списке. Ширину
   этим не чинят: поле, где обрезается каждый пункт, надо расширять
   (`span` в сетке), а многоточие — страховка на длинный пункт-исключение. */
select.control { text-overflow: ellipsis; }

/* Строка «сейчас лежит такой файл» над полем загрузки. Имя ломается по
   любому месту: одно длинное слово без пробелов иначе распирает ячейку
   изнутри, и поле загрузки под ним считает свои 100% уже от неё —
   так «Файл шаблона» вылезал на 96px за край карточки. */
/* Превью загруженной картинки (логотип, подпись): на сером, чтобы белый
   PNG с прозрачным фоном не сливался с карточкой. */
.form__filepreview {
    display: inline-block;
    align-self: flex-start;   /* колонка flex иначе тянет блок на всю ширину */
    width: fit-content;
    margin-bottom: 8px;
    padding: 8px;
    border: 1px solid var(--border);
    border-radius: 6px;
    background: var(--bg-soft, #f3f4f6);
}
.form__filepreview img { display: block; max-height: 90px; max-width: 260px; }

.cell-facts { color: var(--text); font-variant-numeric: tabular-nums; }

.form__filenow {
    font-size: var(--fs-sm);
    color: var(--text-muted);
    margin-bottom: 6px;
    overflow-wrap: anywhere;
}
.form__check--inline { display: inline-flex; gap: 5px; align-items: center; margin-left: 8px; }

/* Сетка на 12 колонок, а не auto-fit.

   auto-fit раскладывал поля по фактической ширине, и число колонок гуляло
   от строки к строке: четыре поля, потом три, потом пять. Выглядело как
   каша, и глазу не за что было зацепиться при заполнении. Двенадцать
   колонок дают ровные ряды и позволяют задать ширину по смыслу: «дом»
   не должен быть шириной с «улицу».

   Отступы сжаты с 18 до 12/14: поля одной карточки — это одна мысль,
   и разносить их на два сантиметра незачем. */
.form__grid {
    display: grid;
    grid-template-columns: repeat(12, minmax(0, 1fr));
    gap: 14px 12px;
    align-items: start;

    /* Сетка меряет себя, а не окно. Форма живёт в колонке шириной 300px
       при окне 1280 — по ширине окна ни один перелом не срабатывал,
       и поле выходило 57px. Текст в такое поле ещё влезает, а нативный
       `input[type=date]` не сжимается ниже ~132px и просто вылезал
       за край карточки: «Действует с» торчал на 75px. */
    container-type: inline-size;
}
.form__field {
    display: flex;
    flex-direction: column;
    gap: 4px;
    grid-column: span 3;
    min-width: 0;
}
/* Выпадающему списку — треть строки, а не четверть.

   Ширину `select` определяет самый длинный пункт, а не введённое значение:
   в поле ввода длинный текст прокручивается, в списке — обрезается по букве.
   Пункты здесь длинные по существу («Заявление подано клиентом в MOS»,
   «Dolnośląski Urząd Wojewódzki we Wrocławiu»), и четверти строки им мало.

   Обёрнуто в `:where()` не для красоты: `:has(select)` берёт специфичность
   своего аргумента, то есть считается за класс + тег и перебивает
   `.form__field--span-6` — явная ширина из шаблона переставала работать
   («Тип события» просил половину строки и получал треть). `:where()`
   обнуляет вклад, дальше решает порядок правил, и явный `span` побеждает. */
.form__field:where(:has(select)) { grid-column: span 4; }

/* Полю выбора файла — половина строки. Кнопка «Выберите файл» с подписью
   рядом имеет собственный неснижаемый размер (~246px), и в четверти строки
   она вылезала за край ячейки. Над ним ещё строка «сейчас лежит такой файл». */
.form__field:where(:has(input[type="file"])) { grid-column: span 6; }

.form__field--span-2 { grid-column: span 2; }
.form__field--span-4 { grid-column: span 4; }
.form__field--span-6 { grid-column: span 6; }
.form__field--wide { grid-column: 1 / -1; }

/* В узкой сетке двенадцать колонок превращаются в шесть, потом в одну:
   поле в 1/12 ширины боковой колонки — это не поле.

   Порог 720px, а не 620: 620 был посчитан от даты — самого несжимаемого
   поля (132px), и он честно отвечал на вопрос «влезет ли дата». Но форма
   в двух колонках (справочники писем и шаблонов .docx) даёт сетку 634px,
   то есть ячейку 150px: дата влезает, а «— любой в воеводстве —» уже нет.
   720px закрывает и это: ниже порога поле занимает половину строки.
   380px: половина строки — 184px, дата влезает. Ниже — одна колонка. */
@container (max-width: 1080px) {
    .form__field--span-2:has(input[type="date"]) { grid-column: span 3; }
}
@container (max-width: 800px) {
    .form__field, .form__field--span-2,
    .form__field--span-4, .form__field--span-6 { grid-column: span 6; }
    /* Кнопка выбора файла не сжимается ниже своих ~246px: в половине узкой
       строки она вылезала за край. Целая строка — единственное, что ей
       остаётся отдать. Здесь `:has` уже без `:where`: в узкой сетке это
       правило должно побеждать и явные `span` из шаблонов. */
    .form__field:has(input[type="file"]) { grid-column: 1 / -1; }
    /* «Широкое» поле — это вся строка и в узкой сетке (11.09.2026). Правило
       `.form__field` выше стоит позже `.form__field--wide` при той же
       специфичности и отдавало тексту половину строки: у шаблона уведомления
       текст сообщения жил в колонке 289px рядом с галочкой «Активен». */
    .form__field--wide { grid-column: 1 / -1; }
}
@container (max-width: 420px) {
    .form__field, .form__field--span-2,
    .form__field--span-4, .form__field--span-6 { grid-column: 1 / -1; }
}

/* Поле файла. Нативное «Выберите файл · Файл не выбран» — единственный
   контрол, оставшийся неоформленным (заказчик, 26.08.2026: «почему кнопки
   не стилизированы»): класс `control` ему не помогает, вид кнопки внутри
   поля задаётся отдельным псевдоэлементом. */
input[type="file"] {
    width: 100%;
    padding: 6px 8px;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    background: var(--surface);
    font-size: var(--fs-md);
    color: var(--text-muted);
}
input[type="file"]:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-soft);
}
input[type="file"]::file-selector-button {
    margin-right: 10px;
    padding: 5px 12px;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    background: var(--surface);
    color: var(--text);
    font: inherit;
    font-size: var(--fs-sm);
    font-weight: 550;
    line-height: 1.4;
    cursor: pointer;
}
input[type="file"]::file-selector-button:hover { background: #f2f4f7; }

/* Знак подсказки у подписи. Сама подсказка — в title поля и здесь же:
   без метки о её существовании никто бы не догадался. */
.form__help-mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 14px;
    height: 14px;
    margin-left: 4px;
    border-radius: 50%;
    background: var(--border);
    color: var(--text-muted);
    font-size: var(--fs-xs);
    font-weight: 700;
    cursor: help;
    vertical-align: middle;
}
.form__help-mark:hover { background: var(--accent); color: #fff; }
.form__field-head { display: flex; align-items: flex-end; }
.form__field-body { display: flex; flex-direction: column; gap: 5px; }

/* Выравнивание полей по строке.
   Подписи разной высоты («Категория» в одну строку, «Максимальный возраст
   документа» в две) иначе сдвигают поля ввода по вертикали, и ряд выглядит
   кривым. Subgrid отдаёт всем полям строки общие дорожки: подписи растут
   вниз до общей базы, поля ввода начинаются на одном уровне. */
@supports (grid-template-rows: subgrid) {
    .form__field {
        display: grid;
        grid-template-rows: subgrid;
        grid-row: span 2;
        gap: 5px;
        align-content: start;
    }
    /* Чекбокс стоит один в своей строке — дорожки подписи ему не нужны. */
    .form__field--check { grid-row: auto; display: flex; flex-direction: column; gap: 5px; }
    /* Поле, собранное в шаблоне руками (подпись, поле, подсказка — три
       ребёнка на две дорожки): лишнему ребёнку места в subgrid нет, и браузер
       кладёт его в последнюю дорожку поверх поля ввода — так подсказка легла
       на выбранного клиента (снимок заказчика 10.09.2026). Такое поле идёт
       колонкой без общих дорожек: криво по строке лучше, чем текст на тексте. */
    .form__field:has(> :nth-child(3)) { grid-row: auto; display: flex; flex-direction: column; gap: 5px; }
}
.form__label { font-size: var(--fs-sm); font-weight: 550; color: #344054; }
.form__hint { font-size: var(--fs-sm); color: var(--text-muted); }
.form__errors { font-size: var(--fs-sm); color: var(--danger); }
.form__check { display: flex; gap: 9px; align-items: flex-start; }
.form__check input { margin-top: 3px; }

/* Список галочек (CheckboxSelectMultiple): Django рисует его вложенными div,
   поэтому стилизуем по содержимому, а не по классу. */
.form__field-body > div > div,
.form__field-body > ul > li { list-style: none; }
.form__field-body input[type="checkbox"] + label,
.form__field-body label > input[type="checkbox"] { margin-right: 7px; }
.form__field-body > div > div,
.form__field-body > ul { margin: 0; padding: 0; }
.form__field-body > div > div { padding: 3px 0; font-size: var(--fs-md); }
.form__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    align-items: center;
    padding: 16px 18px;
    border-top: 1px solid var(--border);
    background: #fafbfc;
}
.form__nonfield { margin-bottom: 16px; }

.page-actions { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }

/* ---------- Вкладки справочников ---------- */

.tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 2px;
    border-bottom: 1px solid var(--border);
    margin-bottom: 20px;
}
.tabs a {
    padding: 9px 14px;
    font-size: var(--fs-md);
    color: var(--text-muted);
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
}
.tabs a:hover { color: var(--text); text-decoration: none; }
.tabs a.is-active { color: var(--accent); border-bottom-color: var(--accent); font-weight: 600; }

/* Второй ряд навигации настроек: пункты текущей группы. Тоньше верхнего
   ряда — он про раздел, этот про экран внутри него. */
.subtabs {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 14px;
    margin: -8px 0 20px;
}
.subtabs a {
    font-size: var(--fs-md);
    color: var(--text-muted);
    padding: 4px 0;
}
.subtabs a:hover { color: var(--text); text-decoration: none; }
.subtabs a.is-active { color: var(--text); font-weight: 600; }

/* ---------- Инлайн-редактор пунктов пакета ---------- */

/* Ширины колонок задаются, а не выторговываются.

   В auto-раскладке браузер при нехватке места отбирает её у колонки,
   которой ширину не назначили, — и это оказывалась самая длинная:
   в адресах «Улица» ужималась до 63px, а «Дом» рядом держал сотню.
   Список «Тип» доходил до 46px и обрезал «Проживание» по букве.

   `fixed` раздаёт ровно то, что написано в `<th>`, а не влезшее уезжает
   в горизонтальную прокрутку `.table-wrap` — она вокруг этих таблиц уже
   есть, но при `width: 100%` не включалась никогда: таблица послушно
   сжималась вместо того, чтобы вылезти. `min-width` — та ширина, ниже
   которой строка адреса перестаёт читаться. */
.formset { width: 100%; border-collapse: collapse; table-layout: fixed; min-width: 780px; }
.formset th {
    text-align: left;
    font-size: var(--fs-xs);
    text-transform: uppercase;
    letter-spacing: .4px;
    color: var(--text-muted);
    padding: 9px 10px;
    background: #fafbfc;
    border-bottom: 1px solid var(--border);
}
.formset td { padding: 9px 10px; border-bottom: 1px solid var(--border); vertical-align: top; }
.formset td .control { min-width: 0; }
.formset .col-narrow { width: 90px; }
.formset .col-check { width: 90px; text-align: center; }
.formset__errors { color: var(--danger); font-size: var(--fs-sm); margin-top: 4px; }
/* Ошибка всей строки: относится к паре полей, поэтому стоит над строкой,
   а не в ячейке одного из них. */
.formset__rowerror td { border-bottom: 0; padding-bottom: 0; }
.formset__rowerror .formset__errors { margin-top: 0; }

/* Подпись группы в меню: «Система» отделяет ежедневную работу от того,
   что правят раз в месяц. Разделение по ритму использования, не по типу. */
.nav__caption {
    /* Линия во всю ширину меню над подписью группы: без неё «Работа»
       и «Система» читались строкой между пунктами, а не заголовком
       (заказчик, 04.09.2026). Подпись стоит на отступе пункта. */
    margin: 10px 0 4px;
    padding: 10px 12px 0;
    border-top: 1px solid rgba(255, 255, 255, .1);
    font-size: var(--fs-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .7px;
    color: var(--sidebar-muted);
}

/* Полоска поступлений за месяц. Синяя, а не красная/оранжевая:
   те заняты состоянием сроков, а деньги — не тревога. */
.finance-bar {
    height: 14px;
    min-width: 2px;
    border-radius: 3px;
    background: var(--accent, #2f6fed);
    opacity: .75;
}
.finance-bar--expense { background: var(--warn); }
.finance-negative { color: var(--danger); }

/* Парные столбики прихода и расхода. SVG, не canvas: печатается на бумагу
   и работает без JS; геометрия посчитана во вьюхе. */
.chart-scroll { overflow-x: auto; }
/* По ширине карточки, а не 64px на месяц (06.09.2026): два столбика
   в пустой карточке на 1900px. viewBox не короче года, масштаб
   ограничен сверху — подписи не должны становиться плакатом. */
.finance-chart { display: block; width: 100%; max-width: 1150px; height: auto; }
.finance-chart__income { fill: var(--accent); opacity: .8; }
.finance-chart__expense { fill: var(--warn); opacity: .8; }
.finance-chart__label { font-size: 10px; fill: var(--text-muted); }
.finance-chart__value { font-size: 9px; fill: var(--text); }
.finance-chart__value--expense { fill: var(--warn); }
.chart-legend { display: flex; gap: 16px; margin-top: 8px; font-size: var(--fs-sm); color: var(--text-muted); }
.chart-legend__item { display: inline-flex; align-items: center; gap: 6px; }
.chart-legend__dot { width: 10px; height: 10px; border-radius: 2px; display: inline-block; }
.chart-legend__dot--income { background: var(--accent); }
.chart-legend__dot--expense { background: var(--warn); }

/* Главная плитка финансов — остаток. */
.tile--main .tile__value { font-size: var(--fs-2xl); }
.filters__presets .btn { margin-right: 6px; }

/* ---------- Просмотр файла поверх страницы ---------- */

/* Окно занимает почти весь экран: скан A4 в маленькой рамке нечитаем,
   а ради «посмотреть, тот ли это документ» превью и заводилось. */
.preview[hidden] { display: none; }
.preview {
    position: fixed;
    inset: 0;
    z-index: 100;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
}
.preview__backdrop { position: absolute; inset: 0; background: rgba(17, 24, 39, .55); }
.preview__box {
    position: relative;
    display: flex;
    flex-direction: column;
    width: min(1100px, 100%);
    height: min(92vh, 100%);
    background: var(--card-bg, #fff);
    border-radius: 10px;
    overflow: hidden;
    box-shadow: 0 18px 50px rgba(17, 24, 39, .35);
}
.preview__head {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 14px;
    background: var(--head-bg);
    border-bottom: 1px solid var(--border);
}
.preview__title {
    flex: 1;
    min-width: 0;
    margin: 0;
    font-size: var(--fs-lg);
    font-weight: 600;
    /* Длинное название документа не должно расталкивать кнопки. */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.preview__actions { display: flex; gap: 8px; flex: 0 0 auto; }
.preview__close { padding-left: 12px; padding-right: 12px; }
.preview__body {
    flex: 1;
    min-height: 0;
    background: #f3f4f6;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: auto;
}
.preview__frame { width: 100%; height: 100%; border: 0; }
/* Картинка вписывается целиком: скан открывают, чтобы увидеть документ,
   а не левый верхний угол в натуральную величину. */
.preview__img { max-width: 100%; max-height: 100%; object-fit: contain; }
.preview__note { padding: 24px; color: var(--text-muted); text-align: center; }

/* ---------- Подсказка-предупреждение ---------- */

.hint-strip {
    display: flex;
    gap: 10px;
    align-items: flex-start;
    padding: 12px 16px;
    background: var(--warn-soft);
    border: 1px solid #fedf89;
    border-radius: var(--radius-sm);
    font-size: var(--fs-md);
    color: #7a4a08;
    margin-bottom: 20px;
}
/* Только текстовые ссылки: кнопки в полосе держат свой цвет (02.10.2026 —
   синяя кнопка получала тёмно-жёлтый текст). */
.hint-strip a:not(.btn) { color: var(--warn); font-weight: 550; }

/* ---------- Обзор настроек: один столбец, группы подписями ----------

   Прежняя сетка из восьми карточек (auto-fill от 330px) выравнивалась
   по рядам: ряд держал высоту самой длинной карточки, и на ширине 1990px
   из 868px сетки около 700px приходилось на пустые провалы — 210px в первом
   ряду, 269px во втором (замер 26.08.2026, замечание заказчика). Столбец
   такой ошибки не допускает ни на какой ширине, а состояния встают одной
   колонкой: «что не настроено» читается сверху вниз одним взглядом,
   а не собирается глазами по четырём колонкам.

   Ширина ограничена и колонка отцентрована — как у .form-page: строка
   «название … состояние» в 1900px превращается в две далёкие точки. */

/* Экран настроек занимает всю ширину, как и остальные экраны (заказчик,
   26.08.2026: «почему всё по середине вместо занять пространство»).
   Колонка на 1240 px посреди белого поля читалась как чужая страница:
   дела, клиенты и очередь дня идут во всю ширину.

   Читаемость держится не полями страницы, а колонками внутри: формы
   и списки раскладываются по ширине столбца, а не растягиваются
   на два метра монитора. */
.settings-page { max-width: none; }
/* Полоса вкладок не переносится, а прокручивается: перенос ставил
   активную закладку на одну строку, а линию полосы — под другую. Тот же
   приём, что у бокового меню ниже 1000 px и у широких таблиц. */
.tabs--settings {
    margin-bottom: 18px;
    flex-wrap: nowrap;
    overflow-x: auto;
    /* Тонкая полоса прокрутки: обычная забирает половину высоты ряда. */
    scrollbar-width: thin;
}
.settings-cols {
    display: grid;
    /* Столько колонок, сколько влезает по 480 px: на 1280 их две,
       на 1990 — три. Форма в колонке уже 480 px становится теснее,
       чем на своём отдельном экране. */
    grid-template-columns: repeat(auto-fit, minmax(480px, 1fr));
    gap: 18px;
    align-items: start;
}
/* Вкладка без форм — одна колонка во всю ширину: там таблица,
   и делить её на колонки незачем. */
.settings-cols--single { grid-template-columns: minmax(0, 1fr); }
/* Пояснение — колонка таблицы, а не всплывающая подсказка: заказчик
   26.08.2026 попросил «название, число, описание» строкой. Мельче
   названия, чтобы читалось как пояснение, а не как вторая колонка данных. */
.settings-table__hint { color: var(--text-muted); font-size: var(--fs-sm); }
/* Минимальной ширины у этих таблиц нет: они стоят в колонке 800 px
   и должны в неё влезать, а не прокручиваться внутри карточки. Колонки
   сжимаются по содержимому — длинное переносится. */
/* `break-word`, а не `anywhere`: второй влияет ещё и на минимальную ширину
   колонки, и таблица сжимала «действует с» до «дейс/тву/ет с». Первый рвёт
   слово только тогда, когда оно и правда не влезает (длинная ссылка
   на источник), а колонку ниже слова не ужимает. */
.settings-table td, .settings-table th { overflow-wrap: break-word; }
.settings-col { display: flex; flex-direction: column; gap: 18px; min-width: 0; }
/* Поля панели — по ширине, а не по долям двенадцати: в панели 840 px
   треть строки даёт 200 px, и почтовый адрес в неё не влезает (замер
   26.08.2026: обрезались «Логин» и «Адрес отправителя»). Здесь важна
   не доля, а то, чтобы в поле помещалось значение. */
.settings-panel .form__grid {
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}
.settings-panel .form__field,
.settings-panel .form__field--span-2,
.settings-panel .form__field--span-4,
.settings-panel .form__field--span-6,
.settings-panel .form__field:where(:has(select)) {
    grid-column: span 1;
}
.settings-panel .form__field--wide { grid-column: 1 / -1; }

.settings-panel__hint {
    font-size: var(--fs-sm);
    color: var(--text-muted);
    margin-bottom: 12px;
}
/* Состояний у панели бывает несколько (у порогов их два: суммы и предел
   пакета) — без зазора они слипались в «заполнены50 МБ». */
.settings-panel .card__actions { display: flex; gap: 12px; align-items: baseline; }
@media (max-width: 1100px) {
    .settings-cols { grid-template-columns: minmax(0, 1fr); }
}
/* Состояние настройки: «5», «не заведены», «1 тип без правила». Живёт
   и в колонке таблицы справочников, и в шапке живой панели — поэтому
   отдельным классом, а не частью строки списка (список стал таблицей
   26.08.2026 по просьбе заказчика: название, число, пояснение). */
.settings-row__state {
    font-size: var(--fs-sm);
    font-weight: 600;
    color: var(--text);
}
.settings-row__state--warn { color: var(--warn); }
.settings-row__state--empty { color: var(--text-faint); font-weight: 500; }
.settings-row__state--muted { color: var(--text-faint); font-weight: 400; }

/* ---------- Одна отправка: текст, который получил человек ----------

   Тело заморожено при отправке, поэтому показывается как есть: переносы
   строк — часть сообщения, а не оформление. */

.sent__subject {
    margin-top: 16px;
    font-size: var(--fs-md);
    font-weight: 650;
}
.sent__body {
    margin-top: 8px;
    padding: 14px 16px;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    font-size: var(--fs-md);
    line-height: 1.6;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

/* ---------- Форма рассылки: вкладки текста и чипы клиентов ---------- */

.text-tabs { margin-top: 14px; }
.text-tabs .tabs { margin-bottom: 12px; }
.chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }
.chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 10px;
    border-radius: 999px;
    background: var(--accent-soft);
    border: 1px solid var(--head-border);
    font-size: var(--fs-sm);
    font-weight: 550;
}
.chip__remove {
    border: none;
    background: none;
    cursor: pointer;
    font-size: var(--fs-xs);
    color: var(--text-muted);
    padding: 0;
}
.chip__remove:hover { color: var(--danger); }
.chips__results {
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--surface);
    box-shadow: var(--shadow);
    margin-top: 4px;
    max-width: 380px;
}
.chips__option {
    display: block;
    width: 100%;
    text-align: left;
    padding: 8px 12px;
    border: none;
    background: none;
    font: inherit;
    font-size: var(--fs-md);
    cursor: pointer;
}
.chips__option:hover { background: var(--accent-soft); }

/* Заголовок раздела внутри формы (пороги проверок) */
.form__section {
    font-size: var(--fs-md);
    font-weight: 650;
    margin: 18px 0 10px;
    padding-top: 14px;
    border-top: 1px solid var(--border);
}
.form__section:first-of-type { margin-top: 0; padding-top: 0; border-top: none; }

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

.btn {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 8px 14px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border-strong);
    background: var(--surface);
    color: var(--text);
    font-size: var(--fs-md);
    font-weight: 550;
    /* Своя высота строки — иначе <a class="btn"> и <button class="btn">
       в одном ряду разной высоты: ссылка наследует 1.5 у страницы,
       у кнопки браузер ставит `normal` (~1.15). На карточке дела это
       давало 31 px против 26 в соседних кнопках одного ряда
       (замер 26.08.2026, замечание заказчика о симметрии). */
    line-height: 1.4;
    cursor: pointer;
    white-space: nowrap;
}
.btn:hover { background: #f2f4f7; text-decoration: none; }
.btn--primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.btn--primary:hover { background: var(--accent-dark); }
.btn--sm { padding: 5px 10px; font-size: var(--fs-sm); }
/* Приглушённая кнопка для удаления пункта. Внешне отличается от соседней
   «Не требуется» намеренно: две одинаковые кнопки рядом — это промах мышью,
   а действия у них разные и одно из них необратимо. Красной её не делаем:
   красный в проекте занят состоянием сроков. */
.btn--ghost { background: transparent; border-color: transparent; color: var(--text-muted); }
.btn--ghost:hover { background: #f2f4f7; border-color: var(--border-strong); color: var(--text); }

/* ---------- Карточки ---------- */

.card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    margin-bottom: 20px;
    overflow: hidden;
}
/* Шапка подкрашена синим: на странице дела карточек десяток, и без заливки
   границы между разделами теряются — глазу не за что зацепиться при прокрутке.
   Синим здесь становится фон, а не заголовок: синий текст в проекте означает
   ссылку или действие, и заголовок-рубрика не должен выглядеть кликабельным. */
.card__head {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 14px 18px;
    background: var(--head-bg);
    border-bottom: 1px solid var(--head-border);
}
/* Заголовок карточки — чёрный жирный на голубой полосе шапки (заказчик,
   22.08.2026; синий текст пробовался и отменён в тот же день). */
.card__title { font-size: var(--fs-lg); font-weight: 700; margin: 0; color: var(--text); }
.card__note { color: var(--text-muted); font-size: var(--fs-sm); }
/* На синей шапке серый --text-muted даёт около 3,8:1 — для 12,5 px мало.
   Подпись рядом с заголовком темнее, чем такая же подпись на белом. */
.card__head .card__note { color: #475467; }
.card__actions { margin-left: auto; display: flex; gap: 8px; align-items: center; }
.card__body { padding: 18px; }

.card--danger { border-left: 3px solid var(--danger); }
.card--warn { border-left: 3px solid var(--warn); }

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

.tiles {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: 16px;
    margin-bottom: 20px;
}
.tile {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: 16px 18px;
    display: block;
    color: inherit;
}
.tile:hover { text-decoration: none; border-color: var(--border-strong); }
.tile__label { color: var(--text-muted); font-size: var(--fs-sm); }
.tile__value { font-size: var(--fs-3xl); font-weight: 680; line-height: 1.15; margin-top: 6px; letter-spacing: -.5px; }
/* Подсказка несёт смысл («срок прошёл, документа нет») — цвет muted,
   а не faint: faint на белом даёт 2.6:1 и не читается (WCAG AA — 4.5). */
.tile__hint { color: var(--text-muted); font-size: var(--fs-sm); margin-top: 4px; }
.tile--danger .tile__value { color: var(--danger); }
.tile--warn .tile__value { color: var(--warn); }

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

.table { width: 100%; border-collapse: collapse; }
.table th {
    text-align: left;
    font-size: var(--fs-xs);
    font-weight: 620;
    text-transform: uppercase;
    letter-spacing: .4px;
    color: var(--text-muted);
    padding: 10px 18px;
    background: #fafbfc;
    border-bottom: 1px solid var(--border);
    white-space: nowrap;
}
.table td {
    padding: 12px 18px;
    border-bottom: 1px solid var(--border);
    vertical-align: middle;
}
.table tbody tr:last-child td { border-bottom: none; }
.table tbody tr:hover { background: #fafbfc; }
/* Строка, которая открывается по клику, должна об этом сообщать курсором. */
[data-href] { cursor: pointer; }
.table__num { font-variant-numeric: tabular-nums; white-space: nowrap; }
.table-wrap { overflow-x: auto; }

.cell-main { font-weight: 550; }
.cell-sub { color: var(--text-muted); font-size: var(--fs-sm); margin-top: 2px; }

/* Номер дела в таблице — кнопка, а не текстовая ссылка.
   Это основной переход в списках: у него должна быть кликабельная площадь,
   а не подчёркнутые семь символов. */
.case-btn {
    display: inline-flex;
    align-items: center;
    padding: 5px 11px;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    background: var(--surface);
    color: var(--text);
    font-size: var(--fs-md);
    font-weight: 620;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    line-height: 1.3;
}
.case-btn:hover {
    background: var(--accent-soft);
    border-color: var(--accent);
    color: var(--accent-dark);
    text-decoration: none;
}
.case-btn:active { background: #e0e9ff; }

/* ---------- Бейджи ---------- */

.badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 2px var(--badge-pad);
    border-radius: 999px;
    font-size: var(--fs-sm);
    font-weight: 550;
    white-space: nowrap;
    background: #f2f4f7;
    color: #344054;
}
.badge--danger { background: var(--danger-soft); color: var(--danger); }
.badge--warn { background: var(--warn-soft); color: var(--warn); }
.badge--ok { background: var(--ok-soft); color: var(--ok); }
.badge--accent { background: var(--accent-soft); color: var(--accent-dark); }
.badge--dot::before {
    content: "";
    width: 6px; height: 6px;
    border-radius: 50%;
    background: currentColor;
}

/* ---------- Мелочи ---------- */

.muted { color: var(--text-muted); }
.faint { color: var(--text-faint); }
.nowrap { white-space: nowrap; }
/* Кнопка-действие в строке таблицы. Действие меняет данные, значит это
   POST, значит форма, а форма по умолчанию блочная и сбрасывала кнопку
   на следующую строку. */
.inline-form { display: inline-block; }
.stack > * + * { margin-top: 4px; }
.row-actions { display: flex; gap: 8px; align-items: center; }

.empty {
    padding: 28px 18px;
    text-align: center;
    color: var(--text-muted);
    font-size: var(--fs-md);
}
.empty strong { display: block; color: var(--text); font-size: var(--fs-lg); margin-bottom: 4px; }

/* Отрывок распознанного текста в результатах поиска. Текст сырой,
   со сломанными переносами и мусором распознавания, поэтому моноширинный
   и приглушённый: это доказательство совпадения, а не содержимое документа. */
.excerpt {
    margin-top: 6px;
    padding: 8px 10px;
    background: var(--surface-soft, #f9fafb);
    border-left: 2px solid var(--border);
    border-radius: 4px;
    font-size: var(--fs-sm);
    line-height: 1.55;
    color: var(--text-muted);
    word-break: break-word;
}
.excerpt mark {
    background: #fef0c7;
    color: var(--text);
    padding: 0 2px;
    border-radius: 2px;
}

.filters {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    align-items: flex-end;
    padding: 14px 18px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    margin-bottom: 20px;
}
.field { display: flex; flex-direction: column; gap: 4px; }
.field__label { font-size: var(--fs-sm); color: var(--text-muted); }
.field select, .field input {
    padding: 7px 10px;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    font-size: var(--fs-md);
    background: #fff;
    color: var(--text);
    min-width: 160px;
}
.field input:focus, .field select:focus { outline: 2px solid var(--accent-soft); border-color: var(--accent); }

/* ---------- Двухколоночная раскладка карточки ---------- */

/* Правая колонка не должна расти вместе с экраном: это сводка, а не работа.
   Всё лишнее место отдаётся очереди слева. */
.cols {
    display: grid;
    grid-template-columns: minmax(0, 1fr) clamp(340px, 26%, 520px);
    gap: 20px;
    align-items: start;
}
@media (max-width: 1100px) { .cols { grid-template-columns: minmax(0, 1fr); } }

/* minmax(0, 1fr), а не 1fr: у дорожки grid неявный min-width: auto, и её
   распирает самый неразрывный элемент внутри. Бейдж статуса — nowrap,
   поэтому «Пакет готов, ждём подачи клиентом» растягивал колонку на 361px
   в карточке шириной 318 и срезался её overflow: hidden — без многоточия,
   посреди слова. Вместе с ним уезжали имя клиента, воеводство и urząd. */
.kv {
    display: grid;
    /* Ширина подписи ровно заданная, без `auto`: с auto колонка росла
       по самой длинной подписи СВОЕГО списка, и в трёх карточках одной
       колонки значения начинались в 1269, 1288 и 1299 — тот самый разъезд,
       ради устранения которого всё это и делалось (замер 26.08.2026). */
    grid-template-columns: var(--kv-label) minmax(0, 1fr);
    gap: 8px var(--kv-gap);
    font-size: var(--fs-md);
}
/* Контейнер — тело карточки, а не сам список: запрос действует на потомков,
   и `container-type` на `.kv` собственные колонки не переключал (поймано
   замером: список 262 px, а колонки остались 120/126). */
.card__body { container-type: inline-size; }
/* Узкая карточка: подпись ужимается, но остаётся слева. При 120 px на неё
   значению доставалось 126, и «Показать пароль» с пояснением срезалось
   по букве (замер 26.08.2026). Ставить подпись над значением пробовал —
   колонка вытягивается и перестаёт читаться списком, поэтому уменьшена
   подпись: 96 + 10 дают значению 156 px, в которые кнопка влезает. */
@container (max-width: 400px) {
    /* И строки оплаты тоже: они соседи по колонке, и подпись у них должна
       быть той же ширины — иначе значения снова начинаются в двух разных
       местах (1269 против 1299 на карточке дела). */
    .kv, .pay__row { --kv-label: 128px; --kv-gap: 10px; }
}
.kv dt { color: var(--text-muted); overflow-wrap: anywhere; }
/* Значение тоже ломается где угодно: имя файла upo_PRYKLADNIUK_08_2026.pdf
   (252px) в колонке 175 на телефоне вылезало за карточку (замер 04.09.2026). */
.kv dd, .kv__val { min-width: 0; overflow-wrap: anywhere; }
/* Значения набраны с отступом в поле бейджа, а бейдж на столько же
   выдвинут влево. Тогда текст в бейдже и обычный текст соседней строки
   стоят на одной линии, а коробка бейджа — по краю колонки: раньше
   строка с бейджем выглядела съехавшей на эти 9 px (заказчик, 26.08.2026). */
.kv dd {
    margin: 0;
    min-width: 0;
    padding-left: var(--badge-pad);
    /* Длинное неразрывное значение (почта, код доступа, номер) в узкой
       колонке иначе срезается по букве: `halyna123@example.com` не влезал
       в 126 px и обрывался посреди слова — без многоточия, то есть
       незаметно (замер 26.08.2026). Перенос по любому месту честнее. */
    overflow-wrap: anywhere;
}
.kv dd > .badge:first-child,
.pay__value > .badge:first-child {
    margin-left: calc(-1 * var(--badge-pad));
}
/* Длинный статус переносится по словам, а не распирает карточку. */
.kv dd .badge { white-space: normal; }

/* ---------- Права сотрудника ----------

   Список галочек с пояснением: право без объяснения, что оно закрывает,
   выдают наугад. Отклонение от роли помечено прямо в строке — иначе через
   месяц не вспомнить, что выдано вручную. */

.caps { display: flex; flex-direction: column; gap: 2px; margin-top: 8px; }
.caps__row {
    display: grid;
    grid-template-columns: 18px minmax(0, 1fr);
    gap: 10px;
    align-items: start;
    padding: 8px 10px;
    border-radius: var(--radius-sm);
    cursor: pointer;
}
.caps__row:hover { background: var(--accent-soft); }
.caps__row input { margin-top: 2px; }
.caps__text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.caps__label { font-size: var(--fs-md); font-weight: 550; }
.caps__hint { font-size: var(--fs-sm); color: var(--text-muted); }

/* ---------- Лента событий ---------- */

.timeline { list-style: none; margin: 0; padding: 0; }
.timeline li { position: relative; padding: 0 0 18px 22px; border-left: 2px solid var(--border); }
.timeline li:last-child { padding-bottom: 0; border-left-color: transparent; }
.timeline li::before {
    content: "";
    position: absolute;
    left: -6px; top: 3px;
    width: 10px; height: 10px;
    border-radius: 50%;
    background: var(--border-strong);
    border: 2px solid var(--surface);
}
.timeline li.is-hard::before { background: var(--danger); }
.timeline__date { font-size: var(--fs-sm); color: var(--text-muted); }
.timeline__title { font-weight: 550; margin-top: 2px; }
.timeline__body { color: var(--text-muted); font-size: var(--fs-md); margin-top: 3px; }
.timeline__actions { display: flex; gap: 8px; align-items: center; margin-top: 8px; }
.timeline__actions form { margin: 0; display: inline-flex; }

/* ---------- Чек-лист документов ---------- */

.checklist { list-style: none; margin: 0; padding: 0; }
.checklist li {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 18px;
    border-bottom: 1px solid var(--border);
}
.checklist li:last-child { border-bottom: none; }
.checklist__main { min-width: 0; flex: 1; }
.checklist__name { font-weight: 550; }
.checklist__meta {
    color: var(--text-muted);
    font-size: var(--fs-sm);
    margin-top: 2px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.checklist__right { margin-left: auto; display: flex; align-items: center; gap: 10px; }
/* Кнопки-действия оформлены формами (POST), чтобы действие нельзя было
   вызвать переходом по ссылке. Форма не должна ломать раскладку строки. */
.checklist__right form, .card__actions form, .queue__right form { margin: 0; display: inline-flex; }

/* ---------- Показ выпущенного кода ---------- */

.code-reveal {
    background: var(--accent-soft);
    border: 1px solid #b9d0ff;
    border-radius: var(--radius-sm);
    padding: 14px 16px;
    text-align: center;
}
.code-reveal__value {
    font: 700 var(--fs-2xl)/1.2 "Cascadia Mono", Consolas, "Courier New", monospace;
    letter-spacing: 2px;
    color: var(--accent-dark);
    user-select: all;
}
.code-reveal__note { color: var(--text-muted); font-size: var(--fs-sm); margin-top: 8px; }

/* ---------- Заметки ---------- */

.note {
    background: #fffdf5;
    border: 1px solid #f0e2c0;
    border-radius: var(--radius-sm);
    padding: 12px 14px;
    font-size: var(--fs-md);
}
.note + .note { margin-top: 10px; }
.note__meta { color: var(--text-muted); font-size: var(--fs-sm); margin-top: 6px; }

/* ---------- Вход ---------- */

.login { display: flex; min-height: 100vh; }
.login__promo {
    flex: 1;
    background: linear-gradient(160deg, #1b2436 0%, #24314b 100%);
    color: #fff;
    padding: 56px clamp(40px, 6vw, 96px);
    display: flex;
    flex-direction: column;
    justify-content: center;
}
@media (max-width: 900px) { .login__promo { display: none; } }
/* Содержимое не растягивается вместе с монитором: на широком экране
   логотип оказывался в левом углу пустого поля, а строка текста уезжала
   за читаемую длину. Блок центрируется в своей половине. */
/* По центру: логотип и подпись под ним читаются как одна композиция,
   а прижатые влево — как две отдельные вещи в пустом поле. */
.login__promo-inner { width: 100%; max-width: 720px; margin: 0 auto; text-align: center; }
/* Логотип — главное, что здесь есть: он опознаёт фирму раньше текста.
   Растёт вместе с экраном, но не бесконечно. */
.login__promo h1 {
    font-size: clamp(30px, 3.2vw, 46px);
    font-weight: 660;
    margin: 0 0 16px;
    letter-spacing: -.015em;
    text-wrap: balance;
}
.login__promo p { color: #aab5c5; font-size: var(--fs-lg); line-height: 1.65; margin: 0 auto; max-width: 520px; }
.login__form-wrap {
    /* Не фиксированные 440px: на широком мониторе колонка выглядела
       щелью у края. Растёт долей ширины, с потолком — форма из двух полей
       шире 560px не читается. */
    flex: 0 0 clamp(460px, 34%, 620px);
    background: var(--surface);
    padding: 56px clamp(40px, 4vw, 64px);
    display: flex;
    flex-direction: column;
    justify-content: center;
}
@media (max-width: 900px) {
    .login__form-wrap {
        flex: 1;
        padding: 32px 24px;
        /* Тёмная половина скрыта, и форма осталась бы во всю ширину:
           одно поле email на 812px — это не форма, а полоса. Содержимое
           держится читаемой ширины и центрируется. */
        align-items: center;
    }
    .login__form-wrap > * { width: 100%; max-width: 500px; }
}
/* Логотип над формой — только когда тёмная половина скрыта: иначе он был бы
   на экране дважды. Без него на телефоне не остаётся ничего, что называет
   фирму, а это первый экран, который человек видит. */
.login__form-logo { display: none; }
@media (max-width: 900px) {
    .login__form-logo {
        display: block;
        width: 132px; height: 132px;
        object-fit: contain;
        margin: 0 auto 20px;
    }
}
.login__form-wrap h2 { font-size: var(--fs-2xl); margin: 0 0 6px; letter-spacing: -.01em; }
.login__lead { color: var(--text-muted); font-size: var(--fs-lg); margin: 0 0 28px; }
.login .field { margin-bottom: 20px; }
.login .field__label { font-size: var(--fs-md); color: var(--text); font-weight: 500; }
/* Крупнее, чем поля рабочих экранов: здесь их два, а не двадцать,
   и вводят их с утра одним движением. 16px — заодно порог, ниже которого
   мобильный Safari увеличивает страницу при касании. */
.login .field input {
    width: 100%;
    padding: 12px 14px;
    font-size: var(--fs-lg);
    min-height: 48px;
}
.login .btn {
    width: 100%;
    justify-content: center;
    padding: 13px;
    font-size: var(--fs-lg);
    min-height: 48px;
    margin-top: 4px;
    /* Без этого <a class="btn"> оказывается на три пикселя выше соседней
       <button>: у ссылки высоту добирает межстрочное расстояние body (1.5),
       у кнопки — нет. Две кнопки в стопке разной высоты читаются как
       недоделка. */
    line-height: 1.2;
}
/* «Забыли пароль» — кнопка, а не ссылка. По ней сотрудник задаёт себе
   ПЕРВЫЙ пароль: карточку заводит глава, а пароль за коллегу не вводят,
   то есть это полноценное действие рядом со входом, а не сноска.
   Второстепенная по виду — первичное действие на экране одно. */
.login__actions { display: flex; flex-direction: column; gap: 10px; margin-top: 4px; }
.login__actions .btn { margin-top: 0; }
.login__foot { margin-top: 26px; color: var(--text-muted); font-size: var(--fs-md); line-height: 1.55; }
.login__error {
    background: var(--danger-soft);
    color: var(--danger);
    border-radius: var(--radius-sm);
    padding: 10px 12px;
    font-size: var(--fs-md);
    margin-bottom: 18px;
}

/* ---------- Заявленная клиентом оплата ----------
   Строка с действием, а не запись в истории: пока сотрудник не сверил
   поступление, деньги не считаются, и дело может стоять из-за этого. */

.declared-payment {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    padding: 10px 0;
    border-bottom: 1px solid var(--border);
    font-size: var(--fs-md);
}
.declared-payment:last-of-type { border-bottom: none; margin-bottom: 8px; }
.declared-payment__main { flex: 1; min-width: 200px; }
.declared-payment__reject { display: flex; gap: 6px; align-items: center; }

.control--sm { padding: 5px 8px; font-size: var(--fs-md); width: 210px; }

/* ---------- Дорожка состояния дела ----------
   Тот же принцип, что у трекинга посылки: одним взглядом видно, где дело
   сейчас и что будет дальше. Ветвления (wezwanie, отказ, odwołanie) не
   добавляют шагов, а перекрашивают текущий — дерево из пяти веток
   с одного взгляда не читается.

   Цвет: пройденное и текущее — синие, впереди — серое, проблема — красная.
   Красный тут по правилу проекта и есть состояние: wezwanie и отказ — это
   то же «горит», что и просроченный документ. */

.track {
    display: flex;
    list-style: none;
    margin: 0;
    padding: 18px 8px 16px;
    overflow-x: auto;
}
.track__step {
    position: relative;
    flex: 1 1 0;
    min-width: 96px;
    padding: 0 6px;
    text-align: center;
}
/* Линия рисуется влево от точки, поэтому у первого шага её нет. */
.track__line {
    position: absolute;
    top: 6px;
    right: 50%;
    left: -50%;
    height: 2px;
    background: var(--border-strong);
}
.track__step:first-child .track__line { display: none; }
.track__dot {
    position: relative;
    width: 14px;
    height: 14px;
    margin: 0 auto 10px;
    border-radius: 50%;
    background: var(--border-strong);
}
.track__label { font-size: var(--fs-sm); font-weight: 550; color: var(--text-muted); }
.track__date { font-size: var(--fs-xs); color: var(--text-faint); margin-top: 2px; }
/* Долг по отчётам ZUS на текущем шаге: бейдж под датой, красный при просрочке. */
.track__waiting {
    display: inline-block;
    margin-top: 6px;
    padding: 2px 8px;
    border-radius: 999px;
    font-size: var(--fs-xs);
    font-weight: 600;
    color: var(--accent-dark);
    background: var(--accent-soft);
    white-space: normal;
}
.track__waiting--overdue { color: #b42318; background: #fef3f2; }

.track__step--done .track__line,
.track__step--done .track__dot { background: var(--accent); }
.track__step--done .track__label { color: var(--text); }

.track__step--current .track__line { background: var(--accent); }
.track__step--current .track__dot {
    background: var(--accent);
    box-shadow: 0 0 0 4px var(--accent-soft);
}
.track__step--current .track__label { color: var(--accent-dark); font-weight: 650; }

.track__step--problem .track__line { background: var(--accent); }
.track__step--problem .track__dot {
    background: var(--danger);
    box-shadow: 0 0 0 4px var(--danger-soft);
}
.track__step--problem .track__label { color: var(--danger); font-weight: 650; }

/* Клиент отказался: дорожка не продолжится, но и тревогой это не является. */
.track__step--stopped .track__dot { background: var(--text-faint); }
.track__step--stopped .track__label { color: var(--text-muted); font-weight: 650; }

/* На телефоне пять подписей в ряд не помещаются — дорожка встаёт вертикально
   и линия переезжает слева от точек. */
@media (max-width: 640px) {
    .track { display: block; padding: 14px 4px; }
    .track__step { min-width: 0; text-align: left; padding: 0 0 0 26px; }
    .track__step + .track__step { margin-top: 14px; }
    .track__line { top: -14px; left: 6px; right: auto; bottom: 7px; width: 2px; height: auto; }
    .track__dot { position: absolute; left: 0; top: 1px; margin: 0; }
    .track__date { display: inline; margin-left: 8px; }
}

/* ---------- События, требующие действия ----------
   Событие со сроком — это задача, а не запись в истории: пока по нему
   ничего не сделано, оно стоит отдельным блоком над лентой. Отмеченное
   уходит вниз, в историю, и перестаёт гореть здесь и на главной. */

.event-todo { list-style: none; margin: 0; padding: 0; }
.event-todo__item {
    display: flex;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
    padding: 14px 18px 14px 15px;
    border-bottom: 1px solid var(--border);
    border-left: 3px solid var(--border-strong);
}
.event-todo__item.is-hard { border-left-color: var(--danger); background: #fffbfa; }
.event-todo__main { flex: 1; min-width: 220px; }
.event-todo__title { font-weight: 600; }
.event-todo__meta {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    color: var(--text-muted);
    font-size: var(--fs-sm);
    margin-top: 3px;
}
.event-todo__actions { display: flex; gap: 8px; align-items: center; margin-left: auto; }
.event-todo__actions form { margin: 0; display: inline-flex; }

/* Выполненное в ленте: точка гаснет, заголовок перестаёт быть акцентом.
   Зачёркивания нет — событие остаётся фактом истории дела, а не ошибкой. */
.timeline li.is-done::before { background: var(--ok); }
.timeline li.is-done .timeline__title { color: var(--text-muted); font-weight: 500; }

/* ---------- Состояние перетаскивания документа ---------- */
/* Строка молчит, пока её не тронули: подпись под каждым документом
   «готов к перетаскиванию» была бы шумом на весь список. Появляется
   только после нажатия и только если есть что сказать. */
.drag-state:empty { display: none; }
.drag-state {
    font-size: var(--fs-sm);
    color: var(--text-muted);
}
.drag-state--ok { color: var(--ok, #38634c); }

/* ---------- Подзаголовок внутри карточки формы ---------- */
/* Карточка клиента собрала в себе несколько разнородных блоков: имя,
   адрес, история пребывания. Без разделителя это сплошная сетка
   полей, в которой не видно, где кончается одно и начинается другое. */
/* Подзаголовок внутри карточки: «Подача клиентом» и «Opłaty skarbowe»
   переехали в карточку дела и разделены им, а не отдельными шапками.
   Кнопка в той же строке прижимается вправо — действие относится
   к разделу, а не ко всей карточке. */
.card__subhead {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin: 18px 0 10px;
    padding-top: 14px;
    border-top: 1px solid var(--border);
    font-size: var(--fs-sm);
    font-weight: 650;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--text-muted);
}

.form__subhead {
    font-size: var(--fs-md);
    font-weight: 620;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin: 22px 0 12px;
    padding-top: 16px;
    border-top: 1px solid var(--border);
}
.form__subhead:first-child { margin-top: 0; padding-top: 0; border-top: none; }

/* ---------- Смена статуса в шапке дела ---------- */
/* Статус меняют часто и по одному поводу — он стоит там, где на него
   смотрят, а не в форме правки среди цены и работодателя. */
.status-switch {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 8px;
}
/* В шапке «Хода дела» переключатель стоит рядом с заголовком: отступ сверху
   там лишний, шапка и так выравнивает по центру. Перенос строки разрешён —
   иначе на узком экране список статусов сжался бы до нечитаемого. */
.card--track .card__head { flex-wrap: wrap; }
.card--track .status-switch { margin-top: 0; }

/* Месяцы отчётов ZUS в строку: их бывает десяток, и вертикальным списком
   они заняли бы экран ради ответа на вопрос «какие месяцы закрыты». */
.zus-months {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin: 8px 0 4px;
}
.status-switch__label {
    font-size: var(--fs-sm);
    /* На --head-bg (голубая панель) приглушённый давал 3,8:1. Подпись
       поля читают, а не проглядывают — берём основной цвет текста. */
    color: var(--text);
}
.status-switch .control--sm { width: auto; min-width: 200px; }

/* Приём подписанного файла. Отдельная зона, а не просто поле выбора файла:
   подписанный PDF приходит из окна загрузок браузера, и перетащить его
   быстрее, чем искать в диалоге. */
.dropzone {
    position: relative;
    display: block;
    margin-top: 12px;
    padding: 18px 14px;
    border: 1px dashed var(--border);
    border-radius: var(--radius);
    background: var(--head-bg);
    text-align: center;
    cursor: pointer;
}
.dropzone.is-over { border-color: var(--accent); background: var(--surface); }
/* Зона в карточке дела. Серым на белом она сливалась с фоном карточки
   (заказчик, 26.08.2026), поэтому фон зелёный — тот же --ok-soft, каким
   в системе набраны «принято» и «проверен», то есть цвет уже означает
   «сюда всё в порядке». Тона — в токенах --drop-*, там же и замеры.

   Полем она осталась вспомогательным: это способ положить файл,
   а не действие по делу. */
.dropzone--slim {
    margin-top: 0;
    padding: 20px 16px;
    background: var(--drop-bg);
    border-color: var(--drop-border);
}
/* Ронять файл можно в любое место карточки, поэтому подсветка зоны должна
   быть заметна и с другого её конца — иначе непонятно, куда он попадёт. */
.dropzone--slim.is-over {
    background: var(--drop-bg-over);
    border-color: var(--ok);
}
.dropzone--slim .dropzone__hint { color: var(--drop-text); font-size: var(--fs-md); }
/* Зона шире прочего содержимого карточки: боковые отступы у неё вдвое
   меньше, чем у .card__body, — цель для мыши, а не абзац текста. */
.card__dropzone { padding: 12px 9px 6px; }
.dropzone__input {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: pointer;
}
.dropzone__hint { color: var(--text-muted); font-size: var(--fs-sm); }

/* Ключи подстановки кнопками: набранный руками ключ не заменится ничем
   и уедет в письмо как есть. */
.chips { display: flex; flex-wrap: wrap; gap: 6px; }
.chip {
    border: 1px solid var(--border-strong);
    background: var(--surface);
    border-radius: 999px;
    padding: 3px 10px;
    font: inherit;
    font-size: var(--fs-sm);
    color: var(--text);
    cursor: pointer;
}
.chip:hover { border-color: var(--accent); color: var(--accent); }
.letter-preview {
    white-space: pre-wrap;
    font: inherit;
    font-size: var(--fs-md);
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 12px;
    margin: 8px 0 0;
    max-height: 420px;
    overflow: auto;
}

/* Идентификатор в узкой колонке: номер отправления состоит из дефисов,
   а браузер по дефисам переносит — «FS-sda-123-CFD-123» разваливался
   на три обрывка и переставал читаться как номер. Одна строка, длинное
   обрезается многоточием, целиком видно при наведении. */
.cell-id {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
}

/* --- Лист письма ---------------------------------------------------------

   Экран правки показывает страницу так, как она напечатается, и позволяет
   двигать блоки мышью. Поэтому вся геометрия здесь задана в миллиметрах,
   а не в пикселях: `fpdf2` считает в них же, и одно и то же число означает
   на экране и в файле одно и то же. Размер шрифта — в пунктах по той же
   причине: CSS-пункт и типографский пункт PDF равны 1/72 дюйма.

   Шрифт берётся из того же файла, который зашит в PDF. Системный serif
   дал бы другую ширину букв, и строки на экране рвались бы не там. */
@font-face {
    font-family: "LetterSerif";
    src: url("../fonts/DejaVuSerif.ttf") format("truetype");
    font-weight: 400;
    font-display: swap;
}
@font-face {
    font-family: "LetterSerif";
    src: url("../fonts/DejaVuSerif-Bold.ttf") format("truetype");
    font-weight: 700;
    font-display: swap;
}
/* Курсивного начертания в поставке нет, и подделывать его наклоном нельзя:
   PDF набрал бы это место прямым, и лист врал бы про файл. Файл появится —
   правило заработает само. */
@font-face {
    font-family: "LetterSerif";
    src: url("../fonts/DejaVuSerif-Italic.ttf") format("truetype");
    font-weight: 400;
    font-style: italic;
    font-display: swap;
}

.letter-edit {
    display: grid;
    /* Лист — 210 мм, ужатый до --sheet-zoom. Колонка меряется тем же
       выражением, иначе она либо режет лист, либо оставляет дыру.
       Плюс рамка карточки и округление: без запаса лист вылезает
       на пару пикселей, и под ним появляется полоса прокрутки. */
    grid-template-columns:
        calc(210mm * var(--sheet-zoom) + 4px) minmax(320px, 1fr);
    gap: 20px;
    align-items: start;
    --sheet-zoom: .72;
}
@media (max-width: 1500px) { .letter-edit { --sheet-zoom: .62; } }
@media (max-width: 1200px) {
    .letter-edit { grid-template-columns: 1fr; --sheet-zoom: .55; }
}

/* Боковых полей у этой карточки нет: лист занимает её ширину целиком,
   и любой отступ по краям выталкивает его за карточку. */
.sheet-scroll { padding: 10px 0 0; }

/* Рамка ужатого листа. Она нужна отдельно от самого листа: `transform`
   уменьшает картинку, но не то место, которое элемент занимает в потоке,
   и без рамки под листом висела бы полоса прокрутки на те самые 210 мм,
   которых на экране уже нет. Отрицательными полями это лечится только
   наполовину — переполнение считается по коробке элемента, а не по полям. */
.sheet-frame {
    width: calc(210mm * var(--sheet-zoom));
    height: calc(297mm * var(--sheet-zoom));
    margin: 0 auto 12px;
    overflow: hidden;
}

.sheet {
    position: relative;
    width: 210mm;
    height: 297mm;
    background: #fff;
    border: 1px solid var(--border-strong);
    box-shadow: 0 2px 10px rgba(16, 24, 40, .10);
    transform: scale(var(--sheet-zoom));
    transform-origin: top left;
    font-family: "LetterSerif", Georgia, serif;
    color: #000;
    overflow: hidden;
}
.sheet__num {
    position: absolute;
    right: 6mm;
    bottom: 4mm;
    font-size: 8pt;
    color: var(--text-faint);
}

.sheet-block {
    position: absolute;
    box-sizing: border-box;
    cursor: grab;
    outline: 1px dashed transparent;
    outline-offset: 2px;
}
.sheet-block:hover { outline-color: var(--border-strong); }
.sheet-block.is-selected { outline: 1px solid var(--accent); }
.sheet-block.is-dragging { cursor: grabbing; outline: 1px solid var(--accent); }
/* Подвинутый блок помечен: иначе через месяц непонятно, почему это письмо
   не такое, как остальные, и что вернёт кнопка «Вернуть как было». */
.sheet-block.is-moved::after {
    content: "";
    position: absolute;
    left: -3mm;
    top: 0;
    width: 1mm;
    height: 100%;
    background: var(--accent);
    opacity: .5;
}
.sheet-block__text, .sheet-block__extra { white-space: pre-wrap; }
.sheet-block__extra { margin-top: 3mm; }

/* Подпись под названием блока — только при наведении: подписи на всех
   восьми блоках сразу превращают лист в схему, а смотреть на него надо
   как на письмо. */
.sheet-block__tag {
    position: absolute;
    left: 0;
    top: -4.6mm;
    font-family: var(--font);
    font-size: 8px;
    letter-spacing: .3px;
    text-transform: uppercase;
    color: var(--accent);
    background: var(--accent-soft);
    border-radius: 3px;
    padding: 1px 4px;
    opacity: 0;
    pointer-events: none;
    white-space: nowrap;
}
.sheet-block:hover .sheet-block__tag,
.sheet-block.is-selected .sheet-block__tag { opacity: 1; }

.sheet-block__grip {
    position: absolute;
    right: -1.5mm;
    top: 0;
    width: 3mm;
    height: 100%;
    cursor: ew-resize;
    opacity: 0;
}
.sheet-block:hover .sheet-block__grip { opacity: 1; background: rgba(37, 99, 235, .12); }

.sheet-block.is-sign { text-align: left; }
.sheet-sign__img {
    display: block;
    width: 100%;
    height: auto;
}
.sheet-sign__img--blank {
    display: flex;
    align-items: flex-end;
    height: 100%;
    border-bottom: 0;
    font-family: var(--font);
    font-size: 9px;
    color: var(--text-faint);
}
/* Точечная линия тянется по ширине блока — как в PDF, где число точек
   считается от ширины колонки. */
.sheet-sign__line { display: block; height: 5mm; border-bottom: 1px dotted #000; }
.sheet-sign__title { font-size: 9pt; margin-top: 0; }  /* в PDF должность сразу под именем */

/* Панель выбранного блока. Стоит над листом, а не сбоку: выбирают блок
   мышью на листе, и уводить взгляд в другой угол экрана незачем. */
.sheet-tools {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 16px;
    border-bottom: 1px solid var(--border);
    background: var(--bg);
    font-size: var(--fs-sm);
}
.sheet-tools__sel { color: var(--text-muted); }
.sheet-tools__aligns { display: inline-flex; gap: 4px; }
/* Скрытие через `hidden` иначе не работает: правило выше перебивает
   `display: none` из стилей браузера, и кнопки висят на виду всегда. */
.sheet-tools__aligns[hidden] { display: none; }
.sheet-tools__gap { flex: 1; }
.sheet-tools__note { color: var(--text-faint); }
.sheet-note { border-top: 1px solid var(--border); font-size: 12px; }

/* Разметка текста. Кнопки правят textarea, а не подменяют его редактором:
   тот же текст уходит вторым разом в тело обращения в e-Doręczenia,
   и HTML там был бы мусором. */
.marktools {
    display: flex;
    align-items: center;
    gap: 6px;
    margin: 4px 0 8px;
}
.marktools__gap { width: 10px; }

/* --- Панель действий в карточке дела -------------------------------------
   Форма открывается поверх страницы, а не отдельной страницей: заголовок
   оформлен вкладкой, содержимое — то же, что на полной странице. */
.panel[hidden] { display: none; }
.panel {
    position: fixed;
    inset: 0;
    z-index: 60;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    padding: 4vh 16px 16px;
}
.panel__backdrop { position: absolute; inset: 0; background: rgba(17, 24, 39, .55); }
.panel__box {
    position: relative;
    /* 1040 вместо 860: форма приёмки в 860 ломала сетку полей на узкие
       обрубки, и «всё поместилось» не выполнялось (заказчик, 21.08.2026). */
    width: min(1160px, 100%);
    max-height: 92vh;
    display: flex;
    flex-direction: column;
    background: var(--bg);
    border-radius: var(--radius);
    box-shadow: 0 18px 50px rgba(16, 24, 40, .35);
    overflow: hidden;
}
.panel__head {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 12px;
    padding: 10px 14px 0;
    background: var(--sidebar-bg);
}
/* Заголовок — вкладкой: выступ, «прилипший» к содержимому ниже. */
.panel__tab {
    display: inline-block;
    padding: 8px 18px;
    background: var(--bg);
    color: var(--text);
    font-weight: 650;
    font-size: var(--fs-md);
    border-radius: var(--radius-sm) var(--radius-sm) 0 0;
    max-width: 70%;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.panel__actions { display: flex; gap: 8px; padding-bottom: 8px; }
.panel__body { overflow: auto; padding: 16px; }
/* Внутри панели страница уже, чем в полном окне, — колонкам незачем
   вставать рядом. */
.panel__body .cols { grid-template-columns: minmax(0, 1fr); }

/* ---------- Документы в деле: группы по смыслу ---------- */

/* Заголовок группы — строка таблицы, а не отдельная таблица на группу:
   колонки должны остаться одной ширины по всему списку. */
.table__group-row th {
    text-transform: none;
    letter-spacing: 0;
    font-size: var(--fs-sm);
    font-weight: 620;
    color: var(--text);
    background: #f3f5f8;
    padding: 8px 18px;
}
/* На подложке строки группы приглушённый теряет ~0,4 контраста и уходит
   ниже нормы. Приглушённый второго уровня здесь не нужен: это счётчик,
   его читают. */
.table__group-row th .faint { margin-left: 6px; font-weight: 400; color: var(--text-muted); }
.table__fold td { padding: 6px 18px; background: #fafbfc; }
/* Вывод о непрерывности — строка под заголовком группы. Тот же фон, что
   у свёрнутого хвоста: это не документ, а сказанное о документах. */
.table__note-row td { padding: 8px 18px; background: #fafbfc; font-size: var(--fs-sm); }
.table__note-row .badge { margin-right: 6px; }
.table__note-row .cell-sub { margin-top: 4px; }
/* Заменённые свёрнуты только при работающем JS: без него свёрнутое
   было бы недостижимо. */
/* Ширины колонок не пересчитываются от содержимого (заказчик, 26.08.2026:
   «почему при развёртывании заменённых все элементы смещаются»).

   В auto-раскладке скрытые строки в счёт не идут: развернул хвост —
   и колонка «Действует до» выросла со 124 до 172 px под бейдж
   «не привязан к умове», утащив «Проверил» на 48 px вправо. Замерено
   до и после нажатия. `fixed` раздаёт ровно то, что написано в `<th>`,
   а длинное значение переносится, а не расталкивает соседей. */
.table--fixed { table-layout: fixed; }
/* Нижний предел ширины — только у таблицы документов дела: в ней семь
   колонок, и в узкой карточке они схлопывались до 21 px. Таблице
   справочников на вкладке настроек этот предел не нужен — она из трёх
   колонок и обязана влезать в свою колонку, а не прокручиваться. */
.table--docs { min-width: 1000px; }
.table--fixed th, .table--fixed td { overflow-wrap: anywhere; }
/* Бейдж в колонке фиксированной ширины переносится по словам, а не
   вылезает за край: «не привязан к умове» шире своей колонки на 44 px. */
.table--fixed .badge { white-space: normal; }

.js-docs-folded .row--superseded { display: none; }
.row--superseded td { color: var(--text-muted); }
.row--superseded .cell-main a { color: inherit; }


/* ---------- Шапка дела (22.08.2026, по макету заказчика) ---------- */

.case-hero {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 14px;
    margin-bottom: 18px;
}
.case-hero__icon {
    width: 40px; height: 40px; flex: none;
    border-radius: 10px;
    background: var(--accent);
    color: #fff;
    display: flex; align-items: center; justify-content: center;
}
.case-hero__main { min-width: 0; flex: 1 1 360px; }
.case-hero__title { margin: 0; font-size: var(--fs-2xl); font-weight: 700; line-height: 1.2; }
.case-hero__meta {
    display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
    margin-top: 4px; font-size: var(--fs-md); color: var(--text-muted);
}
.case-hero__client { color: var(--accent); font-weight: 500; }
/* Разделитель между полями шапки. Роль декоративная, но глиф текстовый
   и попадает в проверку контраста — берём приглушённый вместо цвета рамки. */
.case-hero__sep { color: var(--text-muted); }
.case-hero__actions {
    margin-left: auto;
    flex: none;
    display: flex; flex-wrap: wrap; gap: 10px; align-items: center;
    justify-content: flex-end;
}
/* Узкий экран: заголовок сверху, кнопки строкой под ним.

   `flex-basis: 100%` и `margin-left` вместе дают ширину «100% плюс отступ»,
   то есть строка кнопок вылезала за край на величину отступа. Отступ
   выравнивал кнопки под заголовком; ниже 1000px, где места и так нет,
   он снимается. */
@media (max-width: 1100px) {
    .case-hero { flex-wrap: wrap; }
    .case-hero__actions { margin-left: 54px; flex-basis: 100%; justify-content: flex-start; }
}
@media (max-width: 1000px) {
    .case-hero__actions { margin-left: 0; }
    /* Выпадающее меню «⋯» у правого края: без потолка ширины его 220px
       выталкивают страницу вбок. */
    .menu__list { min-width: 0; max-width: min(220px, calc(100vw - 32px)); }
}
.btn--icon { display: inline-flex; align-items: center; gap: 7px; }
.btn--icon svg { flex: none; }

/* Меню «⋯» на <details>: открывается и закрывается без JS. */
.menu { position: relative; }
.menu__toggle { list-style: none; cursor: pointer; font-weight: 700; letter-spacing: 1px; padding-inline: 12px; }
.menu__toggle::-webkit-details-marker { display: none; }
.menu__list {
    position: absolute; right: 0; top: calc(100% + 6px); z-index: 20;
    min-width: 220px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 10px;
    box-shadow: 0 8px 24px rgba(16, 24, 40, .12);
    padding: 6px;
    display: flex; flex-direction: column;
}
.menu__list a {
    padding: 8px 10px; border-radius: 6px; color: var(--text); font-size: var(--fs-md);
}
.menu__list a:hover { background: #f2f4f7; text-decoration: none; }
.menu__list .menu__danger { color: var(--danger); }

.topbar__back { font-size: var(--fs-md); font-weight: 500; color: var(--text-muted); }
.topbar__back:hover { color: var(--accent); text-decoration: none; }


/* ---------- Карточка дела: две колонки по макету (22.08.2026) ---------- */

.case-layout { grid-template-columns: minmax(0, 1fr) clamp(380px, 32%, 520px); }
/* minmax(0, 1fr): иначе колонка растягивается по min-content самой широкой
   карточки — дорожка дела и таблица документов удерживали 881px в окне 753,
   и страница уезжала вбок. Прокрутка у них своя (.table-wrap, .track). */
@media (max-width: 1100px) { .case-layout { grid-template-columns: minmax(0, 1fr); } }
.case-layout__side .card { margin-bottom: 16px; }

/* Свёрнутая карточка: одна строка с шевроном, разворачивается без JS. */
.card--fold > .card__fold {
    list-style: none; cursor: pointer;
    display: flex; align-items: center; gap: 10px;
    padding: 14px 18px; font-weight: 600; font-size: var(--fs-md);
}
.card--fold > .card__fold::-webkit-details-marker { display: none; }
.card__chevron { margin-left: auto; color: var(--text-faint); font-size: var(--fs-lg); line-height: 1; transition: transform .15s; }
.card--fold[open] > .card__fold .card__chevron { transform: rotate(90deg); }
.card--fold[open] > .card__fold { border-bottom: 1px solid var(--border); }
/* Внутри свёрнутой карточки лежит обычная карточка — её рамку убираем,
   иначе получается коробка в коробке. */
.card--fold > .card { border: 0; box-shadow: none; margin: 0; border-radius: 0; }


/* ---------- Оплата услуг: цена, полоса, оплачено/остаток (22.08.2026) ---------- */

.pay { margin-bottom: 10px; }
.pay__price { font-size: var(--fs-xl); font-weight: 700; margin-bottom: 8px; }
.pay__note { font-size: var(--fs-md); font-weight: 400; margin-left: 6px; }
.pay__bar { height: 10px; border-radius: 999px; background: #eaecf0; overflow: hidden; margin-bottom: 10px; }
.pay__fill { height: 100%; border-radius: 999px; background: #12b76a; transition: width .2s; }
.pay__fill.is-paid { background: var(--ok); }
.pay__row { display: flex; gap: var(--kv-gap); align-items: baseline; font-size: var(--fs-md); padding: 3px 0; }
.pay__label { color: var(--text-muted); min-width: var(--kv-label); }
.pay__value { padding-left: var(--badge-pad); }
.pay__value.is-paid { color: var(--ok); }
.pay__value.is-unpaid { color: var(--danger); }
.card__title--icon { display: inline-flex; align-items: center; gap: 8px; }
.card__title--icon svg { color: var(--accent); }

/* Подсказки в карточке документов — одним блоком, зазор между ними 8 px. */
.card__hints { display: flex; flex-direction: column; gap: 8px; }
.card__hints .hint-strip { margin-bottom: 0; }

/* ---------- Боковое дерево настроек (03.09.2026, №10) ----------
   Заменило вкладки. Раскладка в две колонки вешается на содержимое
   страницы через :has(): дерево — первый ребёнок .content, остальные
   карточки уходят во вторую колонку. Шаблоны экранов не трогались. */
/* Обзор настроек (home.html) держит дерево внутри .settings-page, а не прямо
   в .content — там правило не срабатывало, дерево вставало блоком СВЕРХУ,
   и панели уезжали под него в самый низ страницы (снимок заказчика,
   04.09.2026). Оба контейнера — одна раскладка. */
.content:has(> .settings-tree), .settings-page:has(> .settings-tree) {
    display: grid;
    grid-template-columns: 280px minmax(0, 1fr);
    column-gap: 22px;
    align-items: start;
}
.content:has(> .settings-tree) > .settings-tree, .settings-page:has(> .settings-tree) > .settings-tree {
    grid-column: 1;
    grid-row: 1 / span 400;
    position: sticky;
    top: 16px;
    align-self: start;
}
.content:has(> .settings-tree) > :not(.settings-tree), .settings-page:has(> .settings-tree) > :not(.settings-tree) { grid-column: 2; }
.settings-tree__toggle { display: none; margin-bottom: 8px; }
.settings-tree__search { width: 100%; margin-bottom: 10px; }
.settings-tree__group { margin-bottom: 12px; }
.settings-tree__title {
    display: block;
    font-size: var(--fs-xs);
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--text-muted);
    padding: 4px 8px;
}
.settings-tree__title.is-active { color: var(--accent, #2f5fa8); }
.settings-tree__items { list-style: none; margin: 0; padding: 0; }
.settings-tree__items a {
    display: block;
    padding: 6px 10px;
    border-radius: 6px;
    color: var(--text);
    text-decoration: none;
    font-size: var(--fs-md);
}
.settings-tree__items a:hover { background: var(--surface-2, #f1f4f8); text-decoration: none; }
.settings-tree__items a.is-active {
    background: var(--accent-soft, #e6eefb);
    color: var(--accent, #2f5fa8);
    font-weight: 600;
}
.settings-tree__empty { padding: 6px 8px; }
@media (max-width: 1000px) {
    .content:has(> .settings-tree), .settings-page:has(> .settings-tree) { grid-template-columns: minmax(0, 1fr); }
    .content:has(> .settings-tree) > .settings-tree, .settings-page:has(> .settings-tree) > .settings-tree { grid-column: 1; grid-row: auto; position: static; }
    .content:has(> .settings-tree) > :not(.settings-tree), .settings-page:has(> .settings-tree) > :not(.settings-tree) { grid-column: 1; }
    .settings-tree__toggle { display: inline-flex; }
    .settings-tree.js-collapsed .settings-tree__body { display: none; }
    .settings-tree { margin-bottom: 16px; }
}

/* ---------- Свёрнутые секции форм и знак словаря (03.09.2026, №16) ----------
   Основное открыто, остальное — <details>: без JS видно всё, секция
   с ошибкой раскрывается сама (фильтр errors_in). */
.form__fold { border-top: 1px solid var(--border); margin-top: 16px; }
.form__fold > summary {
    cursor: pointer; list-style: none;
    display: flex; align-items: center; gap: 8px;
    padding: 12px 0; font-weight: 600; font-size: var(--fs-md);
}
.form__fold > summary::-webkit-details-marker { display: none; }
.form__fold > summary::before {
    content: "›"; display: inline-block; width: 12px;
    color: var(--text-faint); font-size: var(--fs-lg); line-height: 1;
    transition: transform .15s;
}
.form__fold[open] > summary::before { transform: rotate(90deg); }
.form__fold > .form__grid { padding-bottom: 10px; }
.form__fold .faint { font-weight: 400; }
.topbar__help {
    display: inline-flex; align-items: center; justify-content: center;
    width: 28px; height: 28px; border-radius: 50%;
    border: 1px solid var(--border); color: var(--text-muted);
    font-weight: 700; text-decoration: none; flex: none;
}
.topbar__help:hover { color: var(--accent, #2f5fa8); border-color: var(--accent, #2f5fa8); text-decoration: none; }
.glossary dt { font-weight: 600; margin-top: 12px; }
.glossary dd { margin: 2px 0 0; color: var(--text-muted); }
abbr[title] { text-decoration: underline dotted; cursor: help; }

/* Галочка «запомнить устройство» на экране кода входа (03.09.2026). */
.login__check { display: flex; align-items: center; gap: 10px; margin: 6px 0 14px; font-size: var(--fs-md); }
.login__check input { width: 18px; height: 18px; }

/* Переключатель языка интерфейса RU/PL в боковом меню (03.09.2026). */
/* Переключатель языка интерфейса — в правом углу шапки (05.09.2026,
   просьба заказчика; до этого стоял в меню под именем). Сегментный
   контрол на сером треке: активный язык — белая плашка с тенью.
   Акцентный синий не берётся — он занят действиями. */
.lang-switch {
    display: inline-flex; align-items: center; gap: 2px; flex: none;
    margin: 0; padding: 3px;
    border-radius: 999px;
    background: var(--surface-2);
    border: 1px solid var(--border);
}
.lang-switch__btn {
    height: 28px; padding: 0 12px;
    border: 0; border-radius: 999px;
    background: transparent; color: var(--text-muted);
    font: 700 var(--fs-xs)/1 var(--font); letter-spacing: .06em;
    cursor: pointer;
    transition: background .12s, color .12s, box-shadow .12s;
}
.lang-switch__btn:hover { color: var(--text); }
.lang-switch__btn.is-active {
    background: var(--surface); color: var(--text);
    box-shadow: 0 1px 2px rgba(20, 30, 50, .14);
    cursor: default;
}
.lang-switch__btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }
/* На экране входа (06.09.2026) — в правом верхнем углу панели формы, вне
   потока: форма остаётся отцентрованной по высоте, как была. На узком экране
   правило `.login__form-wrap > *` растягивает детей на всю ширину —
   переключателю оно не нужно. */
.login__form-wrap { position: relative; }
.login__form-wrap > .lang-switch--login {
    position: absolute; top: 20px; right: 24px;
    width: auto; max-width: none;
}


/* ==========================================================================
   Слой компонентов (04.09.2026, этап 1 по ревизии интерфейса).

   Ревизия показала: логика экранов сильная, а слоя компонентов под ней нет —
   нативные select/checkbox/date, невидимая рамка фокуса (#eff4ff на белом),
   21 кегль системного шрифта, пустые состояния жирным текстом, один синий
   на всё, «опасной» кнопки в CSS не было при трёх местах в шаблонах.

   Блок стоит в конце файла и переопределяет прежние правила теми же
   селекторами: шаблоны не тронуты, все 125 экранов смотрят на те же классы
   .control / .btn / .badge / .empty / .tile. Каркас экранов не меняется —
   меняется одежда.
   ========================================================================== */

/* ---------- Шрифты: файлы кладутся в static/fonts, до этого — системный стек.
   Manrope и IBM Plex Sans знают кириллицу и польские диакритики (OFL). ---------- */
@font-face {
    font-family: "Manrope";
    font-weight: 500 800;
    font-display: swap;
    src: local("Manrope"), url("../fonts/Manrope-Variable.ttf") format("truetype");
}
@font-face {
    font-family: "IBM Plex Sans";
    font-weight: 400;
    font-display: swap;
    src: local("IBM Plex Sans"), url("../fonts/IBMPlexSans-Regular.woff2") format("woff2");
}
@font-face {
    font-family: "IBM Plex Sans";
    font-weight: 500;
    font-display: swap;
    src: local("IBM Plex Sans Medium"), url("../fonts/IBMPlexSans-Medium.woff2") format("woff2");
}
@font-face {
    font-family: "IBM Plex Sans";
    font-weight: 600;
    font-display: swap;
    src: local("IBM Plex Sans SemiBold"), url("../fonts/IBMPlexSans-SemiBold.woff2") format("woff2");
}

/* ---------- Токены: нейтрали с холодным подтоном под акцент, роли цвета ---------- */
:root {
    --font: "IBM Plex Sans", -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    --font-display: "Manrope", "IBM Plex Sans", -apple-system, "Segoe UI", Roboto, sans-serif;

    --accent: #2456d6;
    --accent-dark: #1d47b5;
    --accent-soft: #eaf0fb;
    --head-bg: #dbe6fa;
    --head-border: #b7cbf0;

    --danger: #b42318;
    --danger-soft: #fdeceb;
    --warn: #9a5b00;
    --warn-soft: #fff4e0;
    --ok: #0b6e3a;
    --ok-soft: #e5f5ec;

    --text: #1a2233;
    --text-muted: #5d6878;
    --text-faint: #6b7688;
    --border: #e1e6ee;
    --border-strong: #cfd6e2;
    --bg: #f4f6f9;
    --surface: #ffffff;
    --surface-2: #f4f6fa;

    --radius: 12px;
    --radius-sm: 8px;
    --focus-ring: 0 0 0 3px rgba(36, 86, 214, .22);
    --focus-ring-danger: 0 0 0 3px rgba(180, 35, 24, .16);
    --shadow: 0 1px 2px rgba(20, 30, 50, .06), 0 6px 18px rgba(20, 30, 50, .08);
    --shadow-2: 0 4px 10px rgba(20, 30, 50, .10), 0 16px 40px rgba(20, 30, 50, .16);

    /* Шкала кеглей — в rem, от размера шрифта <html>: xs 12 · sm 14 · md 16 ·
       lg 18 · xl 24 · 2xl 28 · 3xl 32 при 100%. Пиксельных кеглей в интерфейсе
       больше нет (04.09.2026, «мелковато всё»): 8–11.5 стали xs, 12–12.5 — sm,
       13–14 — md, 14.5–16 — lg, 18–20 — xl, 22–27 — 2xl, 28–30 — 3xl. Лист
       письма (мм и pt) и подписи графика SVG сюда не входят. */
    --fs-xs: .75rem;
    --fs-sm: .875rem;
    --fs-md: 1rem;
    --fs-lg: 1.125rem;
    --fs-xl: 1.5rem;
    --fs-2xl: 1.75rem;
    --fs-3xl: 2rem;
}

/* Единственная ручка масштаба интерфейса: 100% = 16px. Крупнее или мельче
   всё разом — здесь, а не по кеглям. */
html { font-size: 100%; }

body { font: var(--fs-md)/1.5 var(--font); }
.topbar__title, .card__title, .tile__value, .sidebar__brand-name,
.state-tier__title, .login h1, .login h2, .form__section, .settings-tree__title {
    font-family: var(--font-display);
    letter-spacing: -.01em;
}
.topbar__title { font-size: var(--fs-xl); font-weight: 700; }
.card__title { font-size: var(--fs-lg); font-weight: 700; }
.form__label { font-size: var(--fs-sm); font-weight: 500; color: var(--text-muted); }
.form__hint { font-size: var(--fs-sm); }
.form__errors { font-size: var(--fs-sm); display: flex; align-items: flex-start; gap: 6px; margin-top: 4px; }
.form__errors::before {
    content: ""; flex: none; width: 14px; height: 14px; margin-top: 2px;
    background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23b42318' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><circle cx='12' cy='12' r='9'/><path d='M12 8v5M12 16h.01'/></svg>") no-repeat center / contain;
}

/* ---------- Фокус: виден везде, одним правилом ---------- */
a:focus-visible, summary:focus-visible, [tabindex]:focus-visible {
    outline: 3px solid rgba(36, 86, 214, .35);
    outline-offset: 2px;
    border-radius: 4px;
}
.btn:focus-visible, .control:focus-visible, .tile:focus-visible,
input:focus-visible, select:focus-visible, textarea:focus-visible {
    outline: none;
    box-shadow: var(--focus-ring);
}

/* ---------- Поля ввода ---------- */
.control {
    height: 44px;
    padding: 0 14px;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    background: var(--surface);
    color: var(--text);
    font: var(--fs-md)/1.4 var(--font);
    transition: border-color .15s, box-shadow .15s;
}
.control:hover { border-color: #aab5c6; }
.control:focus { outline: none; border-color: var(--accent); box-shadow: var(--focus-ring); }
.control::placeholder { color: #9aa6b8; }
.control:disabled, .control[readonly] { background: var(--surface-2); color: var(--text-muted); }
textarea.control { height: auto; min-height: 108px; padding: 10px 14px; line-height: 1.5; }
.control--sm { height: 36px; padding: 0 12px; font-size: var(--fs-sm); }

/* Выпадающий список: своя стрелка вместо стрелки операционной системы. */
select.control, .topbar__search select, select.settings-tree__search {
    appearance: none;
    -webkit-appearance: none;
    padding-right: 36px;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%235d6878' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><path d='m6 9 6 6 6-6'/></svg>");
    background-repeat: no-repeat;
    background-position: right 12px center;
    cursor: pointer;
}
select.control[multiple] { height: auto; background-image: none; padding: 6px 8px; }
select.control:disabled { cursor: default; }

/* Дата и время: нативный календарь остаётся, но поле одной высоты с прочими,
   а иконка календаря — серая, не чёрная. */
input[type="date"].control, input[type="time"].control, input[type="datetime-local"].control {
    padding-right: 10px;
}
input[type="date"].control::-webkit-calendar-picker-indicator,
input[type="time"].control::-webkit-calendar-picker-indicator,
input[type="datetime-local"].control::-webkit-calendar-picker-indicator {
    opacity: .55; cursor: pointer;
}

/* Поле с ошибкой: красная рамка и кольцо — не только текст под полем. */
.form__field:has(.form__errors) .control,
.form__field:has(.form__errors) select,
.form__field:has(.form__errors) input:not([type="checkbox"]):not([type="radio"]) {
    border-color: var(--danger);
    box-shadow: var(--focus-ring-danger);
}

/* ---------- Галочки и переключатели ---------- */
input[type="checkbox"], input[type="radio"] {
    appearance: none;
    -webkit-appearance: none;
    flex: none;
    width: 20px; height: 20px;
    margin: 0;
    border: 1.5px solid #9aa6b8;
    border-radius: 5px;
    background: var(--surface);
    display: inline-grid;
    place-items: center;
    vertical-align: -3px;
    cursor: pointer;
    transition: background .15s, border-color .15s, box-shadow .15s;
}
input[type="radio"] { border-radius: 50%; }
input[type="checkbox"]:hover, input[type="radio"]:hover { border-color: var(--accent); }
input[type="checkbox"]:checked, input[type="radio"]:checked { background: var(--accent); border-color: var(--accent); }
input[type="checkbox"]:checked::after {
    content: ""; width: 6px; height: 11px; margin-top: -2px;
    border: solid #fff; border-width: 0 2px 2px 0; transform: rotate(45deg);
}
input[type="radio"]:checked::after { content: ""; width: 8px; height: 8px; border-radius: 50%; background: #fff; }
input[type="checkbox"]:disabled, input[type="radio"]:disabled { background: var(--surface-2); border-color: var(--border-strong); cursor: default; }
input[type="checkbox"]:focus-visible, input[type="radio"]:focus-visible { box-shadow: var(--focus-ring); }

.form__check { display: flex; gap: 10px; align-items: center; font-size: var(--fs-md); color: var(--text); cursor: pointer; }
.form__check input { margin-top: 0; }
.form__check .form__label { font-size: var(--fs-md); font-weight: 500; color: var(--text); }
.form__check .form__hint { margin-top: 1px; }
/* Галочка с подсказкой под ней: подпись и подсказка — колонкой, галочка — сверху по строке подписи. */
.form__field--check .form__check { align-items: flex-start; }
.form__field--check .form__check input { margin-top: 2px; }

/* Переключатель «включено / выключено» — для настроек-режимов.
   Ставится на .form__check классом form__check--switch (виджет с data-switch). */
.form__check--switch input[type="checkbox"] {
    width: 44px; height: 24px; border-radius: 999px; border: none; background: #c9d1de; position: relative;
}
.form__check--switch input[type="checkbox"]::after {
    content: ""; position: absolute; top: 2px; left: 2px; width: 20px; height: 20px;
    border-radius: 50%; background: #fff; box-shadow: 0 1px 2px rgba(0, 0, 0, .25);
    border: none; transform: none; margin: 0; transition: transform .15s;
}
.form__check--switch input[type="checkbox"]:checked { background: var(--accent); }
.form__check--switch input[type="checkbox"]:checked::after { transform: translateX(20px); }

/* Знак «?» у подписи: круг 16 px, читается как кнопка, а не как опечатка. */
.form__help-mark {
    width: 18px; height: 18px; border-radius: 50%;
    font-size: var(--fs-xs); font-weight: 700; line-height: 1;
    display: inline-grid; place-items: center;
    border: 1px solid var(--border-strong); color: var(--text-muted); background: var(--surface);
    margin-left: 4px; cursor: help; vertical-align: 1px;
}
.form__help-mark:hover { background: var(--accent); border-color: var(--accent); color: #fff; }

/* ---------- Кнопки: пять ролей, два размера ---------- */
.btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 8px;
    height: 42px; padding: 0 16px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border-strong);
    background: var(--surface);
    color: var(--text);
    font: 500 var(--fs-md)/1 var(--font);
    cursor: pointer;
    white-space: nowrap;
    text-decoration: none;
    transition: background .12s, border-color .12s, color .12s, transform .06s, box-shadow .12s;
}
.btn svg { width: 18px; height: 18px; flex: none; }
.btn:hover { background: var(--surface-2); border-color: #b8c2d1; text-decoration: none; }
.btn:active { transform: translateY(1px); }
.btn--primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.btn--primary:hover { background: var(--accent-dark); border-color: var(--accent-dark); }
.btn--danger { background: #fff5f4; border-color: #f2c4bf; color: var(--danger); }
.btn--danger:hover { background: var(--danger-soft); border-color: #e59d96; color: #8f1c14; }
.btn--ghost { background: transparent; border-color: transparent; color: var(--text-muted); }
.btn--ghost:hover { background: var(--surface-2); border-color: transparent; color: var(--text); }
.btn--sm { height: 34px; padding: 0 12px; font-size: var(--fs-sm); gap: 6px; }
.btn--sm svg { width: 16px; height: 16px; }
.btn[disabled], .btn[aria-disabled="true"], .btn[aria-busy="true"] {
    opacity: .6; cursor: default; pointer-events: none;
}
/* Кнопка отправки, пока форма уходит: скрипт ставит aria-busy — текст
   остаётся, справа появляется вращающееся кольцо. */
.btn[aria-busy="true"]::after {
    content: ""; width: 14px; height: 14px; border-radius: 50%;
    border: 2px solid currentColor; border-right-color: transparent;
    animation: btn-spin .7s linear infinite;
}
@keyframes btn-spin { to { transform: rotate(360deg); } }

/* ---------- Бейджи: точка-маркер у состояний, чтобы читалось и без цвета ---------- */
/* Цвет здесь НЕ задаётся: правило стоит позже вариантов .badge--ok/--warn/
   --danger/--accent при той же специфичности и перебивало их — все состояния
   («отправлен», «проверен») стали серыми (замечание заказчика 04.09.2026).
   Нейтральный фон остаётся у базового .badge выше по файлу. */
.badge {
    height: 24px; padding: 0 var(--badge-pad);
    font-size: var(--fs-sm); font-weight: 600; letter-spacing: .01em;
}
.badge--ok::before, .badge--warn::before, .badge--danger::before, .badge--accent::before {
    content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: none;
}

/* ---------- Таблицы и списки ---------- */
.table th { font-size: var(--fs-xs); font-weight: 600; letter-spacing: .05em; color: var(--text-muted); background: var(--surface-2); }
.table tbody tr:hover { background: #f7f9fc; }
.table tbody tr[data-href]:hover { background: var(--accent-soft); }
.table td, .table th { font-variant-numeric: tabular-nums; }
.cell-sub { font-size: var(--fs-sm); }

/* ---------- Плитки главной ---------- */
.tile { transition: transform .12s, box-shadow .12s, border-color .12s; }
.tile:hover { transform: translateY(-1px); box-shadow: var(--shadow); }
.tile__label { font-size: var(--fs-sm); font-weight: 500; }
.tile__value { font-size: var(--fs-3xl); font-weight: 700; letter-spacing: -.02em; }
.tile__hint { font-size: var(--fs-sm); }
/* Ноль не соревнуется с ненулём: плитка без работы приглушена. */
.tile--zero .tile__value { color: var(--text-faint); }
.tile--zero .tile__label, .tile--zero .tile__hint { color: var(--text-faint); }

/* ---------- Пустое состояние: спокойный знак, заголовок, строка, действие ---------- */
.empty {
    padding: 28px 18px;
    text-align: center;
    color: var(--text-muted);
    font-size: var(--fs-md);
    line-height: 1.5;
}
.empty::before {
    content: ""; display: block; width: 32px; height: 32px; margin: 0 auto 10px;
    background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239aa6b8' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'><path d='M4 13h4l2 3h4l2-3h4'/><path d='M5 5h14l2 8v6H3v-6z'/></svg>") no-repeat center / contain;
}
.empty strong { display: block; color: var(--text); font: 600 var(--fs-lg)/1.3 var(--font-display); margin-bottom: 4px; }
.empty .btn { margin-top: 12px; }

/* ---------- Сообщения после действий: уведомление в углу, не полоса над всем ---------- */
.messages {
    position: fixed; right: 24px; bottom: 24px; z-index: 80;
    display: grid; gap: 8px; width: min(420px, calc(100vw - 32px));
    margin: 0;
}
.message {
    display: flex; align-items: flex-start; gap: 10px;
    padding: 12px 14px 12px 16px;
    border-radius: 10px;
    border: 1px solid transparent;
    background: var(--surface);
    box-shadow: var(--shadow-2);
    font-size: var(--fs-md);
    animation: toast-in .18s ease-out;
}
.message::before {
    content: ""; flex: none; width: 8px; height: 8px; border-radius: 50%; margin-top: 6px; background: currentColor;
}
.message--success { background: var(--ok-soft); color: var(--ok); border-color: #b7e4c7; }
.message--warning { background: var(--warn-soft); color: var(--warn); border-color: #f5d9a4; }
.message--error { background: var(--danger-soft); color: var(--danger); border-color: #f2c4bf; }
.message--info { background: var(--accent-soft); color: var(--accent-dark); border-color: #c7d7f5; }
.message.is-leaving { opacity: 0; transform: translateY(6px); transition: opacity .25s, transform .25s; }
@keyframes toast-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@media (max-width: 720px) { .messages { right: 12px; left: 12px; bottom: 12px; width: auto; } }
@media (prefers-reduced-motion: reduce) {
    .message, .btn, .tile, .control, input[type="checkbox"], input[type="radio"] { transition: none !important; animation: none !important; }
}

/* Кнопка сворачивания дерева настроек: правило .btn ниже по файлу возвращало
   ей display, и она показывалась на широком экране. Повтор правила после слоя.
   */
.settings-tree__toggle { display: none; }
@media (max-width: 1000px) { .settings-tree__toggle { display: inline-flex; } }

/* Пустое состояние внутри ленты (события дела): слева, без знака — знак
   в центре над левым текстом читался как чужой элемент (снимок 04.09.2026). */
.empty--inline { text-align: left; padding: 8px 0; }
.empty--inline::before { display: none; }


/* ---------- Этап 2 ревизии (04.09.2026): иконки, меню в строке, подсказки, подтверждение ---------- */
.icon { width: 18px; height: 18px; flex: none; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.btn--sm .icon { width: 16px; height: 16px; }

/* Меню «⋯» в строке списка: кнопки форм выглядят как пункты меню. */
.menu--row { display: inline-block; }
.menu--row .menu__toggle { height: 34px; padding-inline: 10px; font-size: var(--fs-lg); letter-spacing: 0; }
.menu__list form { margin: 0; }
.menu__list form button {
    display: block; width: 100%; text-align: left;
    padding: 8px 14px; border: 0; background: transparent;
    font: 500 var(--fs-md)/1.3 var(--font); color: var(--text); cursor: pointer;
}
.menu__list form button:hover { background: var(--surface-2); }
.menu__list form button.menu__danger { color: var(--danger); }
.menu__list form button.menu__danger:hover { background: var(--danger-soft); }

/* Ярус состояния на главной: заголовок и строка «активных дел» в одной шапке. */
.state-tier__head { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin: 24px 0 12px; }
.state-tier__head .state-tier__title { margin: 0; }
.state-tier__note { font-size: var(--fs-sm); color: var(--text-muted); text-decoration: none; }
.state-tier__note b { color: var(--text); font-family: var(--font-display); font-size: var(--fs-lg); }
.state-tier__note:hover { color: var(--text); text-decoration: none; }

/* Подсказка «?»: всплывающий блок по клику и по фокусу, Esc закрывает. */
.form__field-head { position: relative; }
.form__help-mark[aria-expanded="true"] { background: var(--accent); border-color: var(--accent); color: #fff; }
.form__help-pop {
    position: absolute; z-index: 30; left: 0; top: calc(100% + 6px);
    max-width: 320px; padding: 10px 12px;
    background: var(--text); color: #fff;
    font: 400 var(--fs-sm)/1.45 var(--font);
    border-radius: 8px; box-shadow: var(--shadow-2);
    animation: toast-in .12s ease-out;
}
.form__help-pop::before {
    content: ""; position: absolute; top: -5px; left: 14px;
    width: 10px; height: 10px; background: var(--text); transform: rotate(45deg);
}

/* Диалог подтверждения: коротко, с последствиями, опасная кнопка справа. */
.confirm {
    border: 0; border-radius: 14px; padding: 0; width: min(440px, calc(100vw - 32px));
    box-shadow: var(--shadow-2); color: var(--text); background: var(--surface);
}
.confirm::backdrop { background: rgba(20, 30, 50, .45); }
.confirm__body { display: flex; gap: 12px; padding: 22px 22px 6px; }
.confirm__icon { width: 24px; height: 24px; color: var(--warn); margin-top: 2px; }
.confirm__text { margin: 0; font-size: var(--fs-lg); line-height: 1.5; }
.confirm__actions { display: flex; justify-content: flex-end; gap: 8px; padding: 14px 22px 20px; }


/* ---------- Этап 3 ревизии (04.09.2026): телефон 375px по замеру снимков ----------
   Замер: страница уезжала вбок на 85px («Сегодня», меню-полоса не сжималась)
   и на 479px (карточка клиента, ряд кнопок в одну строку); логотип 140px
   держал в полосе меню 166px высоты; переключатель статуса, шапки карточек
   и кнопки форм не переносились. Таблицы в порядке — .table-wrap прокручивает. */
@media (max-width: 1000px) {
    .sidebar__logo { width: 36px; height: 36px; margin: 0; }
    .sidebar__brand { padding: 8px 14px; }
    .sidebar__user { padding: 8px 14px; border-bottom: 0; }
    /* Меню — своя строка во всю ширину, прокручивается внутри себя:
       без min-width: 0 flex-элемент не сжимается уже содержимого,
       и прокрутка не включалась никогда. */
    .nav { flex: 1 1 100%; min-width: 0; order: 3; }
    .sidebar__foot { margin-left: auto; }
    .page-actions { flex-wrap: wrap; }
}
@media (max-width: 640px) {
    .content { padding: 14px 12px 40px; }
    .topbar { padding: 10px 12px; }
    .topbar__right { flex-wrap: wrap; row-gap: 8px; }
    .topbar__search { flex: 1 1 160px; }
    /* Дату телефон показывает сам. */
    .topbar__date { display: none; }
    .topbar > :first-child { max-width: 100%; }
    .card__head { flex-wrap: wrap; }
    .card__actions { flex-wrap: wrap; row-gap: 6px; }
    .form__actions { flex-wrap: wrap; }
    .status-switch { flex-wrap: wrap; }
    .status-switch .control--sm { min-width: 0; flex: 1 1 160px; }
    /* Полоса «собрано, но не отправлено»: выбор канала, номер письма и кнопка
       в одну строку — 620px в полосе 313 (замер 04.09.2026 на 375px). */
    .hint-strip { flex-wrap: wrap; }
    .hint-strip form { flex: 1 1 100%; min-width: 0; flex-wrap: wrap; }
    .hint-strip .control--sm { width: auto; min-width: 0; flex: 1 1 160px; }
    .confirm__body { padding: 18px 16px 4px; }
    .confirm__actions { padding: 12px 16px 16px; }
}

/* Перебивка каскада слоем (найдена прогоном 04.09.2026 вслед за бейджами):
   .form__check в слое стоит позже .form__check--inline и делал галочку
   «в строке» блочной. Повтор варианта после слоя. */
.form__check--inline { display: inline-flex; gap: 5px; }

/* Полоса прокрутки резервирует место всегда: страница короче окна теряла
   её, и всё содержимое сдвигалось на ширину полосы при переходе между
   экранами — «дёргается при переключении» (заказчик, 04.09.2026). */
html { scrollbar-gutter: stable; }


/* ---------- Письмо правится на листе (04.09.2026) ----------
   Лист крупнее — теперь это редактор, а не предпросмотр; правая колонка
   узкая: действия и свёрнутые поля. Текст блоков редактируется на месте,
   ярлык блока стал ручкой перетаскивания — сам текст занят курсором. */
.letter-edit {
    --sheet-zoom: .95;
    grid-template-columns: calc(210mm * var(--sheet-zoom) + 4px) minmax(260px, 1fr);
}
@media (max-width: 1750px) { .letter-edit { --sheet-zoom: .82; } }
@media (max-width: 1500px) { .letter-edit { --sheet-zoom: .7; } }
@media (max-width: 1300px) { .letter-edit { --sheet-zoom: .6; } }
@media (max-width: 1200px) { .letter-edit { grid-template-columns: 1fr; --sheet-zoom: .55; } }
/* Шаблон письма стоит рядом с деревом настроек (302px), а зум листа считался
   от ширины окна: при 1400px лист .7 просил 844px на 762 доступных, и страница
   прокручивалась вбок (замер 04.09.2026). Пороги с поправкой на дерево;
   ниже 1365px палитра уходит под лист. */
@media (max-width: 1750px) { .content:has(> .settings-tree) .letter-edit { --sheet-zoom: .7; } }
@media (max-width: 1500px) { .content:has(> .settings-tree) .letter-edit { --sheet-zoom: .55; } }
@media (max-width: 1365px) { .content:has(> .settings-tree) .letter-edit { grid-template-columns: 1fr; --sheet-zoom: .55; } }

.sheet-block { cursor: default; }
.sheet-block__text[contenteditable], .sheet-block__extra[contenteditable] {
    cursor: text; outline: none; min-height: 1em; border-radius: 1px;
}
.sheet-block__text[contenteditable]:focus, .sheet-block__extra[contenteditable]:focus {
    background: rgba(36, 86, 214, .06);
    box-shadow: 0 0 0 1.5mm rgba(36, 86, 214, .06);
}
/* Пустая строка блока остаётся кликабельной и подписанной: иначе стёртый
   адрес нечем вернуть, кроме кнопки. */
.sheet-block__text[contenteditable]:empty::before, .sheet-block__extra[contenteditable]:empty::before {
    content: attr(data-placeholder); color: #9aa3b2;
    font-family: var(--font); font-size: 8pt; font-weight: 400;
}
/* Ярлык — ручка: над ним курсор «рука», сам он ловит мышь. */
.sheet-block__tag.js-handle { pointer-events: auto; cursor: grab; }
.sheet-block.is-dragging .sheet-block__tag { cursor: grabbing; }
/* Переписанный блок помечен, как подвинутый: через месяц должно быть
   видно, почему это письмо не как остальные и что вернёт «как было». */
.sheet-block.is-overridden .sheet-block__tag::after { content: " · текст изменён"; }
.sheet-tools [hidden] { display: none !important; }
.sheet-tools__date { height: 28px; width: 150px; padding: 0 8px; font-size: 12px; }
.sheet-sign__title { font-weight: 400; }
.sheet-block[data-key="title"] .sheet-block__text { text-transform: uppercase; }

.letter-fields__summary { list-style: none; cursor: pointer; display: flex; align-items: center; gap: 10px; }
.letter-fields__summary::-webkit-details-marker { display: none; }
.letter-fields__summary::before { content: "▸"; color: var(--text-muted); font-size: var(--fs-sm); }
.letter-fields[open] > .letter-fields__summary::before { content: "▾"; }
.letter-fields:not([open]) > .letter-fields__summary { border-bottom: 0; }


/* ---------- Шаблон письма на листе: чипы подстановок (04.09.2026) ---------- */
/* Строчный, не inline-block: многострочный пример («ul. Przykładowa 1 m. 2 /
   00-001 Warszawa») иначе рос выше строки и наезжал на соседний текст;
   без user-select: none — с ним Backspace не удалял чип. */
.ph {
    display: inline; padding: 0 .35em; margin: 0 .05em; border-radius: 3px;
    -webkit-box-decoration-break: clone; box-decoration-break: clone;
    background: var(--accent-soft); color: var(--accent-dark);
    font-family: var(--font); font-size: .82em; font-weight: 500;
    white-space: normal; cursor: default;
}
.ph::before { content: attr(data-label); }
.ph--unknown { background: var(--danger-soft); color: var(--danger); }
.ph--unknown::before { content: "{" attr(data-key) "}"; }
/* Режим «с примером»: вместо названия — придуманные данные образца. */
.is-sample .ph { background: #fff3cd; color: #5a4300; font-family: inherit; font-size: inherit; font-weight: inherit; white-space: pre-line; }
.is-sample .ph::before { content: attr(data-sample); }
.is-sample .ph[data-sample=""]::before { content: attr(data-label); }
.is-sample .ph--unknown::before { content: "{" attr(data-key) "}"; }
/* Блоки бланка на листе шаблона: показаны, но не правятся здесь. */
.sheet-block.is-fixed { cursor: help; }
.sheet-block.is-fixed:hover { outline-color: transparent; background: rgba(0, 0, 0, .025); }
.js-template-form .sheet-block__text[data-single-line] { white-space: nowrap; overflow: hidden; }
.js-template-form .sheet-block[data-key="title"] .sheet-block__text { white-space: normal; }


/* ---------- Настройки: крошки, свёртка дерева, формы блоками (05.09.2026) ----------
   По разбору концепта заказчика: иерархия важнее декора. Крошки — путь без
   текущей страницы (её называет заголовок), дерево показывает одну строку
   на группу, форма справочника — карточки-блоки с липкой полосой действий. */
.crumbs {
    display: flex; flex-wrap: wrap; align-items: center; gap: 2px 8px;
    margin-bottom: 4px;
    font-size: var(--fs-sm); color: var(--text-muted);
}
.crumbs a { color: var(--text-muted); text-decoration: none; }
.crumbs a:hover { color: var(--accent); text-decoration: none; }
.crumbs__sep { color: var(--text-faint); }

.settings-tree__group { margin-bottom: 4px; }
summary.settings-tree__title {
    display: flex; align-items: center; gap: 8px;
    list-style: none; cursor: pointer;
    padding: 8px 10px; border-radius: 6px;
    color: var(--text); font-size: var(--fs-md); font-weight: 600;
    letter-spacing: 0; text-transform: none;
}
summary.settings-tree__title::-webkit-details-marker { display: none; }
summary.settings-tree__title::before {
    content: "›"; display: inline-block; width: 10px;
    color: var(--text-faint); font-size: var(--fs-lg); line-height: 1;
    transition: transform .15s;
}
.settings-tree__group[open] > summary.settings-tree__title::before { transform: rotate(90deg); }
summary.settings-tree__title:hover { background: var(--surface-2); }
summary.settings-tree__title.is-active { color: var(--accent); }
/* Название группы — ссылка на её обзор (как вкладка до 03.09), стрелка и остальная строка сворачивают. */
summary.settings-tree__title a { color: inherit; text-decoration: none; }
summary.settings-tree__title a:hover { color: var(--accent); }
.settings-tree__count {
    margin-left: auto;
    font-size: var(--fs-xs); font-weight: 600; color: var(--text-faint);
}
.settings-tree__items { padding-left: 18px; margin: 2px 0 6px; }

/* Форма справочника: блоки-карточки на фоне страницы, а не карточка в карточке.
   Ширина — вся колонка, как у остальных экранов (02.10.2026): предел 1160px
   оставлял на мониторе 2000px полосу пустоты справа от формы, а формы
   соседствуют на странице с блоками во всю ширину — край выходил рваным.
   Строки полей при этом доходят до правого края сами (`crmFormRows`
   в app.js), поэтому длинных пустых хвостов в широкой форме нет. */
.form-page { max-width: none; }
.form-page.form-page--blocks { background: transparent; border: 0; box-shadow: none; overflow: visible; }
.form-page--blocks .card__body { padding: 0; }  /* и вложенный: у типа документа тело карточки внутри обёртки */
.form-page--blocks .form__block {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: 18px 20px 8px;
    margin-bottom: 14px;
}
.form-page--blocks .form__block-title {
    margin: 0 0 14px;
    font: 600 var(--fs-lg)/1.3 var(--font-display);
    letter-spacing: -.01em;
}
.form-page--blocks .form__fold { border-top: 0; margin-top: 0; padding-top: 0; padding-bottom: 0; }
.form-page--blocks .form__fold > summary { padding: 6px 0 10px; font-size: var(--fs-lg); font-family: var(--font-display); }
.form-page--blocks .form__fold[open] > summary { padding-bottom: 12px; }
.form-page--blocks .form__nonfield { margin-bottom: 14px; }
/* Полоса действий липнет к низу окна у любой формы: у длинной «Сохранить»
   всегда под рукой. Главное действие — справа, отмена левее, удаление
   у левого края. `.card` режет overflow, а липкость считается от ближайшего
   прокручиваемого предка — форме-карточке overflow возвращается. */
.card.form-page { overflow: visible; }
.form-page .form__actions {
    position: sticky; bottom: 0; z-index: 3;
    justify-content: flex-end;
    border-radius: 0 0 var(--radius) var(--radius);
}
.form-page .form__actions .btn--primary { order: 2; }
/* То же правило для небольших форм в колонках (семейная группа): главное справа. */
.form__actions--end { justify-content: flex-end; }
.form__actions--end .btn--primary { order: 2; }
.form-page .form__actions .btn--danger { margin-right: auto; }
.form-page--blocks .form__actions {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: 12px 20px;
}


/* ---------- Документы в деле: статус одной строкой, ряд по верхней линии (06.09.2026) ----------
   Снимок заказчика 05.09.2026: «принят автоматически» ломался на две строки.
   Причина глубже подписи: слой компонентов (04.09) зафиксировал бейджу
   height: 24px, а `.table--fixed .badge { white-space: normal }` (22.08)
   разрешил перенос — две строки текста вылезали ИЗ плашки поверх соседей.
   Замерено: scrollHeight 44 при height 24 у каждого переносимого бейджа. */
.table--fixed .badge {
    height: auto; min-height: 24px;
    padding-top: 2px; padding-bottom: 2px;
    line-height: 1.3; text-align: left;
}
/* Ячейки таблицы документов — по верхней линии, не по центру: название
   занимает до трёх строк (документ, период, «Для e-Doręczenia»), и бейджи
   «по центру» висели посреди ряда, а не на одной линии с названием.
   Боковые отступы 18 → 12: семь колонок в 1000px, каждой нужны эти 12. */
.table--docs td, .table--docs th { padding-left: 12px; padding-right: 12px; }
.table--docs td { vertical-align: top; }
/* Кегль бейджа в этой таблице — xs: при sm «требует проверки» (126px)
   и «нужно заверить» (96px) занимали ровно ширину ячейки и ломались
   на две строки даже после расширения колонок (замер 06.09.2026). */
.table--docs .badge { font-size: var(--fs-xs); }
/* Имя проверившего — текстом, не плашкой: имя не состояние, а в плашке
   «Anna Wzorcowa» не помещалось в 116px и шло второй строкой. */
.table--docs .cell-who { display: block; font-size: var(--fs-sm); color: var(--ok); font-weight: 600; margin-bottom: 4px; }
.table--docs td > .badge:first-child,
.table--docs td > a.badge:first-child { margin-top: -1px; }
/* Принят без подписи сотрудника: пунктир вместо заливки — состояние
   временное, «Подтвердить» стоит в той же строке. */
.badge--auto {
    background: transparent; color: var(--text-muted);
    box-shadow: inset 0 0 0 1px var(--border-strong);
    border: 0;
}


/* ---------- Ссылка на бота — кнопкой (06.09.2026) ---------- */
.copy-link { margin-top: 12px; display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.copy-link__source { font-size: var(--fs-xs); overflow-wrap: anywhere; color: var(--text-muted); }
.btn.is-copied { color: var(--ok); border-color: var(--ok); }


/* ---------- Быстрая карточка: цена свёрнута (06.09.2026) ---------- */
.price-fold__details { min-height: 44px; }
.price-fold__summary {
    list-style: none; cursor: pointer;
    display: flex; align-items: center; gap: 10px;
    min-height: 44px; padding: 0 2px;
    font-size: var(--fs-md);
}
.price-fold__summary::-webkit-details-marker { display: none; }
.price-fold__value { color: var(--text-muted); }
.price-fold__value.is-known { color: var(--text); font-weight: 600; font-variant-numeric: tabular-nums; }
.price-fold__edit { color: var(--accent); font-size: var(--fs-sm); text-decoration: underline; text-underline-offset: 2px; }
.price-fold__details[open] > .price-fold__summary { min-height: 28px; margin-bottom: 4px; }
.price-fold__details[open] .price-fold__edit { display: none; }


/* ---------- Календарь flatpickr — в цветах интерфейса (06.09.2026) ----------
   Библиотека даёт свой синий и свой шрифт; здесь только то, что расходится
   с токенами: акцент, кегль, скругление, тень. Видимое поле календаря — это
   обычный .control: класс переезжает с исходного поля (app.js). */
.flatpickr-calendar {
    font-family: var(--font); font-size: var(--fs-md);
    border-radius: 10px; border: 1px solid var(--border);
    box-shadow: 0 12px 32px rgba(16, 24, 40, .16);
}
.flatpickr-calendar.arrowTop::before, .flatpickr-calendar.arrowTop::after,
.flatpickr-calendar.arrowBottom::before, .flatpickr-calendar.arrowBottom::after { display: none; }
.flatpickr-months .flatpickr-month, .flatpickr-current-month { color: var(--text); font-weight: 600; }
.flatpickr-current-month .flatpickr-monthDropdown-months { font-weight: 600; font-family: var(--font); }
.flatpickr-current-month input.cur-year { font-family: var(--font); font-weight: 600; }
.flatpickr-months .flatpickr-prev-month:hover svg, .flatpickr-months .flatpickr-next-month:hover svg { fill: var(--accent); }
span.flatpickr-weekday { color: var(--text-muted); font-weight: 600; font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: .04em; }
.flatpickr-day { color: var(--text); border-radius: 8px; font-variant-numeric: tabular-nums; }
.flatpickr-day:hover, .flatpickr-day:focus, .flatpickr-day.prevMonthDay:hover, .flatpickr-day.nextMonthDay:hover { background: var(--accent-soft); border-color: var(--accent-soft); color: var(--accent-dark); }
.flatpickr-day.today { border-color: var(--accent); }
.flatpickr-day.today:hover, .flatpickr-day.today:focus { background: var(--accent-soft); color: var(--accent-dark); }
.flatpickr-day.selected, .flatpickr-day.startRange, .flatpickr-day.endRange,
.flatpickr-day.selected:hover, .flatpickr-day.selected:focus { background: var(--accent); border-color: var(--accent); color: #fff; }
.flatpickr-day.flatpickr-disabled, .flatpickr-day.prevMonthDay, .flatpickr-day.nextMonthDay { color: var(--text-faint); }
.flatpickr-time input, .flatpickr-time .flatpickr-time-separator, .flatpickr-time .flatpickr-am-pm { color: var(--text); font-family: var(--font); }
.flatpickr-time input:hover, .flatpickr-time input:focus { background: var(--accent-soft); }
/* Скрытое исходное поле не должно занимать место в сетке формы. */
.form__field-body > input.flatpickr-input[type="hidden"] { display: none; }


/* ---------- Редакторы письма и шаблона: сетка и симметрия (06.09.2026) ----------
   Замечание заказчика по снимку шаблона письма: справа палитра на весь экран,
   под ней форма, ещё ниже поля — колонки не выровнены. Теперь: инструменты
   у листа двумя рядами (блок / текст), правая колонка — стопка карточек
   одной ширины: форма, палитра свёрнутыми группами, поля. */
.letter-edit__textcol { display: flex; flex-direction: column; gap: 20px; min-width: 0; }
.letter-edit__textcol > .card { margin: 0; }
.letter-edit { grid-template-columns: calc(210mm * var(--sheet-zoom) + 4px) minmax(360px, 1fr); }
@media (max-width: 1200px) { .letter-edit { grid-template-columns: 1fr; } }
/* Рядом с деревом настроек (302px) на 1400px правой колонке остаётся ~300px:
   лист ужимается до .5, колонке — минимум 300 (замер 06.09.2026: при 360
   страница прокручивалась вбок на 31px). Сетка формы сама переходит
   в одну колонку по ширине контейнера. */
@media (max-width: 1500px) {
    .content:has(> .settings-tree) .letter-edit {
        --sheet-zoom: .5;
        grid-template-columns: calc(210mm * var(--sheet-zoom) + 4px) minmax(300px, 1fr);
    }
}
@media (max-width: 1365px) { .content:has(> .settings-tree) .letter-edit { grid-template-columns: 1fr; } }
/* Второй ряд инструментов — про текст: без заливки, чтобы ряды читались
   как два, а не как одна толстая полоса. */
.sheet-tools--text { background: var(--surface); padding-top: 6px; padding-bottom: 6px; }
.sheet-tools--text .marktools { margin: 0; }
.sheet-tools { flex-wrap: wrap; row-gap: 6px; }
/* Палитра подстановок — группы <details>: открыта одна, остальные строкой
   с числом ключей. Без JS работает само. */
.palette { padding-top: 6px; padding-bottom: 6px; }
.palette__group + .palette__group { border-top: 1px solid var(--border); }
.palette__summary {
    list-style: none; cursor: pointer;
    display: flex; align-items: center; gap: 8px;
    min-height: 40px; padding: 4px 0;
    font-size: var(--fs-md); font-weight: 600; color: var(--text);
}
.palette__summary::-webkit-details-marker { display: none; }
.palette__summary::before { content: "▸"; color: var(--text-muted); font-size: var(--fs-sm); width: 12px; }
.palette__group[open] > .palette__summary::before { content: "▾"; }
.palette__count {
    margin-left: auto; min-width: 22px; height: 22px; padding: 0 7px;
    border-radius: 999px; background: var(--surface-2); color: var(--text-muted);
    font-size: var(--fs-xs); font-weight: 600; display: inline-flex; align-items: center; justify-content: center;
}
.palette__chips { padding: 2px 0 12px 20px; }
.kv--tight { row-gap: 4px; }


/* ---------- Карточка рассылки: текст по языкам и получатели (06.09.2026) ---------- */
/* Две равные колонки: справа таблица из четырёх столбцов, ей нужно
   не меньше, чем тексту слева (замер 06.09.2026: при 40% таблица
   результатов уходила в горизонтальную прокрутку). */
.cols--broadcast { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
.table--recipients td, .table--recipients th, .table--results td, .table--results th { padding-left: 12px; padding-right: 12px; }
@media (max-width: 1100px) { .cols--broadcast { grid-template-columns: minmax(0, 1fr); } }
.tabs--lang { margin-bottom: 14px; }
.tabs--lang a { display: inline-flex; align-items: center; gap: 6px; font-variant-numeric: tabular-nums; }
.tabs__dot { font-size: 8px; color: var(--accent); }
.lang-card { border: 1px solid var(--border); border-radius: 10px; padding: 14px 16px; }
.lang-card + .lang-card { margin-top: 12px; }
.lang-card__head { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-bottom: 10px; }
.lang-card__copy { margin-left: auto; }
.lang-card__subject { font-weight: 600; margin-bottom: 6px; }
.lang-card__body { white-space: normal; line-height: 1.55; }
.lang-card__note { margin-top: 12px; font-size: var(--fs-sm); }
.table--recipients .table__num { width: 44px; }
.recipients-count { font-size: var(--fs-sm); color: var(--text-muted); font-variant-numeric: tabular-nums; }


/* ---------- Стартовый экран первого визита (06.09.2026, макет заказчика) ----------
   Степпер из трёх шагов, карточки шагов с отметкой внизу, справа — клиент
   и прогресс. Отметки хранятся на деле; степпер только показывает. */
.stepper {
    list-style: none; margin: 0 0 18px; padding: 0;
    display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px;
}
.stepper__step {
    display: flex; align-items: center; gap: 12px;
    padding: 12px 16px; border-radius: 12px;
    background: var(--surface); border: 1px solid var(--border);
    min-width: 0;
}
.stepper__num {
    flex: none; width: 34px; height: 34px; border-radius: 50%;
    display: inline-flex; align-items: center; justify-content: center;
    font-weight: 700; font-size: var(--fs-md);
    background: var(--surface-2); color: var(--text-muted);
}
.stepper__text { min-width: 0; display: flex; flex-direction: column; }
.stepper__label { font-weight: 600; color: var(--text-muted); overflow-wrap: anywhere; }
.stepper__sub { font-size: var(--fs-sm); color: var(--text-faint); overflow-wrap: anywhere; }
.stepper__step--done .stepper__num { background: var(--ok); color: #fff; }
.stepper__step--done .stepper__label { color: var(--text); }
.stepper__step--current { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.stepper__step--current .stepper__num { background: var(--accent); color: #fff; }
.stepper__step--current .stepper__label { color: var(--accent-dark); }
@media (max-width: 800px) { .stepper { grid-template-columns: 1fr; } }

.cols--quick { grid-template-columns: minmax(0, 1fr) clamp(320px, 30%, 420px); }
@media (max-width: 1100px) { .cols--quick { grid-template-columns: minmax(0, 1fr); } }
/* Шаблон уведомления (11.09.2026): экран во всю ширину — предел форм
   в 1160px оставлял на широком мониторе треть экрана пустой (снимок
   заказчика). Слева форма, текст во всю её ширину и в рост содержимого,
   справа палитра ключей. Порог — по ширине самой формы, а не окна: рядом
   с меню и деревом настроек при окне 1400 форме остаётся 747px. Уже 900px
   палитра уходит под форму. */
.form-page.js-notify-template { max-width: none; container-type: inline-size; }
/* Колонки — одной высоты: короткая карточка тянется до длинной, кнопки
   стоят внизу своей карточки, и под короткой колонкой не остаётся голого
   фона (под формой было 160px пустоты рядом с палитрой). */
.cols--notify-template { grid-template-columns: minmax(0, 1fr) clamp(360px, 34%, 540px); align-items: stretch; }
@container (max-width: 900px) { .cols--notify-template { grid-template-columns: minmax(0, 1fr); } }
.notify-template__main, .notify-template__palette { margin: 0; }
.notify-template__main { display: flex; flex-direction: column; }
.notify-template__main > .card__body { flex: 1 1 auto; }
.js-notify-template textarea[name="body"] {
    min-height: 30rem;
    field-sizing: content;
    line-height: 1.55;
    resize: vertical;
}
.notify-template__note { margin: 0 0 10px; font-size: var(--fs-sm); }
/* Чипы палитры — плиткой, где ширина позволяет в две колонки: название
   слева, ключ под ним мелко. По центру и в одну колонку палитра выходила
   выше формы, и под формой оставалась пустота. */
.notify-template__palette .palette__chips {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 6px;
    padding-left: 12px;
}
.notify-template__palette .chip {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    justify-content: flex-start;
    gap: 2px;
    height: 100%;
    border-radius: 8px;
    padding: 6px 10px;
    text-align: left;
}
.notify-template__palette .chip code { font-size: var(--fs-xs); color: var(--text-muted); }
/* Язык и канал — по четверти строки, тема — половиной: одна строка вместо
   двух с пустым хвостом. Список сам по себе просит треть (`:has(select)`),
   поэтому четверть задана явно — и только в широкой сетке: в узкой
   действуют общие правила. */
@container (min-width: 801px) {
    .js-notify-template .form__field--span-3 { grid-column: span 3; }
}
/* Финансы (06.09.2026): внизу страницы не «очередь + сводка», а четыре
   таблицы по пять-шесть колонок. В правой колонке 340px «Кто не доплатил»
   давала 568px и уезжала в прокрутку. Колонки равные, ниже 1700px — одна:
   при 1400 содержимое 1105px, и каждая таблица встаёт целиком. */
.cols--finance { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
@media (max-width: 1700px) { .cols--finance { grid-template-columns: minmax(0, 1fr); } }
.quick-main, .quick-side { display: flex; flex-direction: column; gap: 20px; min-width: 0; }
.quick-main > .card, .quick-side > .card { margin: 0; }

.step-card--current { border-color: var(--accent); }
.step-card--upcoming { opacity: .8; }
.step-card__num {
    display: inline-flex; align-items: center; justify-content: center;
    width: 26px; height: 26px; border-radius: 50%; margin-right: 6px;
    background: var(--accent-soft); color: var(--accent-dark);
    font-size: var(--fs-sm); font-weight: 700; vertical-align: -6px;
}
.step-card__mark {
    display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px;
    padding: 12px 20px; border-top: 1px solid var(--border); background: var(--bg);
}
.step-card__hint { color: var(--text-muted); font-size: var(--fs-sm); }
.step-card__done { display: inline-flex; align-items: center; gap: 8px; color: var(--ok); font-weight: 600; }
.step-card__done .icon { width: 18px; height: 18px; }
.step-card__lead { margin: 0 0 14px; font-size: var(--fs-md); line-height: 1.55; }

.doc-cards { display: flex; flex-direction: column; gap: 10px; }
.doc-card {
    display: flex; align-items: center; gap: 14px; margin: 0;
    padding: 12px 14px; border: 1px solid var(--border); border-radius: 10px; background: var(--surface);
}
.doc-card__icon { flex: none; width: 24px; height: 24px; color: var(--accent); }
.doc-card__text { min-width: 0; flex: 1; }
.doc-card__title { font-weight: 600; overflow-wrap: anywhere; }
.doc-card__sub { font-size: var(--fs-sm); color: var(--text-muted); margin-top: 2px; }
.doc-card__actions { flex: none; display: flex; flex-wrap: wrap; align-items: center; gap: 8px; justify-content: flex-end; }
.doc-card--empty { border-style: dashed; background: transparent; }
@media (max-width: 640px) { .doc-card { flex-wrap: wrap; } .doc-card__actions { width: 100%; justify-content: flex-start; } }

.handout-split { display: grid; grid-template-columns: minmax(0, 1fr) minmax(240px, 320px); gap: 20px; align-items: start; }
@media (max-width: 900px) { .handout-split { grid-template-columns: 1fr; } }
/* Лист памятки — как есть, уменьшенный zoom-ом: iframe рендерит ту же
   страницу, что уходит на печать. Высота — под А4 в этом масштабе. */
.handout-preview { border: 1px solid var(--border); border-radius: 10px; overflow: hidden; background: #f7f8fa; height: 520px; }
.handout-preview iframe { display: block; width: 100%; height: 100%; border: 0; zoom: .62; }
.handout-what__title { font-size: var(--fs-sm); color: var(--text-muted); text-transform: uppercase; letter-spacing: .04em; font-weight: 600; margin-bottom: 8px; }
.handout-what .btn { margin-top: 12px; }

.check-list { list-style: none; margin: 0; padding: 0; }
.check-list li { position: relative; padding: 6px 0 6px 26px; line-height: 1.4; }
.check-list li::before {
    content: ""; position: absolute; left: 0; top: 9px; width: 16px; height: 16px; border-radius: 50%;
    border: 1.5px solid var(--border-strong);
}
.check-list li.is-ok::before { background: var(--ok); border-color: var(--ok); }
.check-list li.is-ok::after {
    content: ""; position: absolute; left: 5px; top: 12px; width: 6px; height: 9px;
    border: solid #fff; border-width: 0 2px 2px 0; transform: rotate(45deg);
}
.check-list li.is-missing::before { border-color: var(--warn); border-style: dashed; }
.check-list li .cell-sub { display: block; }
.check-list li .badge { margin-left: 6px; }
.code-reveal--inline { display: inline-block; margin: 4px 0; }

.finish-bot { display: flex; align-items: flex-start; gap: 20px; padding: 14px; border: 1px solid var(--border); border-radius: 10px; }
.finish-bot > div { min-width: 0; flex: 1; }
.finish-bot__qr { flex: none; width: 120px; height: 120px; }
@media (max-width: 640px) { .finish-bot { flex-wrap: wrap; } }

.who { display: flex; align-items: center; gap: 14px; margin-bottom: 14px; }
.who__avatar {
    flex: none; width: 52px; height: 52px; border-radius: 50%;
    background: var(--accent-soft); color: var(--accent-dark);
    display: inline-flex; align-items: center; justify-content: center;
    font-weight: 700; font-size: var(--fs-lg); letter-spacing: .02em;
}
.who__text { min-width: 0; }
.who__name { font-weight: 700; font-size: var(--fs-lg); overflow-wrap: anywhere; }
.who__meta { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 4px; color: var(--text-muted); font-size: var(--fs-sm); }
.hr { border: 0; border-top: 1px solid var(--border); margin: 14px 0; }

.progress { height: 8px; border-radius: 999px; background: var(--surface-2); overflow: hidden; margin-bottom: 12px; }
.progress__bar { height: 100%; background: var(--accent); border-radius: 999px; transition: width .2s; }
.progress__count { font-weight: 700; font-variant-numeric: tabular-nums; }
.check-list--steps li.is-todo::before { border-style: solid; }
.next-list { margin: 0; padding-left: 20px; }
.next-list li { margin-bottom: 8px; line-height: 1.5; }
.topbar__sep { color: var(--text-faint); margin: 0 6px; }

/* Узкая правая колонка стартового экрана: подписи .kv короче, значению — место. */
/* 136px: «Ответственный» при 16px — около 125px, в 112 последняя буква
   уезжала на вторую строку (снимок заказчика 07.09.2026). */
.quick-side .kv { grid-template-columns: 136px minmax(0, 1fr); }


/* ---------- Полоса «собрано, но не отправлено» (06.09.2026) ----------
   Форма отметки (канал, номер, кнопка) стояла с flex-shrink: 0 в инлайне
   и на 1400px, где левой колонке достаётся ~530px, оставляла тексту 80px —
   он шёл столбиком в двадцать строк (снимок всей карточки). Теперь текст
   держит не меньше 260px, а форма уходит под него, когда не помещается. */
.hint-strip { flex-wrap: wrap; }
.hint-strip > div:first-child { flex: 1 1 260px; min-width: 0; }
.hint-strip__form { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; flex: 0 1 auto; min-width: 0; }


/* ---------- Ряд кнопок под кодом доступа (06.09.2026, заказчик) ----------
   «Печать памятки · Ссылка на бота · Скрыть код» одним рядом: кнопки делят
   ширину поровну, между ними и от краёв — отступы ряда. Не помещается —
   переносится, оставаясь растянутым. */
.page-actions--fill > * { flex: 1 1 0; min-width: max-content; }
.page-actions--fill > form { display: flex; }
.page-actions--fill > form > .btn { flex: 1 1 0; }
.page-actions--fill .btn { justify-content: center; }
.page-actions--fill > code { flex: 1 1 100%; min-width: 0; }


/* ---------- Форма рассылки в виде карточки (06.09.2026) ---------- */
.lang-card--edit .form__grid { margin-top: 4px; }
/* Тема и текст — друг под другом: в узком контейнере сетка форм даёт
   «широкому» полю половину строки, и текст письма оказывался рядом с темой. */
.lang-card--edit .form__field { grid-column: 1 / -1; margin-bottom: 0; }
#broadcast-form .hint-strip { margin: 0 0 14px; }
#broadcast-form [data-scope-field] .form__field { margin: 0; }
#broadcast-form .card + .card { margin-top: 20px; }


/* ---------- Финансы: компактные таблицы (06.09.2026) ---------- */
.table--compact td, .table--compact th { padding-left: 10px; padding-right: 10px; }
.table--compact .table__num { text-align: right; }
.menu__toggle--text { letter-spacing: 0; font-weight: 500; padding-inline: 14px; }


/* ---------- График оплаты в карточке дела (06.09.2026) ---------- */
.dues { margin-top: 14px; border-top: 1px solid var(--border); padding-top: 10px; }
.dues__head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 6px; }
.dues__title { font-size: var(--fs-sm); font-weight: 600; color: var(--text-muted); text-transform: uppercase; letter-spacing: .04em; }
.dues__row { display: flex; align-items: flex-start; gap: 10px; padding: 8px 0; border-bottom: 1px solid var(--border); }
.dues__row:last-child { border-bottom: 0; }
.dues__main { flex: 1 1 auto; min-width: 0; }
.dues__state { flex: none; text-align: right; }
.dues__row.is-settled .dues__main { color: var(--text-muted); }
.dues__row.is-overdue strong { color: var(--danger); }

/* ---------- Карточка клиента (06.09.2026, по макету заказчика) ----------
   Личные данные — сеткой «подпись над значением»: два десятка полей
   списком .kv уходили на экран, по три в ряд читаются разом. Правки —
   панелью с карточки, у строк таблиц — свои действия в последней колонке. */
.case-hero__facts {
    display: flex; flex-wrap: wrap; gap: 4px 18px;
    margin-top: 6px; font-size: var(--fs-sm); color: var(--text-muted);
}
.case-hero__facts strong { color: var(--text); font-weight: 500; }
.facts {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 14px 20px;
    margin: 0;
}
.facts__item { min-width: 0; }
.facts__label { font-size: var(--fs-sm); color: var(--text-muted); margin-bottom: 2px; }
.facts__value { margin: 0; font-size: var(--fs-md); overflow-wrap: anywhere; }
.facts__value .badge { vertical-align: middle; }
/* Действия строки — у правого края, иконка с подписью в title и aria-label:
   в макете заказчика карандаш и корзина стоят без слов, а колонка «Действия»
   подписана в шапке таблицы. */
.table__actions { text-align: right; white-space: nowrap; }
.table__actions form { display: inline; }
.table__actions .btn { padding-inline: 8px; }
.address-line { font-size: var(--fs-md); }

/* Права по разделам в карточке сотрудника и имя-ссылка в меню (06.09.2026). */
.caps__section {
    margin: 14px 0 4px;
    font-size: var(--fs-sm);
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--text-muted);
}
.caps__section:first-child { margin-top: 4px; }
a.sidebar__user-name {
    display: block;
    color: inherit;
    text-decoration: none;
}
a.sidebar__user-name:hover { text-decoration: underline; }

/* Скан подписанного под карточкой документа на стартовом экране (06.09.2026). */
.doc-card--signed { align-items: flex-start; }
.doc-card__scan {
    margin-top: 6px;
    display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
    font-size: var(--fs-sm);
}
.doc-card__scan--done { color: var(--ok); font-weight: 600; }
.doc-card__scan--done .icon { width: 16px; height: 16px; }
.doc-card__scan--missing { color: var(--text-muted); }
.dropzone--scan {
    margin-top: 8px;
    padding: 10px 12px;
    text-align: left;
    background: var(--drop-bg);
    border-color: var(--drop-border);
}
.dropzone--scan.is-over { background: var(--drop-bg-over); border-color: var(--ok); }
.dropzone--scan .dropzone__hint { font-size: var(--fs-sm); color: var(--drop-text); }

/* Шапка в два яруса (06.09.2026, замечание заказчика «намешано»): общая
   полоса — дата, поиск, словарь, язык; шапка страницы — заголовок и её
   действия. Полоса прокручивается со страницей, липнет только шапка.
   Прежнее правило `.topbar > :first-child { max-width: 42% }` держало
   заголовок ради правой части в том же ряду — теперь заголовку отдана
   вся строка, действия встают справа и переносятся под него на узком. */
.utility-bar {
    display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px;
    min-height: 46px; padding: 6px 28px;
    background: var(--surface-2);
    border-bottom: 1px solid var(--border);
}
.utility-bar .topbar__date { margin-right: auto; text-align: left; font-size: var(--fs-sm); }
.utility-bar__tools {
    margin-left: auto; display: flex; flex-wrap: wrap; align-items: center;
    justify-content: flex-end; gap: 10px;
}
.utility-bar .topbar__search-input { width: 260px; }
.utility-bar .topbar__search-input:focus { width: 360px; }
.topbar { padding: 14px 28px; gap: 10px 20px; }
.topbar > :first-child { max-width: none; }
.topbar__heading { flex: 1 1 320px; min-width: 0; }
.topbar__actions {
    margin-left: auto; display: flex; flex-wrap: wrap; align-items: center;
    justify-content: flex-end; gap: 8px;
}
.topbar__actions:not(:has(*)) { display: none; }
.topbar__actions .page-actions { gap: 8px; }
/* В полосе места хватает — день недели виден на любой ширине. */
@media (max-width: 1600px) { .topbar__weekday { display: inline; } }
@media (max-width: 640px) {
    .utility-bar { padding: 6px 12px; }
    .utility-bar__tools { width: 100%; }
    .utility-bar .topbar__search { flex: 1 1 160px; }
    .utility-bar .topbar__search-input,
    .utility-bar .topbar__search-input:focus { width: 100%; }
    .topbar__actions { margin-left: 0; width: 100%; justify-content: flex-start; }
}

/* ---------- Порядок перетаскиванием (10.09.2026, static/js/reorder.js) ----------
   Ручка — кнопка в первой колонке: строка списка — ссылка, и нажатие
   на кнопку переход не запускает. touch-action: none — чтобы палец на
   планшете тянул строку, а не прокручивал страницу. */
.col-drag { width: 44px; padding-right: 0 !important; }
.drag-handle {
    display: inline-grid; place-items: center;
    width: 30px; height: 30px; border: 0; border-radius: 6px;
    background: transparent; color: var(--text-muted);
    cursor: grab; touch-action: none;
}
.drag-handle:hover, .drag-handle:focus-visible { background: var(--surface-2, #eef1f6); color: var(--text); }
.drag-handle:active { cursor: grabbing; }
.drag-handle svg { fill: currentColor; }
tr.is-dragging { opacity: .6; }
tr.is-dragging > td { background: var(--accent-soft, #eef3ff); }
.is-reordering, .is-reordering * { user-select: none; cursor: grabbing; }
.reorder-status { padding: 10px 16px; font-size: var(--fs-sm); color: var(--text-muted); border-top: 1px solid var(--border, #e4e7ec); }
.reorder-status.is-error { color: var(--danger); }
.table__group th { background: var(--surface-2, #f5f6f8); font-size: var(--fs-sm); font-weight: 600; text-align: left; }

/* Строка состояния: бейдж и пояснение рядом, на одной базовой линии (18.09.2026).
   Бейдж не переносится и не сжимается, длинное пояснение переносится справа от него. */
.status-line { display: flex; align-items: baseline; gap: 10px; }
.status-line > .badge { flex: 0 0 auto; align-self: flex-start; }
.status-line > span:last-child { min-width: 0; }


/* --- Проверка документа: скан и форма рядом (18.09.2026) ---------------------------
   Две закреплённые половины с подвижной границей. Доля скана — в переменной
   --review-doc (её пишет скрипт и помнит браузер); стороны меняются атрибутом
   data-swapped. Порог «узко» меряется по самому блоку, а не по окну: тот же
   экран живёт и страницей, и в панели поверх карточки дела. */
.review-split {
    --review-doc: 52%;
    container-type: inline-size;
    display: flex;
    align-items: stretch;
    gap: 0;
    min-height: 70vh;
}
.review-split__doc { flex: 0 0 var(--review-doc); min-width: 280px; display: flex; }
.review-split__form { flex: 1 1 0; min-width: 320px; display: flex; flex-direction: column; gap: 16px; }
.review-split[data-swapped="1"] { flex-direction: row-reverse; }
.review-split__handle {
    flex: 0 0 14px; cursor: col-resize; position: relative; touch-action: none;
    border-radius: 7px; outline-offset: 2px;
}
.review-split__handle::before {
    content: ""; position: absolute; top: 12px; bottom: 12px; left: 6px; width: 2px;
    border-radius: 2px; background: var(--border, #d0d5dd);
}
.review-split__handle:hover::before, .review-split__handle:focus-visible::before,
.review-split.is-resizing .review-split__handle::before { background: var(--accent, #2456d6); }
.review-split.is-resizing { user-select: none; cursor: col-resize; }
/* Пока тянут границу, фрейм с PDF не должен перехватывать мышь. */
.review-split.is-resizing iframe { pointer-events: none; }
.review-split__tabs { display: none; gap: 8px; margin-bottom: 12px; }

.review-viewer {
    flex: 1 1 auto; display: flex; flex-direction: column; min-width: 0;
    position: sticky; top: 72px; height: calc(100vh - 96px);
    background: var(--card-bg, #fff); border: 1px solid var(--border, #e4e7ec);
    border-radius: var(--radius, 10px); overflow: hidden;
}
.review-viewer__bar {
    display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
    padding: 8px 12px; border-bottom: 1px solid var(--border, #e4e7ec);
    background: var(--surface-2, #f5f6f8);
}
.review-viewer__name { font-weight: 600; font-size: var(--fs-sm); overflow-wrap: anywhere; min-width: 0; }
.review-viewer__tools { margin-left: auto; display: flex; gap: 6px; flex-wrap: wrap; }
.review-viewer__body { flex: 1 1 auto; min-height: 0; overflow: auto; background: #525659; }
.review-viewer__body > .empty { background: var(--card-bg, #fff); height: 100%; }
.review-viewer__frame { display: block; width: 100%; height: 100%; border: 0; background: #525659; }
.review-viewer__img {
    display: block; margin: 0 auto; max-width: none; width: calc(100% * var(--viewer-zoom, 1));
    transform: rotate(var(--viewer-rotate, 0deg)); transform-origin: center center;
}

/* В панели поверх карточки дела двум половинам нужна вся ширина окна. */
.panel--wide .panel__box { width: min(1880px, 100%); max-height: 96vh; }
.panel--wide .panel__body { padding: 12px; }
.panel--wide .review-viewer { top: 0; height: calc(96vh - 96px); }
.panel--wide .review-split { min-height: 0; }
/* Расчёт с плательщиком в окне (02.10.2026): колонки по ширине окна-панели,
   а не браузера — иначе при окне уже 1700px всё вставало одной растянутой колонкой. */
.panel--wide:has([data-panel-wide]) .panel__box { width: min(1500px, 100%); }
.panel--wide .cols--finance { grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); }
@media (max-width: 1100px) { .panel--wide .cols--finance { grid-template-columns: minmax(0, 1fr); } }

@container (max-width: 900px) {
    .review-split__tabs { display: flex; }
}
@media (max-width: 1000px) {
    .review-split { flex-direction: column; min-height: 0; }
    .review-split[data-swapped="1"] { flex-direction: column; }
    .review-split__tabs { display: flex; }
    .review-split__handle { display: none; }
    .review-split__doc, .review-split__form { flex: 1 1 auto; min-width: 0; }
    .review-split[data-pane-active="form"] .review-split__doc { display: none; }
    .review-split[data-pane-active="doc"] .review-split__form { display: none; }
    .review-split__tabs .btn[aria-selected="true"] { background: var(--accent, #2456d6); color: #fff; border-color: transparent; }
    .review-viewer { position: static; height: 70vh; }
}

/* Расчёт с плательщиком (18.09.2026): кнопки в полосе карточки дела */
.hint-strip__actions { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; min-width: 0; max-width: 100%; }

/* Шапка свёрнутого блока правой колонки переносится на любой ширине (18.09.2026):
   в правой колонке дела (378px) блок «Уведомления» с тремя кнопками вылезал за карточку
   на 113px, и «Вся история» срезалась — но только у дел с работодателем, где кнопок три. */
.card--fold .card__head { flex-wrap: wrap; row-gap: 8px; }
.card--fold .card__actions { flex-wrap: wrap; row-gap: 6px; min-width: 0; }

/* ---------- Физическая папка дела (02.10.2026) ----------
   Метка-кнопка в шапке дела и в списке: номер виден сразу, нажатие
   открывает окно правки. Пустая — пунктиром, чтобы читалась как
   «не указано», а не как ещё одно состояние. */
.folder-chip {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 2px 9px;
    min-height: 26px;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    background: var(--surface);
    color: var(--text);
    font-size: var(--fs-sm);
    font-weight: 600;
    white-space: nowrap;
    line-height: 1.2;
}
.folder-chip .icon { width: 15px; height: 15px; flex: none; color: var(--text-muted); }
.folder-chip__label { color: var(--text-muted); font-weight: 500; }
.folder-chip__number { font-variant-numeric: tabular-nums; }
.folder-chip:hover {
    background: var(--accent-soft);
    border-color: var(--accent);
    color: var(--accent-dark);
    text-decoration: none;
}
.folder-chip:hover .icon, .folder-chip:hover .folder-chip__label { color: var(--accent-dark); }
.folder-chip--empty {
    border-style: dashed;
    color: var(--text-muted);
    font-weight: 500;
}
/* Окно из одного поля (номер папки): во всю ширину панели одинокое поле
   читалось как пустая форма. Узкий вариант — по метке внутри, как --wide. */
.panel:has([data-panel-narrow]) .panel__box { width: min(560px, 100%); }

/* --- «Сегодня»: календарь месяца (11.10.2026) ---------------------------
   В клетке дня — только счётчики по метке типа события, список дня
   справа. Плитки тревог компактнее прежних: главным на странице стал
   календарь. Цвета меток — мягкие фоны, у wezwania красный всегда. */
.tiles__calm { grid-column: 1 / -1; color: var(--text-muted); padding: 4px 0; }

.cal { overflow: visible; }
.cal__head { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; justify-content: space-between; }
.cal__nav { display: flex; align-items: center; gap: 8px; }
.cal__month { font-family: var(--font-display); font-weight: 650; font-size: var(--fs-lg); min-width: 150px; text-align: center; text-transform: capitalize; }
.cal__legend { display: flex; flex-wrap: wrap; gap: 6px; }
.cal__body { display: grid; grid-template-columns: minmax(0, 1fr) clamp(300px, 28%, 440px); }
.cal__grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 6px; padding: 16px; }
.cal__wd { font-size: var(--fs-xs); color: var(--text-muted); text-transform: uppercase; letter-spacing: .04em; padding: 0 6px; }
.cal__day {
    display: flex; flex-direction: column; gap: 4px; align-items: flex-start;
    min-height: 104px; padding: 8px; border: 1px solid var(--border); border-radius: var(--radius-sm);
    background: var(--surface); color: var(--text); text-decoration: none; min-width: 0;
}
.cal__day:hover { border-color: var(--border-strong); text-decoration: none; }
.cal__day--out { background: transparent; border-style: dashed; }
.cal__day--out .cal__num, .cal__day--past .cal__num { color: var(--text-faint); }
.cal__day--today { border: 2px solid var(--accent); padding: 7px; }
.cal__day--today .cal__num { color: var(--accent); font-weight: 700; }
.cal__day--selected { background: var(--accent-soft); }
.cal__num { font-family: var(--font-display); font-size: var(--fs-md); font-weight: 600; line-height: 1; margin-bottom: 2px; }

.cal-chip {
    display: inline-flex; align-items: baseline; gap: 4px; max-width: 100%; overflow: hidden;
    white-space: nowrap; text-overflow: ellipsis; border-radius: 4px; padding: 1px 6px;
    font-size: var(--fs-sm); line-height: 1.5; background: var(--surface-2); color: var(--text-muted);
}
.cal-chip b { font-weight: 700; }
.cal-chip__text { overflow: hidden; text-overflow: ellipsis; }
.cal-chip--danger { background: #fde8e8; color: #8f1d1d; }
.cal-chip--violet { background: #eeedfe; color: #3c3489; }
.cal-chip--teal   { background: #e1f5ee; color: #085041; }
.cal-chip--blue   { background: #e6f1fb; color: #0c447c; }
.cal-chip--amber  { background: #faeeda; color: #633806; }

.cal__day-panel { border-left: 1px solid var(--border); padding: 16px; min-width: 0; }
.cal__day-title { font-family: var(--font-display); font-weight: 650; font-size: var(--fs-lg); margin-bottom: 12px; display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.cal__day-title::first-letter { text-transform: uppercase; }
.cal__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.cal__item { display: flex; gap: 10px; padding: 8px; border-radius: var(--radius-sm); cursor: pointer; }
.cal__item:hover { background: var(--surface-2); }
.cal__bar { flex: 0 0 4px; border-radius: 2px; padding: 0; }
.cal__item-main { min-width: 0; }
.cal__item-title { font-weight: 500; overflow-wrap: anywhere; }
.cal__item-meta { font-size: var(--fs-sm); color: var(--text-muted); overflow-wrap: anywhere; }
.cal__empty { padding: 8px 0; }

.today-lists { display: grid; grid-template-columns: repeat(auto-fill, minmax(360px, 1fr)); gap: 20px; align-items: start; margin-top: 20px; }
.today-lists:empty { display: none; }
.today-lists > .card { margin: 0; }
.today-fold > summary { cursor: pointer; list-style: none; }
.today-fold > summary::-webkit-details-marker { display: none; }
.today-fold > summary::after { content: "▾"; color: var(--text-muted); margin-left: 8px; }
.today-fold[open] > summary::after { content: "▴"; }

@media (max-width: 1500px) {
    .cal__body { grid-template-columns: minmax(0, 1fr); }
    .cal__day-panel { border-left: none; border-top: 1px solid var(--border); }
}
@media (max-width: 760px) {
    .cal__grid { gap: 3px; padding: 8px; }
    .cal__day { min-height: 64px; padding: 4px; }
    .cal__day--today { padding: 3px; }
    .cal-chip { padding: 0 4px; }
    .cal-chip__text { display: none; }
    .today-lists { grid-template-columns: minmax(0, 1fr); }
}

/* Плитки «Сегодня» — тень гуще (замечание заказчика 12.10.2026: «темнее сзади»). */
.tiles .tile { box-shadow: 0 2px 4px rgba(20, 30, 50, .12), 0 10px 28px rgba(20, 30, 50, .22); }
.tiles .tile:hover { box-shadow: 0 4px 8px rgba(20, 30, 50, .16), 0 16px 40px rgba(20, 30, 50, .28); }

/* Плашка хода разбора «Неразобранного» (14.10.2026). */
.inbox-run:empty { display: none; }
.inbox-run {
    margin-bottom: 16px;
    padding: 14px 18px;
    border: 1px solid var(--border, #e3e8ef);
    border-radius: 10px;
    background: var(--surface, #fff);
}
.inbox-run--active { border-color: #9db4f0; background: #f2f6ff; }
.inbox-run__title { display: flex; align-items: center; gap: 10px; font-weight: 600; }
.inbox-run__facts { margin-top: 6px; color: var(--text-muted, #475467); }
.inbox-run__bar { margin-top: 10px; height: 8px; border-radius: 4px; background: #dde6fb; overflow: hidden; }
.inbox-run__bar span { display: block; height: 100%; background: #2456d6; transition: width .4s; }
.inbox-run__spinner {
    width: 16px; height: 16px; flex: none;
    border: 2px solid #9db4f0; border-top-color: #2456d6; border-radius: 50%;
    animation: inbox-run-spin .8s linear infinite;
}
@keyframes inbox-run-spin { to { transform: rotate(360deg); } }
