/* ============================================================================
   Buildificator — базовая тема сгенерированной админки.
   Чистая, просторная, brand-aware (через настоящие токены Filament --primary-*).
   Задаёт «красиво по умолчанию»; поверх ложится per-project custom_css
   (ИИ-хелпер пишет индивидуальный дизайн под конкретную админку → он побеждает
   по каскаду, т.к. инжектится ПОЗЖЕ этой темы). Инжектится ТОЛЬКО в превью-панель
   и в экспорт (skeleton), не в chrome билдера. light + dark.
   ============================================================================ */

/* ── Словарь облика ────────────────────────────────────────────────────────
   Имена и состав — контракт библиотеки обликов (docs/brief-admin-skins.md).
   Значения по умолчанию = характер 01 «учётный плотный».

   СМЕНИТЬ ОБЛИК = переопределить эти два блока в `Project.settings.custom_css`
   (инжектится ПОЗЖЕ темы → побеждает по каскаду). Готовые блоки лежат в
   resources/css/filament/skins/*.css — файл целиком копируется в custom_css.
   Ни одно правило ниже конкретных значений не знает, только имена.
   ────────────────────────────────────────────────────────────────────────── */
/* `:root, body` — не украшение. Уровень плотности ставит свои `--d-*` классом
   на <body>, а подстановка `var()` считается НА ТОМ ЖЕ элементе, где объявлена:
   из `:root` до `body` она не достаёт, и уровень молча переставал действовать —
   поле держалось 26px и в «просторно», и в «максимуме». Объявляем на обоих. */
:root, body {
  /* поверхности */
  --skin-bg:    #f7f8f9;
  --surface:    #ffffff;
  --surface-2:  #f0f2f4;
  --rail:       #fbfbfc;

  /* текст */
  --ink:        #0d1117;
  --body:       #333c45;
  --mute:       #5c666f;
  --faint:      #6c757e;

  /* Фирменный цвет: бренд ПРОЕКТА побеждает облик — это цвет заказчика,
     а не характера. Значение из палитры Filament, значение облика — запасное. */
  --primary:       var(--primary-600, #15619f);
  --primary-hover: var(--primary-700, #0f4e83);
  --primary-soft:  color-mix(in srgb, var(--primary) 12%, transparent);
  --on-primary:    #ffffff;

  /* Состояния. Пара `--on-*` — текст НА заливке этого цвета. Держать в паре
     обязательно: в тёмной теме сам цвет светлеет (чтобы читаться текстом),
     и белая надпись на нём проваливается по контрасту. */
  --ok:   #12724a; --ok-soft:   #e8f4ee; --on-ok:   #ffffff;
  --warn: #8a5300; --warn-soft: #fbf1de; --on-warn: #ffffff;
  --bad:  #a52033; --bad-soft:  #fbe8ea; --on-bad:  #ffffff;
  --info: #15619f; --info-soft: #e8f1f9; --on-info: #ffffff;

  /* линии */
  --line:        #e4e7ea;
  --line-soft:   #eef0f2;
  --line-strong: #d2d7dc;

  /* форма */
  --radius:    6px;
  --radius-sm: 4px;
  --radius-lg: 10px;
  --shadow:    0 8px 28px rgba(13, 17, 23, .14), 0 1px 2px rgba(13, 17, 23, .06);
  --shadow-sm: 0 1px 2px rgba(13, 17, 23, .05);

  /* плотность и текст */
  --row-h:               var(--d-row-h, 22px);
  --pad:       12px;
  --font-base: 13px;
  --font-sm:   11.5px;

  /* прочее */
  --hover:       #f4f6f8;
  --selected:    #e8f1f9;
  --focus:       var(--primary);
  --neutral:     #616b76;
  --neutral-soft:#eef0f2;
  --rail-ink:    #333c45;
  --rail-mute:   #6c757e;
  --rail-active: #eceff2;
}
/* `.dark, body.dark, .dark body` — обратная сторона того же правила, что и у
   светлого словаря. Раз светлые значения объявлены и на `body`, собственное
   объявление элемента бьёт значение, унаследованное от `.dark` на <html>, — и
   тёмная тема до содержимого не доезжает вовсе: карточки остаются белыми.
   Три агента наткнулись на это независимо. */
.dark, body.dark, .dark body {
  --skin-bg:   #0f1216;
  --surface:   #171b21;
  --surface-2: #1f242b;
  --rail:      #14181e;

  --ink:   #f0f3f6;
  --body:  #c9d1d9;
  --mute:  #98a2ac;
  --faint: #8b959f;

  /* --primary НЕ переопределяем: палитра Filament в тёмной теме не светлеет,
     значит и белая надпись на ней остаётся верной. А вот состояния светлеют —
     и парный текст обязан стать тёмным, иначе «Отклонить» нечитаемо. */
  --ok:   #54c082; --ok-soft:   #10251b; --on-ok:   var(--skin-bg);
  --warn: #dda63f; --warn-soft: #271f10; --on-warn: var(--skin-bg);
  --bad:  #ef7079; --bad-soft:  #2b1519; --on-bad:  var(--skin-bg);
  --info: #5aa9e6; --info-soft: #132330; --on-info: var(--skin-bg);

  --line:        #252b33;
  --line-soft:   #1e232a;
  --line-strong: #333b45;

  --shadow:    0 10px 32px rgba(0, 0, 0, .6), 0 1px 2px rgba(0, 0, 0, .4);
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, .35);

  --hover:       #1c2128;
  --selected:    #152a3b;
  --neutral:     #96a0aa;
  --neutral-soft:#1f242b;
  --rail-ink:    #c9d1d9;
  --rail-mute:   #8b959f;
  --rail-active: #232a32;
}

/* Название системы в шапке бокового меню. Оно приходит от заказчика и бывает
   длинным — «Система управления закупками» в 206px не влезает и обрезалось на
   полуслове. Переносим по словам и ужимаем кегль, а не режем. */
.fi-sidebar-header .fi-logo {
  font-size: var(--font-sm);
  line-height: 1.25;
  font-weight: 700;
  white-space: normal;
  overflow-wrap: anywhere;
  color: var(--ink);
}
.fi-sidebar-header { align-items: flex-start; padding-block: 10px; }

/* Кнопка действий в ячейке берёт СВОЙ размер, а не общий значковый: общий 28px,
   а строка целится в 22 — и тянула её именно кнопка, не текст. Приём тот же,
   что у цветных действий: локальная переменная внутри правила. */
.fi-ta-actions .fi-icon-btn,
.fi-ta-cell .fi-icon-btn { --icon-btn-size-md: var(--ta-action-btn-size); }

/* Иконки фильтра и колонок стояли впритык к правому краю и вылезали за
   скруглённый угол листа. Тулбару нужен запас справа не меньше радиуса. */

/* ── Полосы прокрутки ─────────────────────────────────────────────────────
   Тонкие, в цвет линий, без стрелок. Видны, пока есть что прокручивать, и не
   спорят с содержимым. Прятать их я уже пробовал — этим убрал единственный
   способ добраться до дальних вкладок. */
* {
  scrollbar-width: thin;
  scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track);
}
*::-webkit-scrollbar { width: var(--scrollbar-size); height: var(--scrollbar-size); }
*::-webkit-scrollbar-track { background: var(--scrollbar-track); }
*::-webkit-scrollbar-thumb {
  background: var(--scrollbar-thumb);
  border-radius: 999px;
  border: 2px solid transparent;
  background-clip: padding-box;
}
*::-webkit-scrollbar-thumb:hover { background: var(--mute); background-clip: padding-box; }
*::-webkit-scrollbar-corner { background: var(--scrollbar-track); }
*::-webkit-scrollbar-button { display: none; }

/* Тулбар таблицы — ОДИН хозяин отступов.
   Счётчик на иконке фильтра рисуется в её правом верхнем углу и выступает
   за габарит кнопки на 8px. Лист таблицы скруглён и обрезает всё, что вышло
   за край, — счётчик срезало ровно наполовину. Запас справа обязан быть
   больше выступа счётчика, иначе он будет обрезаться при любом радиусе. */
.fi-ta-header-toolbar {
  padding: 4px 10px !important;
  padding-right: 20px !important;
  border-bottom: 1px solid var(--line-soft) !important;
}

/* ── Боковое меню: сведено с эталоном замером ─────────────────────────────
   Эталон (1440×900): панель 206px, фон `--rail`; пункт 27px, кегль 12.5,
   поле 12px, радиус `--radius-sm`, вес обычный; активный — подложка
   `--nav-active-bg`, вес 500 и полоса слева 2px внутрь; подпись группы 11.5
   обычным весом, поле 8/12/4.
   Наше меню оставалось стоковым: пункт с крупным полем, активный — залитая
   пилюля фирменного цвета. Заметно и не в ту сторону. */
.fi-sidebar-item-btn {
  min-height: 27px !important;
  padding: 0 12px !important;
  font-size: var(--font-sm) !important;
  font-weight: 400 !important;
  color: var(--rail-ink) !important;
  border-radius: var(--radius-sm) !important;
  gap: 8px;
}
.fi-sidebar-item-btn:hover { background: var(--hover) !important; color: var(--ink) !important; }
.fi-sidebar-item.fi-active > .fi-sidebar-item-btn {
  background: var(--nav-active-bg) !important;
  color: var(--nav-active-ink) !important;
  font-weight: 500 !important;
  box-shadow: inset 2px 0 0 var(--nav-active-bar) !important;
}
/* Длинная подпись обрезалась многоточием — «Закупочные процед…», и прочитать
   раздел было НЕЧЕМ: подсказки у пункта нет, развернуть некуда, а имена
   разделов придумывает заказчик, и укоротить их мы не вправе. Пусть
   переносится: две строки при 206px закрывают почти всё, что человек напишет.
   Иконка при этом обязана остаться на первой строке, иначе она уползает
   к середине блока. */
.fi-sidebar-item-btn {
  align-items: flex-start !important;
  padding-block: 5px !important;
}
.fi-sidebar-item-btn > .fi-sidebar-item-label,
.fi-sidebar-item-btn > span:not([class]) {
  white-space: normal !important;
  overflow: visible !important;
  text-overflow: clip !important;
  overflow-wrap: anywhere;
  line-height: 16px;
}
.fi-sidebar-item-icon { width: 16px; height: 16px; flex: 0 0 16px; margin-block-start: 1px; color: var(--rail-mute) !important; }
.fi-sidebar-item.fi-active > .fi-sidebar-item-btn .fi-sidebar-item-icon { color: var(--nav-active-bar) !important; }
.fi-sidebar-group-label {
  font-size: var(--font-sm) !important;
  font-weight: 400 !important;
  color: var(--rail-mute) !important;
  padding: 8px 12px 4px !important;
}
.fi-sidebar-nav { padding: 6px 8px !important; row-gap: 2px !important; }
.fi-sidebar-group-items { gap: 0 !important; }

/* Вкладки кластера ПЕРЕНОСЯТСЯ, а не прокручиваются.
   Сначала я спрятал появившуюся полосу прокрутки — и этим убрал единственный
   способ добраться до дальних вкладок: колесо мыши по горизонтали не крутит,
   а полосы больше нет. Прятать способ добраться нельзя; правильнее сделать так,
   чтобы добираться было не нужно. Десять разделов встают в две строки. */
.fi-page-sub-navigation-tabs {
  overflow: visible;
  flex-wrap: wrap;
  row-gap: 2px;
}
.fi-page-sub-navigation-tabs > * { flex: none; }

/* ── Геометрия строки реестра: ОДИН хозяин ────────────────────────────────
   Было четыре правила с `!important`, и два из них с ОДНИМ селектором и разными
   значениями — осадок от правок по кусочкам. Строка держалась 26px при
   заданных 22, и понять почему можно было только через список сработавших
   правил.
   Теперь высота выводится из `--row-h`, а плотность меняет ЗНАЧЕНИЕ токена.
   Эталон: строка 22px при тексте 13/18.85 — отсюда и поле в один пиксель. */
.fi-ta-cell {
  font-size: var(--font-base) !important;
  line-height: calc(var(--row-h) - 3px) !important;
  /* Вертикальные отступы держит ТЕКСТ внутри, а не ячейка: иначе высота
     складывается из двух источников и не сходится ни с каким токеном. */
  padding-block: 0 !important;
  padding-inline: var(--ta-col-pad-x) !important;
}
.fi-ta-cell .fi-ta-text {
  padding-block: 1px !important;
  min-height: 0 !important;
}
.fi-ta-cell .fi-ta-text-item {
  padding-block: 0 !important;
  line-height: calc(var(--row-h) - 3px) !important;
  font-size: var(--font-base) !important;
}
body.bf-density-compact { --d-row-h: 30px; }
body.bf-density-dense   { --d-row-h: 22px; }

/* ── Производные токены ────────────────────────────────────────────────────
   Второй ярус словаря. Характер задаёт БАЗУ (36 имён выше) и вправе не знать
   об этом блоке вовсе: всё здесь выводится из базы и даёт осмысленный вид само.

   Переопределять отсюда характер может ровно то, чем он хочет отличаться —
   и это и есть его ОСИ. Заливка поля против рамки, плашка заливкой против
   точки, вкладка подчёркиванием против пилюли, строка зеброй против волоска.
   Остальные сто с лишним имён он не трогает никогда.

   Так словарь растёт, а работа характера — нет.
   ────────────────────────────────────────────────────────────────────────── */
/* `:root, body` — не украшение. Уровень плотности ставит свои `--d-*` классом
   на <body>, а подстановка `var()` считается НА ТОМ ЖЕ элементе, где объявлена:
   из `:root` до `body` она не достаёт, и уровень молча переставал действовать —
   поле держалось 26px и в «просторно», и в «максимуме». Объявляем на обоих. */
:root, body {
  /* Пары «заливка / надпись на ней». Обжигались дважды: цвет состояния в тёмной
     теме светлеет, чтобы читаться ТЕКСТОМ, и белая надпись на нём проваливается.
     Поэтому заливка и надпись — всегда пара, и обе переопределяются в `.dark`. */
  --bad-fill:     var(--bad);      --on-bad:     var(--surface);
  --ok-fill:      var(--ok);       --on-ok:      var(--surface);
  --warn-fill:    var(--warn);     --on-warn:    var(--surface);
  --info-fill:    var(--info);     --on-info:    var(--surface);
  --neutral-fill: var(--neutral);  --on-neutral: var(--surface);

  /* Мягкие подложки состояний — под плашки и полосы внимания. */
  --ok-soft:   color-mix(in srgb, var(--ok)   14%, var(--surface));
  --warn-soft: color-mix(in srgb, var(--warn) 14%, var(--surface));
  --bad-soft:  color-mix(in srgb, var(--bad)  14%, var(--surface));
  --info-soft: color-mix(in srgb, var(--info) 14%, var(--surface));

  /* ОСЬ: поле ввода. Умолчания сняты ЗАМЕРОМ с эталона, а не выбраны на вкус:
     поле — заливка `--surface-2` без видимой рамки, 26px, поле 8px, кегль 12.5;
     селект — наоборот, белый с рамкой `--line-strong` и полем 6px.
     Замер трёх характеров показал, что эти значения у них ОДИНАКОВЫ — значит
     это умолчание эталона, а не ось. Ось останется: характер, которому нужна
     рамка у поля, поставит `--input-border: var(--line)` и всё. */
  --input-bg:            var(--surface-2);
  --input-border:        transparent;
  --input-border-hover:  var(--line-strong);
  --input-bg-focus:      var(--surface);
  --input-ink:           var(--ink);
  --input-placeholder:   var(--faint);
  --input-readonly-bg:   var(--surface-2);
  --input-readonly-ink:  var(--body);
  --input-disabled-bg:   var(--surface-2);
  --input-disabled-ink:  var(--faint);
  --input-h:             var(--d-input-h, 26px);
  --input-pad-x:         8px;
  --input-ring-w:        3px;
  --label-ink:           var(--body);
  --label-weight:        500;
  --field-gap:           4px;
  --select-bg:           var(--surface);
  --select-border:       var(--line-strong);

  /* ОСЬ: флажок и переключатель — квадратный и строгий ↔ круглый и мягкий. */
  --check-size:   12px;
  --check-bg:     var(--surface);
  --check-border: var(--line-strong);
  --check-on:     var(--primary);
  --toggle-w:        34px;
  --toggle-h:        18px;
  --toggle-on-bg:    var(--primary);
  --toggle-off-bg:   var(--neutral-soft);
  --toggle-off-border: var(--line-strong);
  --toggle-knob-on:  var(--surface);
  --toggle-knob-off: var(--surface);

  /* Прочее в форме — редко становится осью, но должно быть выражено. */
  --picker-panel-bg:     var(--surface);
  --picker-panel-border: var(--line);
  --repeater-item-bg:     var(--surface);
  --repeater-item-border: var(--line);
  --upload-border:  var(--line-strong);
  --slider-track:   var(--neutral-soft);
  --slider-fill:    var(--primary);
  --slider-handle-bg: var(--surface);

  /* ОСЬ: кнопка и плашка. Плашка бывает заливкой, точкой со словом, контуром. */
  --btn-h:      var(--d-btn-h, 28px);
  --btn-pad-x:  var(--d-btn-pad-x, 12px);
  --btn-font:   var(--d-btn-font, var(--font-sm));
  --icon-btn-size-md: 28px;
  --act-gap:    8px;
  /* Плашка ВООБЩЕ и плашка В РЕЕСТРЕ — разные вещи, и одним токеном их не
     выразить. В инвентаре эталона плашка залита мягким тоном состояния;
     в реестре — точка со словом, иначе полсотни строк превращаются в витраж.
     Поэтому две ручки: общая и табличная. */
  --badge-bg:     var(--act-soft, var(--neutral-soft));
  --ta-badge-bg:  transparent;
  --badge-border: transparent;
  --badge-dot:    6px;
  --badge-radius: var(--radius-sm);
  /* Ноль здесь означал плашку без боковых полей: рамка вплотную к числу, а
     производные размеры (`calc(--badge-pad-x - 4px)`) уходили в МИНУС. В
     реестре это не было видно — там плашке задан свой отступ явно, — зато
     вылезало на вкладках со счётчиками, где плашек больше всего.
     Значение сверено с описанием токена ниже по файлу: там всегда стояло 8px. */
  --badge-pad-x:  8px;
  --badge-font:   var(--font-sm);

  /* ОСЬ: строка таблицы. Зебра ↔ волосок ↔ ничего; наведение заливкой ↔ полосой. */
  --row-separator:   var(--line-soft);
  --row-separator-w: 1px;
  --row-stripe:      transparent;
  --row-hover-bg:    var(--hover);
  --row-hover-bar:   transparent;
  --row-hover-bar-w: 0px;
  --row-selected-bg:    var(--selected);
  --row-selected-bar:   var(--primary);
  --row-selected-bar-w: 2px;

  /* ОСЬ: вкладки — подчёркивание ↔ пилюля ↔ сегмент. */
  --tabs-bg:             transparent;
  --tab-radius:          0px;
  --tab-active-bg:       transparent;
  --tab-active-underline: var(--primary);
  --tab-active-ink:      var(--ink);

  /* ОСЬ: пункт меню — подложка ↔ полоса слева. */
  --nav-active-bg:  var(--rail-active);
  --nav-active-bar: var(--primary);
  --nav-active-ink: var(--ink);

  /* Затемнение под модальным окном. */
  --overlay-ink: color-mix(in srgb, var(--ink) 55%, transparent);

  /* Таблица: размеры и оттенки её собственных элементов. */
  --ta-col-pad-x: 10px;   --ta-col-pad-y: 3px;
  --ta-icon-ink:  var(--mute);
  --ta-image-radius: var(--radius-sm);  --ta-image-ring: var(--line);
  --ta-check-size: 14px;  --ta-check-radius: var(--radius-sm);
  --ta-check-line: var(--line-strong);  --ta-check-on: var(--primary);
  --ta-toggle-w: 30px;  --ta-toggle-h: 16px;  --ta-toggle-radius: 999px;
  --ta-toggle-off: var(--neutral-soft);
  --ta-field-h: 24px;
  --ta-cell-input-bg: transparent;   --ta-cell-input-line: transparent;
  --ta-cell-input-minw: 90px;
  --ta-cell-select-bg: transparent;  --ta-cell-select-line: transparent;
  --ta-swatch-size: 14px;
  --ta-layout-gap: 8px;  --ta-stack-gap: 2px;
  --ta-panel-bg: var(--surface-2);  --ta-panel-line: var(--line-soft);
  --ta-search-w: 230px;  --ta-search-bg: var(--input-bg);  --ta-search-line: var(--input-border);
  --ta-filter-bar-bg: var(--surface-2);
  --ta-filter-badge-bg: var(--primary-soft);  --ta-filter-badge-radius: 999px;
  --ta-colman-handle: var(--faint);  --ta-colman-step: 8px;
  --ta-empty-icon-bg: var(--surface-2);  --ta-empty-icon-radius: 999px;
  --ta-selection-bar-bg: var(--primary-soft);
  --ta-sort-icon: var(--faint);
  --th-sorted-ink: var(--ink);
  --th-sorted-underline: var(--primary);  --th-sorted-underline-w: 2px;
  --ta-actions-gap: 4px;
  --ta-action-btn-size: 20px;  --ta-action-icon-size: 14px;
  /* Действия проявляются по наведению: в покое они не спорят с данными. */
  --ta-actions-idle-opacity: .35;

  /* Полосы прокрутки. Их в админке много — под вкладками, в таблицах, в
     выпадающих списках, — и стоковая браузерная выглядит инородно: толстая,
     серая, со стрелками. Прятать нельзя: полоса — единственный способ
     добраться там, где колесо не крутит вбок. */
  --scrollbar-size:  8px;
  --scrollbar-thumb: var(--line-strong);
  --scrollbar-track: transparent;
  /* ОСЬ: секция. Коробка с рамкой ↔ лист с тенью без рамки ↔ без контейнера. */
  --section-bg:        var(--surface);
  --section-border:    var(--line);
  --section-shadow:    var(--shadow-sm);
  --section-pad:       var(--d-section-pad, var(--pad));
  --section-secondary-bg: var(--surface-2);
  --section-footer-bg: var(--surface-2);
  --fieldset-bg:       transparent;
  --fieldset-border:   var(--line);

  /* Сетка и мастер. */
  --grid-gap-x:     12px;
  --grid-gap-y:     10px;
  --grid-gap-dense: 6px;
  --step-bg:            var(--surface);
  --step-border:        var(--line);
  --step-active-bg:     var(--primary-soft);
  --step-active-border: var(--primary);
  --step-marker-bg:     var(--neutral-soft);
  --chart-aspect:   16 / 9;

  /* ОСЬ: виджет инфопанели. Значения сняты ЗАМЕРОМ с эталона (характер 01,
     1440×900), а не выбраны на вкус: карточка показателя 196×76 при поле 9/11,
     подпись 11px ОБЫЧНЫМ регистром, число 19px/600. У нас было 42px/800
     заглавными с разрядкой и цветной плиткой значка 64×64 — три приметы разом.
     Иконочной плитки у эталона нет вовсе, значок остаётся при подписи. */
  /* Пять имён ниже здесь НЕ объявлены намеренно: `--w-pad-x`, `--w-pad-y`,
     `--w-value-font`, `--w-chart-h`, `--w-grid-gap`. Их читают сами правила
     цепочкой `var(--w-…, var(--d-w-…, умолчание))`, и порядок в ней и есть
     «характер сильнее плотности».

     Объявить их тут нельзя: `var()` внутри объявления переменной подставляется
     на ТОМ ЖЕ элементе, а `--d-*` живут на <body> — до `:root` они не достают, и
     уровень плотности молча не сработал бы вовсе. Ровно это и вышло при первом
     заходе: график остался 130px в «максимальной» плотности, потому что взял
     запасное значение, а не значение уровня. Характер объявляет `--w-*` в своём
     `:root` — и тогда побеждает он, как и задумано.

     (Тем же способом сломан `--input-h` в блоке выше — он тоже читает `--d-*`
     из `:root` и никогда его не видит. Правится там же, отдельно.) */
  --w-label-font:   11px;
  --w-label-weight: 400;
  --w-label-ink:    var(--faint);
  --w-value-weight: 600;
  --w-value-ink:    var(--ink);
  --w-value-track:  normal;
  --w-foot-font:    var(--font-sm);
  --w-foot-ink:     var(--mute);
  --w-title-font:   12.5px;
  --w-title-weight: 600;
  --w-axis-font:    10px;
  --w-axis-ink:     var(--faint);
  --w-icon-size:    14px;
  --w-icon-ink:     var(--faint);
  /* Столбец эталона — плоский тон без скругления; серии различаются ТОНОМ
     (план приглушённый, факт фирменный), а не градиентом внутри одного цвета. */
  --w-bar-radius:   0px;
  --w-bar-gap:      2px;
  --w-group-gap:    8px;
  /* Ширина столбца ограничена: у эталона на десяти делениях столбец выходит
     34px, а у нас делений бывает шесть — без потолка они разъезжаются в плиты
     по сто пикселей, и график читается как заливка, а не как данные. */
  --w-bar-max:      44px;
  /* Мера доли в строке топ-листа. Список занимает ряд целиком, поэтому полоса
     «во всю ширину» — это 1080px заливки на 1440: громче всего на инфопанели и
     читается подчёркиванием подписи. Потолок снят с эталона: самая громкая
     заливка в его строке — плашка 38×16px, 608px² краски; 88×3 даёт 264px². */
  --w-top-meter-w:  88px;
  --w-series-1:     var(--primary);
  --w-series-2:     var(--neutral-soft);
  --w-series-3:     color-mix(in srgb, var(--primary) 45%, var(--surface));
}

/* Тёмная тема правит только то, что в ней ЗНАЧИТ ДРУГОЕ. */
/* `.dark, body.dark, .dark body` — обратная сторона того же правила, что и у
   светлого словаря. Раз светлые значения объявлены и на `body`, собственное
   объявление элемента бьёт значение, унаследованное от `.dark` на <html>, — и
   тёмная тема до содержимого не доезжает вовсе: карточки остаются белыми.
   Три агента наткнулись на это независимо. */
.dark, body.dark, .dark body {
  --on-bad: var(--skin-bg);  --on-ok: var(--skin-bg);
  --on-warn: var(--skin-bg); --on-info: var(--skin-bg);
  --on-neutral: var(--skin-bg);
  --overlay-ink: color-mix(in srgb, #000 70%, transparent);
}

/* ── Две мины в именах, обе проверены на собранном CSS Filament v5 ─────────
   1. `--bg` у Filament ЗАНЯТО: это внутренний канал цветных компонентов
      (`.fi-bg-color-600{--bg:var(--color-600)}` → `.fi-btn.fi-color{
      background-color:var(--bg)}`). Объявить его глобально = залить фоном
      страницы всё, что не выставило своё значение. Поэтому холст у нас зовётся
      `--skin-bg`; в блоке облика из библиотеки надо переименовать одну строку.
   2. `--radius-lg` у Filament используется 106 раз в собственных утилитах.
      Значение облика мы отдаём намеренно: форма — часть характера, и пусть
      панель скругляется заодно. Если когда-нибудь это помешает — развести
      так же, как `--bg`.
   ────────────────────────────────────────────────────────────────────────── */

/* Псевдонимы прежнего словаря: правила ниже писались на `--bf-*` и остаются
   как были. Меняется только источник значений. */
/* `:root, body` — не украшение. Уровень плотности ставит свои `--d-*` классом
   на <body>, а подстановка `var()` считается НА ТОМ ЖЕ элементе, где объявлена:
   из `:root` до `body` она не достаёт, и уровень молча переставал действовать —
   поле держалось 26px и в «просторно», и в «максимуме». Объявляем на обоих. */
:root, body {
  --bf-bg:        var(--skin-bg);
  --bf-surface:   var(--surface);
  --bf-ink:       var(--ink);
  --bf-ink-soft:  var(--body);
  --bf-ink-mute:  var(--mute);
  --bf-line:      var(--line);
  --bf-line-soft: var(--line-soft);
  --bf-radius:    var(--d-bf-radius, var(--radius-lg));
  --bf-radius-sm: var(--d-bf-radius-sm, var(--radius));
  --bf-shadow:    var(--shadow);
  --bf-shadow-sm: var(--shadow-sm);
}

/* ── App shell ─────────────────────────────────────────────────────────── */
.fi-body { background: var(--bf-bg) !important; color: var(--bf-ink); -webkit-font-smoothing: antialiased; }
/* Замер на живой админке (1440×900): до первой строки данных было 356px, из них
   110 — чистый воздух между блоками. Не толстые компоненты, а промежутки.
   Поля страницы, отступ под заголовком и шаг сетки страницы поджаты втрое. */
.fi-main { background: transparent !important; padding: 16px 20px !important; }
.fi-page, .fi-page-content { gap: 16px !important; }
.fi-main-ctn { background: transparent !important; }

/* ── Topbar ────────────────────────────────────────────────────────────── */
.fi-topbar > nav,
.fi-topbar {
  background: var(--bf-surface) !important;
  border-bottom: 1px solid var(--bf-line) !important;
  box-shadow: none !important;
}

/* ── Sidebar ───────────────────────────────────────────────────────────── */
.fi-sidebar, .fi-main-sidebar {
  background: var(--bf-surface) !important;
  border-right: 1px solid var(--bf-line) !important;
}
.fi-sidebar-header {
  background: var(--bf-surface) !important;
  border-bottom: 1px solid var(--bf-line-soft) !important;
  box-shadow: none !important;
}
.fi-sidebar-nav { padding: 10px 12px !important; }
.fi-sidebar-group + .fi-sidebar-group { margin-top: 4px; }
/* Пункт меню целиком описан выше, в блоке «Боковое меню сведено с эталоном».
   Здесь его держать нельзя: это правило стояло в файле ПОЗЖЕ и побеждало, из-за
   чего пункт оставался 35px при заданных 27. Шестой за день случай двух хозяев
   у одного элемента. */
.dark .fi-sidebar-item.fi-active > .fi-sidebar-item-btn {
  background: color-mix(in srgb, var(--primary-500) 18%, transparent) !important;
  color: var(--primary-300) !important;
}
.dark .fi-sidebar-item.fi-active > .fi-sidebar-item-btn .fi-sidebar-item-icon { color: var(--primary-400) !important; }

/* ── Page header ───────────────────────────────────────────────────────── */
.fi-header-heading {
  font-size: 22px !important; font-weight: 700 !important;
  letter-spacing: -.015em !important; color: var(--bf-ink) !important;
}
.fi-header { margin-bottom: 12px !important; }

/* Шапка страницы — одной строкой.
   Замер: крошки (20px) и заголовок (25px) стояли друг под другом, и вся шапка
   занимала 59px, а контейнер добавлял ещё 32 зазора. Эталон библиотеки держит
   название, путь и главную кнопку в одной полосе — оттого у него до данных 168px,
   а у нас было 293. Крошки уходят влево от заголовка и сжимаются первыми:
   путь важен, но не важнее строк на экране. */
.fi-header > :first-child {
  display: flex !important; align-items: baseline; gap: 10px;
  min-width: 0; flex-wrap: wrap;
}
.fi-header .fi-breadcrumbs {
  flex: 0 1 auto; min-width: 0; order: -1;
  padding-right: 14px; margin-right: 2px;
  border-right: 1px solid var(--line);
  font-size: 12px; color: var(--faint);
}
.fi-header .fi-breadcrumbs-list { flex-wrap: nowrap; }
.fi-header .fi-breadcrumbs-item:not(:last-child) { white-space: nowrap; }
/* Контейнер страницы держал `padding: 32px 0` — 32px пустоты над шапкой на
   каждом экране админки. Это была самая крупная единичная потеря высоты. */
.fi-page-header-main-ctn { gap: 0 !important; padding-block: 0 !important; }
/* Кнопки шапки несли `margin-top: 28px` — отступ, которым их отодвигали вниз,
   пока крошки и заголовок стояли в два этажа. Теперь этаж один, и отступ был
   единственным, из-за чего шапка занимала 59px вместо 32. */
.fi-header { align-items: center !important; }
.fi-header-actions-ctn { margin-top: 0 !important; }

/* ── Table as an elevated card ─────────────────────────────────────────── */
.fi-ta-ctn {
  background: var(--bf-surface) !important;
  border: 1px solid var(--bf-line) !important;
  border-radius: var(--bf-radius) !important;
  box-shadow: var(--bf-shadow) !important;
  overflow: hidden;
}
.fi-ta-header-cell {
  background: var(--bf-line-soft) !important;
  border-bottom: 1px solid var(--bf-line) !important;
}
/* Filament ставит шапке заглавные сам — снимаем. 11px с разрядкой читается
   хуже 12px обычным регистром и старит таблицу сильнее всего остального. */
.fi-ta-header-cell,
.fi-ta-header-cell-sort-btn,
.fi-ta-header-cell .fi-ta-text {
  text-transform: none !important; letter-spacing: 0 !important;
  font-size: 12px !important; font-weight: 600 !important;
  color: var(--mute) !important;
}
.fi-ta-row { transition: background .12s; }
.fi-ta-row:not(:last-child) > .fi-ta-cell { border-bottom: 1px solid var(--bf-line-soft) !important; }
.fi-ta-row:hover { background: color-mix(in srgb, var(--primary-500) 4.5%, transparent) !important; }
.dark .fi-ta-row:hover { background: color-mix(in srgb, var(--primary-500) 10%, transparent) !important; }
.fi-ta-cell { color: var(--bf-ink) !important; }
/* Цвет текста ячейки НЕ задаём здесь: у колонки бывает свой (`fi-color-primary`
   у первой колонки, серый у приглушённой), и общее правило его затирало —
   `->color('primary')` формально применялся, а на экране ничего не менялось.
   Цвет по умолчанию наследуется от `.fi-ta-cell`. */
.fi-ta-cell .fi-ta-text-item:not([class*="fi-color-"]) { color: var(--body); }
.fi-ta-cell .fi-color-gray, .fi-ta-cell .fi-ta-text-item-muted { color: var(--bf-ink-soft) !important; }

/* Итоговая строка группы. Filament рисует её в полный рост — 77px ради одного
   числа, — и в реестре с разрезом на четыре группы это четыре таких строки.
   Итог должен подводить черту, а не спорить с данными за место. */
.fi-ta-summary .fi-ta-cell,
.fi-ta-summary-row .fi-ta-cell { padding-block: 2px !important; }
.fi-ta-text-summary {
  padding: 0 !important; min-height: 0 !important;
  font-size: 12px; font-weight: 600; color: var(--body);
}
.fi-ta-text-summary-label { color: var(--faint); font-weight: 500; }

/* Полосы над таблицей.
   Замер живого экрана: до первой строки данных 331px против 168 у эталона, и
   львиная доля — не содержимое, а зазоры между тремя полосами подряд.
   Вкладки кластера вдобавок центрировались автоотступами по 322px с каждой
   стороны — в реестре, где всё остальное прижато влево. */
.fi-page-sub-navigation-tabs {
  padding: 3px !important;
  margin-inline: 0 !important;
  width: fit-content;
  margin-bottom: 8px !important;
}
.fi-page-sub-navigation-tabs .fi-tabs-item { padding-block: 5px !important; }

/* ── Buttons ───────────────────────────────────────────────────────────── */
.fi-btn { border-radius: var(--bf-radius-sm) !important; font-weight: 600 !important; }
/* Заливка берётся на ступень темнее акцента. Причина замерена: при светлом
   фирменном цвете белая надпись на 600-й ступени давала 4.03:1 при норме 4.5 —
   и проваливалась ровно главная кнопка экрана. 600 остаётся ссылкам и графике,
   где текст не лежит НА цвете. */
.fi-btn.fi-color-primary {
  background: var(--primary-700, var(--primary)) !important;
  color: var(--on-primary) !important;
  box-shadow: 0 1px 2px rgba(15, 23, 42, .1), 0 6px 16px -6px color-mix(in srgb, var(--primary-600) 55%, transparent) !important;
  transition: transform .12s, box-shadow .15s, background .15s;
}
.fi-btn.fi-color-primary:hover { background: var(--primary-800, var(--primary-hover)) !important; transform: translateY(-1px); }
.fi-icon-btn { border-radius: var(--bf-radius-sm) !important; }

/* ── Inputs / search ───────────────────────────────────────────────────── */
/* Поля ввода целиком описаны в `parts/form-fields.css` — там все шесть
   состояний и обе оси характера (заливка без рамки ↔ белое с рамкой).
   Здесь их не держим: два хозяина у одного элемента — это ровно то, из-за
   чего поле оставалось 40px при формально верных правилах в части. */

/* ── Pagination ────────────────────────────────────────────────────────── */
.fi-pagination-item-btn { border-radius: 9px !important; }
.fi-pagination-item-btn.fi-active { background: var(--primary) !important; color: var(--on-primary) !important; }

/* ── Badges (кросс со статусами) ───────────────────────────────────────── */
.fi-badge { border-radius: var(--radius-sm) !important; font-weight: 600 !important; }

/* Тихие плашки в таблице.
   Когда каждое состояние залито своим цветом, реестр превращается в витраж и
   тревожное перестаёт быть заметным — глазу не за что зацепиться. Поэтому в
   ячейках состояние по умолчанию читается точкой и словом, а заливку получает
   только то, что требует действия: просрочено, отказ, ошибка. */
.fi-ta-cell .fi-badge {
  /* Через токены, а не жёстко: иначе ось «плашка заливкой ↔ точкой» работала бы
     везде, кроме реестра — то есть там, где её и видно. */
  background: var(--ta-badge-bg) !important;
  padding-inline: var(--badge-pad-x) !important;
  gap: 6px;
  color: var(--body) !important;
  padding: var(--d-ta-badge-pad, 0 6px) !important;
  font-size: var(--d-ta-badge-font, 11px) !important;
  line-height: var(--d-ta-badge-lh, 15px) !important;
}
.fi-ta-cell .fi-badge::before {
  content: ''; flex: none;
  width: var(--badge-dot); height: var(--badge-dot); border-radius: 50%;
  background: currentColor;
}
.fi-ta-cell .fi-badge.fi-color-success::before { background: var(--ok); }
.fi-ta-cell .fi-badge.fi-color-warning::before { background: var(--warn); }
.fi-ta-cell .fi-badge.fi-color-info::before,
.fi-ta-cell .fi-badge.fi-color-primary::before { background: var(--info); }
.fi-ta-cell .fi-badge.fi-color-gray::before { background: var(--neutral); }
/* Единственное исключение — то, из-за чего человек и открыл этот список. */
.fi-ta-cell .fi-badge.fi-color-danger {
  background: var(--bad-soft) !important;
  color: var(--bad) !important;
  padding-inline: 7px !important;
}
.fi-ta-cell .fi-badge.fi-color-danger::before { background: var(--bad); }

/* ── Dropdowns / панели ────────────────────────────────────────────────── */
.fi-dropdown-panel {
  border-radius: var(--bf-radius-sm) !important;
  border: 1px solid var(--bf-line) !important;
  box-shadow: var(--bf-shadow) !important;
}

/* ── Sections / cards / widgets (формы, виджеты) ───────────────────────── */
.fi-section,
.fi-wi,
.fi-fo-component-ctn > .fi-section {
  background: var(--bf-surface) !important;
  border: 1px solid var(--bf-line) !important;
  border-radius: var(--bf-radius) !important;
  box-shadow: var(--bf-shadow) !important;
}
.fi-section-header { border-bottom: 1px solid var(--bf-line-soft) !important; }
.fi-section-header-heading { font-weight: 700 !important; color: var(--bf-ink) !important; }

/* Форма: подписи полей */
.fi-fo-field-wrp-label, .fi-fo-field-wrp-label > * { color: var(--bf-ink-soft) !important; font-weight: 600 !important; }

/* ── Stat-виджеты (KPI-карточки) ─────────────────────────────────────────
   Родной StatsOverview Filament: подчиняется той же оси, что и наши карточки,
   иначе на одной инфопанели окажутся два разных представления одного «числа
   с подписью». Подпрыгивание по наведению убрано: карточка не кнопка. */
.fi-wi-stats-overview-stat {
  background: var(--surface) !important;
  border-radius: var(--radius) !important;
  border: 1px solid var(--line-soft) !important;
  box-shadow: var(--shadow-sm) !important;
  padding: var(--w-pad-y, var(--d-w-pad-y, 12px)) var(--w-pad-x, var(--d-w-pad-x, 14px)) !important;
}
.fi-wi-stats-overview-stat-label {
  font-size: var(--w-label-font) !important;
  font-weight: var(--w-label-weight) !important;
  color: var(--w-label-ink) !important;
  text-transform: none !important;
  letter-spacing: normal !important;
}
.fi-wi-stats-overview-stat-value {
  font-size: var(--w-value-font, var(--d-w-value-font, 22px)) !important;
  font-weight: var(--w-value-weight) !important;
  letter-spacing: var(--w-value-track);
  line-height: 1.25 !important;
  color: var(--w-value-ink) !important;
  font-variant-numeric: tabular-nums;
}
.fi-wi-stats-overview-stat-description {
  font-size: var(--w-foot-font) !important;
  color: var(--w-foot-ink) !important;
}

/* ── Хлебные крошки ────────────────────────────────────────────────────── */
.fi-breadcrumbs { font-size: 12px; }
.fi-breadcrumbs-item-label { color: var(--bf-ink-mute) !important; }

/* ── Refined scrollbars ────────────────────────────────────────────────── */
.fi-ta-content-ctn::-webkit-scrollbar { height: 10px; width: 10px; }
.fi-ta-content-ctn::-webkit-scrollbar-thumb { background: var(--bf-line); border-radius: 99px; border: 3px solid var(--bf-surface); }
.fi-ta-content-ctn::-webkit-scrollbar-thumb:hover { background: var(--bf-ink-mute); }

/* ============================================================================
   ПЛОТНОСТЬ ИНТЕРФЕЙСА
   ----------------------------------------------------------------------------
   Стоковый Filament очень воздушный: на вьюпорте 900px шаг строки таблицы 83px
   (при одной строке текста), первая строка данных начинается на y=350 — 39%
   экрана уходит до данных, помещается 6 строк. Для реестров и справочников это
   дорого: монитор большой, информации мало.

   Главный виновник — НЕ ячейка, а `.fi-ta-text-item` внутри неё: padding 16px
   сверху и снизу + line-height 24px, поверх padding самой ячейки 13/24.

   Класс ставится на <body> из Project.settings.density → работает и в превью,
   и в экспорте (превью == экспорт == прод). Отсутствие класса = стоковая
   просторная раскладка, поэтому ничего не меняется само собой.
   ============================================================================ */

/* ── Плотно: рабочая плотность для реестров ─────────────────────────────── */
/* Плотность меняет ЗНАЧЕНИЕ токена, а не спорит с правилом. Прямое правило по
   `.fi-input` добавляло полю 5px сверху и снизу поверх части — поле держалось
   34px при заданных 26. У элемента один хозяин; плотность — это ручка, а не
   второй хозяин. */
/* Но плотность обязана быть ЗАПАСНЫМ значением, а не решением. Класс на <body>
   сильнее любого `:root` по весу — облик, объявивший своё `--input-h`, молча
   проигрывал бы уровню плотности: цвет менялся бы, а размеры нет. Поэтому
   уровень задаёт `--d-*`, а `--input-h` подхватывает его лишь тогда, когда
   характер промолчал. Характер сам решает, насколько он плотный. */
body.bf-density-compact { --d-ta-badge-pad: 1px 7px; --d-ta-badge-font: 11.5px; --d-ta-badge-lh: 16px; --d-input-h: 28px; --d-btn-h: 28px; --d-btn-pad-x: 12px; --d-btn-font: 13px;   --d-section-pad: 16px; --d-section-gap: 14px; }
body.bf-density-dense   { --d-ta-badge-pad: 0 6px;  --d-ta-badge-font: 11px;   --d-ta-badge-lh: 15px; --d-input-h: 26px; --d-btn-h: 26px; --d-btn-pad-x: 10px; --d-btn-font: 12.5px; --d-section-pad: 13px; --d-section-gap: 10px; }

body.bf-density-compact {
  --d-bf-radius: 11px;
  --d-bf-radius-sm: 8px;
}
body.bf-density-compact .fi-main { padding: 15px 18px 22px !important; }
body.bf-density-compact .fi-topbar { min-height: 52px !important; }
body.bf-density-compact .fi-sidebar,
body.bf-density-compact .fi-main-sidebar { width: 256px !important; }
body.bf-density-compact .fi-sidebar-header { min-height: 52px !important; }

body.bf-density-compact .fi-header { margin-bottom: 12px !important; gap: 10px !important; }
body.bf-density-compact .fi-header-heading { font-size: 21px !important; line-height: 1.2 !important; }

body.bf-density-compact .fi-ta-header-cell { padding: 8px 12px !important; }
/* Высоту ряда задаёт САМАЯ высокая ячейка, а это не текст, а плашка состояния:
   замер дал 32px у плашки против 26 у текста. Поджимать текст, не тронув плашку,
   бесполезно — ряд не сдвинется ни на пиксель. */
/* Пустая ячейка была ВЫШЕ заполненной: обёртка `.fi-ta-text` несёт свои
   отступы, и без содержимого внутри они остаются одни — ряд подскакивал
   с 23px до 33. Ритм таблицы рвался там, где в данных пропуск. */
body.bf-density-compact .fi-pagination { padding: 8px 14px !important; }

body.bf-density-compact .fi-fo-component-ctn { gap: 12px !important; }
body.bf-density-compact .fi-in-entry-wrp { padding-block: 6px !important; }

/* ── Максимум: реестр как в учётной системе ─────────────────────────────── */
body.bf-density-dense {
  --d-bf-radius: 9px;
  --d-bf-radius-sm: 7px;
}
body.bf-density-dense .fi-main { padding: 10px 12px 16px !important; }
body.bf-density-dense .fi-topbar { min-height: 46px !important; }
body.bf-density-dense .fi-sidebar,
body.bf-density-dense .fi-main-sidebar { width: 206px !important; }
body.bf-density-dense .fi-sidebar-header { min-height: 46px !important; }

body.bf-density-dense .fi-header { margin-bottom: 8px !important; gap: 8px !important; }
body.bf-density-dense .fi-header-heading { font-size: 18px !important; line-height: 1.2 !important; }
body.bf-density-dense .fi-breadcrumbs { font-size: 11px; }

body.bf-density-dense .fi-ta-header-cell { padding: 6px 10px !important; }
body.bf-density-dense .fi-pagination { padding: 6px 12px !important; }

body.bf-density-dense .fi-fo-component-ctn { gap: 9px !important; }
body.bf-density-dense .fi-in-entry-wrp { padding-block: 4px !important; }

/* ── Инфопанель: виджеты ──
   Карточка показателя ради одного числа занимала 110px при паддинге 24px,
   график — 260px, зазор между виджетами 24px. На вьюпорте 900 инфопанель
   уезжала в скролл на 430px.

   Уровень плотности отдаёт виджетам ЗНАЧЕНИЯ (`--d-w-*`), а не правила: правило
   с классом на <body> перебило бы облик молча, и характер, попросивший крупное
   число, получил бы плотное. Сами правила — ниже, в разделе виджетов. */
body.bf-density-compact { --d-w-pad-x: 12px; --d-w-pad-y: 10px; --d-w-value-font: 20px; --d-w-chart-h: 145px; --d-w-grid-gap: 10px; --d-w-chart-max: 200px; }
body.bf-density-dense   { --d-w-pad-x: 11px; --d-w-pad-y:  9px; --d-w-value-font: 19px; --d-w-chart-h: 130px; --d-w-grid-gap:  8px; --d-w-chart-max: 168px; }

.fi-wi-chart canvas { max-height: var(--d-w-chart-max, 240px); }

/* Кнопки и поля тоже ужимаются — иначе они торчат из плотных строк. */

/* ============================================================================
   ВИДЖЕТЫ ИНФОПАНЕЛИ
   ----------------------------------------------------------------------------
   Три виджета (показатели, график, таблица) раньше рисовал нативный Filament, и
   выглядели плоско ровно они: у StatsOverview нет ни искры, ни прогресса, ни
   плотных плиток, а график — Chart.js со стоковой легендой. Остальные одиннадцать
   давно рисуются своим Blade, поэтому разнобой был виден и без сравнения.

   Здесь ЕДИНЫЙ язык для всех: ФОРМА виджета (что показывает) отделена от СЕМЬИ
   (какой характер). Семья приезжает из отрасли и вешается классом на <body> —
   тем же способом, что и плотность, поэтому автоматически попадает в экспорт.

   Дизайны отрисованы и отобраны на /widgets-lab.
   ============================================================================ */

.fi-body {
  --bf-w-ok:   var(--ok);
  --bf-w-warn: var(--warn);
  --bf-w-bad:  var(--bad);
}

/* Ниже — ПОЛНЫЙ перенос библиотеки виджетов со стенда `/widgets-lab`.
   Стенд был нарисован целиком: двадцать анатомий и три семьи, у каждой формы
   записано, зачем она. Перенесли тогда треть — и ровно без вариантов карточки
   показателя, из-за чего инфопанель собранного приложения выглядела стоковой
   при готовой библиотеке. Токены стенда с самого начала совпадали с темой
   («чтобы перенос был механическим»), поэтому перенос и сделан машинально.

   Правило: правка живёт НА СТЕНДЕ и оттуда переносится сюда. Разойдутся —
   и мы снова будем рисовать одно, а показывать другое. */

    /* ═══════════════ ФОРМЫ ВИДЖЕТОВ ═══════════════ */

    /* Коробка виджета — тот же «лист», что и секция: `--surface`, волосок
       `--line-soft`, мягкая тень. Раньше тут стояла БОЛЬШАЯ тень (`--shadow`,
       28px размытия) и радиус `--radius-lg` — карточка отрывалась от холста
       вдвое сильнее реестра, стоящего рядом на той же странице. */
    .bf-w {
        background: var(--surface); border: 1px solid var(--line-soft);
        border-radius: var(--radius); box-shadow: var(--shadow-sm);
        padding: var(--w-pad-y, var(--d-w-pad-y, 12px)) var(--w-pad-x, var(--d-w-pad-x, 14px));
        /* Ячейка сетки тянется по самому высокому соседу — карточка обязана
           тянуться за ней, иначе ряд выходит рваным. */
        height: 100%;
    }
    .bf-w-label {
        font-size: var(--w-label-font); font-weight: var(--w-label-weight);
        color: var(--w-label-ink); line-height: 1.35;
        display: flex; align-items: center; gap: 5px;
    }
    .bf-w-value {
        font-size: var(--w-value-font, var(--d-w-value-font, 22px)); font-weight: var(--w-value-weight);
        letter-spacing: var(--w-value-track); line-height: 1.25;
        color: var(--w-value-ink); font-variant-numeric: tabular-nums;
    }
    .bf-w-foot { display: flex; align-items: baseline; flex-wrap: wrap; gap: 6px; font-size: var(--w-foot-font); color: var(--w-tone, var(--w-foot-ink)); }
    .bf-w-delta { display: inline-flex; align-items: center; gap: 3px; font-weight: 600; }
    .bf-w-delta.up { color: var(--bf-w-ok); }
    .bf-w-delta.down { color: var(--bf-w-bad); }
    .bf-w-empty { font-size: var(--w-foot-font); color: var(--w-foot-ink); }

    /* Значок ПРИ ПОДПИСИ, а не плитка перед числом. Плитка 64×64 со скруглением
       и цветной заливкой — примета 2010-х; она же съедала полкарточки и делала
       все счётчики похожими друг на друга, потому что цвет плитки читался
       раньше числа. */
    .bf-w-icon { display: inline-flex; flex: none; color: var(--w-tone, var(--w-icon-ink)); }
    .bf-w-icon svg, svg.bf-w-icon, .bf-w-label .fi-icon {
        width: var(--w-icon-size); height: var(--w-icon-size); flex: none;
    }

    /* Тон показателя. Красит подстрочник и значок, но НЕ число: у эталона число
       всегда цвета текста, а состояние несёт подпись под ним — «2 просрочены»
       красным, «было 4,1 дн.» зелёным. Пять разноцветных цифр в ряд превращали
       инфопанель в витраж, из которого не выделяется ничего.
       Спокойные тона (primary / info / gray) молчат намеренно: «сколько
       договоров» — не состояние, и красить там подпись значит кричать без
       повода; таких карточек на экране большинство. */
    .bf-w-t-success { --w-tone: var(--ok); }
    .bf-w-t-warning { --w-tone: var(--warn); }
    .bf-w-t-danger  { --w-tone: var(--bad); }

    /* Ряд показателей одним виджетом (форма `stats`): карточки внутри тянутся
       по самой высокой, иначе ряд выходит ступеньками. */
    .bf-w-heading { font-size: var(--w-title-font); font-weight: var(--w-title-weight); color: var(--ink); margin-bottom: 8px; }
    .bf-w-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: var(--w-grid-gap, var(--d-w-grid-gap, 12px)); align-items: stretch; }

    .bf-w-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 10px; }
    .bf-w-head h3 { font-size: var(--w-title-font); font-weight: var(--w-title-weight); color: var(--ink); }
    .bf-w-hint { font-size: var(--w-foot-font); color: var(--w-foot-ink); }

    /* kpi — подпись, число, подстрочник. Три строки, ничего между ними:
       у эталона карточка занимает 76px и в ряд их влезает шесть.

       Высота — ПО СОДЕРЖИМОМУ, в отличие от остальных форм. Ячейка сетки
       тянется по самому высокому соседу, и счётчик рядом с графиком раздувался
       со своих 78px до 240 — две трети карточки уходили в белое поле. Внутри
       собственного ряда (`.bf-w-row`) карточки всё равно ровняются друг по
       другу: там растягивает сетка, а не эта высота. */
    .bf-w-kpi { display: flex; flex-direction: column; gap: 1px; height: auto; }
    /* Карточка БЕЗ подстрочника не должна быть ниже соседки с ним: замер дал
       60px против 78 в одном ряду, и разнобой читается как сбой вёрстки, а не
       как «тут нечего дописать». Держим место пустой строкой того же кегля —
       тогда высота сходится сама при любой плотности и любом характере, а
       считать её в calc не приходится. */
    .bf-w-kpi:not(:has(.bf-w-foot))::after {
        content: '\00a0';
        font-size: var(--w-foot-font);
    }

    /* kpi-spark — число рядом с формой кривой: цифра говорит «сколько»,
       линия — «куда идёт». Вместе занимают столько же места. */
    .bf-w-spark { margin-top: 6px; height: 30px; display: block; width: 100%; }
    .bf-w-spark path.line { fill: none; stroke: var(--primary); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
    .bf-w-spark path.area { fill: color-mix(in srgb, var(--primary) 12%, transparent); stroke: none; }

    /* kpi-progress — число и цель: без второго первое не с чем сравнить. */
    .bf-w-bar { margin-top: 6px; height: 4px; border-radius: 99px; background: var(--neutral-soft); overflow: hidden; }
    .bf-w-bar span { display: block; height: 100%; border-radius: 99px; background: var(--primary); }

    /* kpi-tile — плотная плитка для операционных экранов: числа крупные,
       воздуха мало, помещается вдвое больше. */
    .bf-w-kpi-tile { flex-direction: row; align-items: center; justify-content: space-between; gap: 10px; }

    /* chart-bars — «сколько за период». Столбцы читаются точнее линии,
       когда точек мало. Заливка ПЛОСКАЯ: градиент внутри одного цвета не несёт
       смысла, а разные серии им уже не различить. */
    .bf-w-chart { padding-bottom: 12px; }
    /* ── Ось значений и подсказка ────────────────────────────────────────
       График без оси показывает только форму: «выше — больше», а насколько и
       сколько это в штуках — неизвестно. Владелец сказал ровно это: «много где
       нет осей значений». Ось идёт слева от поля, тремя делениями.

       Подсказка своя, а не родная `title`: та появляется через секунду, и
       человек, поводив мышью, решает, что её нет вовсе. */
    .bf-w-plot { display: flex; align-items: stretch; gap: 8px; }
    .bf-w-plot > .bf-w-bars,
    .bf-w-plot > .bf-w-area { flex: 1; min-width: 0; }
    .bf-w-yaxis {
      display: flex; flex-direction: column; justify-content: space-between;
      height: var(--w-chart-h, var(--d-w-chart-h, 160px));
      margin-top: 6px; padding-right: 2px;
      font-size: 10.5px; line-height: 1; color: var(--ink-faint);
      text-align: right; white-space: nowrap; flex: none;
    }
    .bf-w-bars i { position: relative; }
    .bf-w-bars i[data-tip]:hover::after {
      content: attr(data-tip);
      position: absolute; bottom: calc(100% + 6px); left: 50%; transform: translateX(-50%);
      z-index: 20; padding: 4px 8px; border-radius: 6px;
      background: var(--ink); color: var(--surface);
      font-size: 11px; line-height: 1.3; white-space: nowrap; pointer-events: none;
      box-shadow: 0 4px 14px rgb(0 0 0 / .18);
    }

    .bf-w-bars { display: flex; align-items: flex-end; gap: var(--w-group-gap); height: var(--w-chart-h, var(--d-w-chart-h, 160px)); margin-top: 6px; }
    /* Столбцы одного деления — группой, между группами зазор шире. Плоским
       рядом с одним зазором шесть месяцев сливались в сплошную синюю плиту:
       где кончается месяц, видно не было. */
    .bf-w-bar-group { flex: 1; min-width: 0; display: flex; align-items: flex-end; justify-content: center; gap: var(--w-bar-gap); height: 100%; }
    .bf-w-bars i { flex: 1; max-width: var(--w-bar-max); display: block; border-radius: var(--w-bar-radius); background: var(--w-series-1); }
    .bf-w-bars i[data-s="1"] { background: var(--w-series-2); }
    .bf-w-bars i[data-s="2"] { background: var(--w-series-3); }
    .bf-w-axis { display: flex; gap: var(--w-group-gap); margin-top: 4px; }
    .bf-w-axis span { flex: 1; text-align: center; font-size: var(--w-axis-font); color: var(--w-axis-ink); font-variant-numeric: tabular-nums; }
    .bf-w-legend-row { display: flex; gap: 12px; margin-top: 8px; font-size: var(--w-foot-font); color: var(--w-foot-ink); }
    .bf-w-legend-row span { display: inline-flex; align-items: center; gap: 5px; }
    .bf-w-legend-row i { width: 8px; height: 8px; flex: none; border-radius: var(--w-bar-radius); background: var(--w-series-1); }
    .bf-w-legend-row span:nth-child(2) i { background: var(--w-series-2); }
    .bf-w-legend-row span:nth-child(3) i { background: var(--w-series-3); }

    /* chart-area — та же серия непрерывной заливкой: для длинных рядов. */
    .bf-w-area { height: var(--w-chart-h, var(--d-w-chart-h, 160px)); width: 100%; display: block; margin-top: 6px; }
    .bf-w-area path.fill { fill: url(#bfWGrad); stroke: none; color: var(--primary); }
    .bf-w-area path.line { fill: none; stroke: var(--primary); stroke-width: 1.8; stroke-linejoin: round; }
    .bf-w-area line { stroke: var(--line-soft); stroke-width: 1; }

    /* top-list — рейтинг: место, имя, доля. Место — приглушённая цифра, а не
       залитый кружок: у эталона на карточке нет ни одной цветной плитки, а
       ряд одинаковых синих кругов читается раньше самих названий.

       Полоса доли стояла ВТОРОЙ СТРОКОЙ под подписью, в четырёх пикселях от
       неё и во всю ширину имени. Список занимает целый ряд инфопанели, поэтому
       на 1440 полоса выходила 1080px сплошного `--primary` под коротким
       названием: глаз читал её подчёркиванием, а не мерой, и строка вырастала
       с эталонных 22px до 32.8.

       Правит это не зазор, а МЕСТО. Замер эталона (характер 01, 1440×900,
       карточки «Ждут вашей визы» / «Просрочка поставки»): строка ровно
       `--row-h` — одна линия, четыре ячейки в ряд (код · название · сумма ·
       плашка), шесть строк в карточке 165px. Лишний сигнал там едет ПОСЛЕДНЕЙ
       ЯЧЕЙКОЙ той же строки, а не следующей строкой. Полоса встала туда же:
       под подписью не остаётся ничего. Ширина ограничена `--w-top-meter-w` —
       самая громкая заливка в строке эталона это плашка 38×16px, и мера обязана
       быть не громче её.

       Ячейка ПОСЛЕ числа, а не перед: полоса фиксированной ширины держит правый
       край, поэтому числа кончаются на одном x, а полосы с одного начинаются.
       Перед числом оба столбца шли бы лесенкой — длины стало бы не с чем
       сравнивать, ради чего полоса и нужна.

       Правило `.bf-w-top-row:first-child .bf-w-rank` убрано: первый ребёнок
       карточки — заголовок, поэтому оно не срабатывало ни разу и обещало
       выделение лидера, которого не было. У эталона строки списка одинаковы. */
    .bf-w-top-row { display: flex; align-items: center; gap: 8px; height: var(--row-h); }
    .bf-w-top-row + .bf-w-top-row { border-top: 1px solid var(--line-soft); }
    .bf-w-rank { flex: none; width: 16px; font-size: var(--w-axis-font); color: var(--faint); text-align: right; font-variant-numeric: tabular-nums; }
    .bf-w-top-name { flex: 1 1 auto; min-width: 0; font-size: 12.5px; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .bf-w-top-val { flex: none; font-size: 12px; color: var(--ink); font-variant-numeric: tabular-nums; }
    .bf-w-top-bar { flex: none; width: var(--w-top-meter-w); height: 3px; border-radius: 99px; background: var(--neutral-soft); overflow: hidden; }
    .bf-w-top-bar i { display: block; height: 100%; background: var(--primary); border-radius: 99px; }

    /* donut — доли целого. Число в центре отвечает на «сколько всего». */
    .bf-w-donut-wrap { display: flex; align-items: center; gap: 18px; }
    .bf-w-donut { position: relative; flex: none; }
    .bf-w-donut figcaption {
        position: absolute; inset: 0; display: grid; place-content: center; text-align: center;
    }
    .bf-w-donut b { font-size: 20px; font-weight: 800; display: block; }
    .bf-w-donut small { font-size: 10.5px; color: var(--bf-ink-mute); }
    .bf-w-legend { display: grid; gap: 7px; font-size: 12.5px; }
    .bf-w-legend div { display: flex; align-items: center; gap: 8px; }
    .bf-w-legend i { width: 9px; height: 9px; border-radius: 3px; flex: none; }
    .bf-w-legend b { margin-left: auto; font-weight: 700; }

    /* status-grid — «что где горит». Цвет + подпись, никогда только цвет. */
    .bf-w-status { display: grid; gap: 8px; }
    .bf-w-status div { display: flex; align-items: center; gap: 9px; padding: 9px 11px; border-radius: 10px; background: color-mix(in srgb, var(--bf-ink) 3%, transparent); }
    .bf-w-dot { width: 8px; height: 8px; border-radius: 99px; flex: none; }
    .bf-w-status b { margin-left: auto; font-weight: 700; }

    /* feed — последние события. Время слева: по нему сканируют. */
    .bf-w-feed { display: grid; gap: 0; }
    .bf-w-feed div { display: grid; grid-template-columns: 46px 1fr; gap: 10px; padding: 9px 0; font-size: 13px; }
    .bf-w-feed div + div { border-top: 1px solid var(--bf-line); }
    .bf-w-feed time { color: var(--bf-ink-mute); font-size: 12px; }

    /* table-mini — реестр в миниатюре: последние записи без ухода в раздел.
       Шапка ОБЫЧНЫМ регистром: заглавные с разрядкой мы уже сняли с реестра и
       формы, и мини-таблица осталась последним местом, где они выжили. */
    .bf-w-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
    .bf-w-table th { text-align: left; font-size: var(--w-label-font); text-transform: none; letter-spacing: normal; color: var(--faint); font-weight: 600; padding-bottom: 6px; }
    .bf-w-table td { padding: 4px 0; border-top: 1px solid var(--line-soft); color: var(--ink); font-variant-numeric: tabular-nums; }
    .bf-w-table td:last-child, .bf-w-table th:last-child { text-align: right; }
    .bf-w-table-empty { color: var(--faint); text-align: center !important; padding: 14px 0 !important; }
    .bf-w-chip { display: inline-block; padding: 0 6px; border-radius: var(--radius-sm); font-size: var(--w-label-font); font-weight: 600; }

    /* gauge — одно число против нормы. Дуга показывает «далеко ли до края». */
    .bf-w-gauge { display: grid; place-items: center; }
    .bf-w-gauge figcaption { text-align: center; margin-top: -34px; }
    .bf-w-gauge b { font-size: 26px; font-weight: 800; display: block; }
    .bf-w-gauge small { font-size: 11.5px; color: var(--bf-ink-mute); }

    /* funnel — путь со ступенями. Ширина ступени = доля дошедших,
       рядом всегда процент: по одной ширине точную потерю не прочитать. */
    .bf-w-funnel { display: grid; gap: 7px; }
    /* Строка ВСЕГДА полной ширины, доля — заливкой под текстом. Если сужать
       саму строку, длинная подпись («Коммерческое предложение») ломается на две
       и наезжает на число: узкая ступень — это как раз та, где читать труднее. */
    .bf-w-funnel div { position: relative; padding: 10px 12px; border-radius: 9px; background: color-mix(in srgb, var(--bf-ink) 4%, transparent); font-size: 13px; font-weight: 600; display: flex; justify-content: space-between; gap: 14px; overflow: hidden; }
    .bf-w-funnel div::before { content: ''; position: absolute; inset: 0 auto 0 0; width: var(--share); background: color-mix(in srgb, var(--primary) 16%, transparent); border-radius: 9px; }
    .bf-w-funnel div > * { position: relative; }
    .bf-w-funnel div span { color: var(--bf-ink-mute); font-weight: 600; white-space: nowrap; }
    .bf-w-funnel div span:first-child { color: var(--bf-ink); overflow: hidden; text-overflow: ellipsis; }
    .bf-w-funnel b { font-weight: 800; color: var(--bf-ink); }

    /* progress-goal — «сколько сделано из плана». Отдельная форма, а не
       показатель: тут главное отношение, а не само число. */
    .bf-w-goal-val { display: flex; align-items: baseline; gap: 8px; margin: 2px 0 8px; }
    .bf-w-goal-val b { font-size: var(--w-value-font, var(--d-w-value-font, 22px)); font-weight: var(--w-value-weight); letter-spacing: var(--w-value-track); font-variant-numeric: tabular-nums; }
    .bf-w-goal-val span { color: var(--w-foot-ink); font-size: var(--w-foot-font); }
    .bf-w-goal-bar { height: 6px; border-radius: 99px; background: var(--neutral-soft); overflow: hidden; }
    .bf-w-goal-bar span { display: block; height: 100%; border-radius: 99px; background: var(--primary); }

    /* pie — доли целого без дырки: когда частей мало и подписи рядом. */
    .bf-w-pie-wrap { display: flex; align-items: center; gap: 18px; }

    /* heatmap — «когда густо». Час × день; цвет = плотность, число в ячейке
       не нужно — читают пятно, а не значение. */
    .bf-w-heat { display: grid; grid-template-columns: 34px repeat(12, 1fr); gap: 3px; align-items: center; }
    .bf-w-heat b { font-size: 10.5px; color: var(--bf-ink-mute); font-weight: 600; }
    .bf-w-heat i { aspect-ratio: 1; border-radius: 4px; display: block; background: var(--primary); }
    .bf-w-heat-legend { display: flex; align-items: center; gap: 6px; margin-top: 12px; font-size: 11px; color: var(--bf-ink-mute); }
    .bf-w-heat-legend i { width: 14px; height: 10px; border-radius: 3px; background: var(--primary); display: block; }

    /* map — точки на карте. В лаборатории схематично: настоящая карта тянет
       внешний тайл-сервер, и место она занимает то же. */
    .bf-w-map { position: relative; height: 190px; border-radius: 11px; overflow: hidden; background: color-mix(in srgb, var(--primary) 7%, var(--bf-surface)); border: 1px solid var(--bf-line); }
    .bf-w-map i { position: absolute; width: 11px; height: 11px; border-radius: 99px; background: var(--primary); box-shadow: 0 0 0 4px color-mix(in srgb, var(--primary) 22%, transparent); }

    /* note — заметка или инструкция. Единственная форма без чисел:
       место для правил смены, ссылок, напоминаний. */
    .bf-w-note { font-size: 13.5px; color: var(--bf-ink-soft); }
    .bf-w-note ul { margin: 8px 0 0; padding-left: 18px; display: grid; gap: 5px; }

    /* radar — сравнение по нескольким осям сразу. */
    .bf-w-radar { display: block; margin-inline: auto; }
    .bf-w-radar .grid { fill: none; stroke: var(--bf-line); }
    .bf-w-radar .shape { fill: color-mix(in srgb, var(--primary) 22%, transparent); stroke: var(--primary); stroke-width: 2; }
    .bf-w-radar .axis { stroke: var(--bf-line); }

    /* ═══════════════ СЕМЬИ ═══════════════
       Одни и те же формы, разный характер. Выбирается под отрасль так же,
       как семья сайта: складу и барбершопу не идёт одно и то же. */

    /* Спокойная — по умолчанию (описана выше). */

    /* Контрастная: тёмные плитки показателей, крупные числа, мало воздуха.
       Для операционных экранов, где смотрят весь день. */
    /* ЛОВУШКА: нельзя брать фоном токен --ink. В тёмной теме он светлеет, и
       карточка становилась светлой при белом тексте — надпись исчезала.
       Поэтому у семьи СВОЯ пара токенов, и в темноте она ИНВЕРТИРУЕТСЯ:
       контраст в тёмной теме — это светлая плитка, а не ещё более чёрная. */
    /* Семья правит ТОЛЬКО свои `--w-*`. Раньше здесь стояли `--radius` и `--pad`
       — имена из общего словаря, и класс на <body> перебивал ими облик на всей
       странице: отраслевая семья виджетов молча переставляла скругление кнопок
       и поле секций. У виджета свои ручки, чужих он не трогает. */
    body.bf-wf-contrast {
        --w-value-font: 26px; --w-value-weight: 700;
        --bf-wc-bg: #0f172a; --bf-wc-fg: #ffffff;
        --bf-wc-mute: rgba(255, 255, 255, .62); --bf-wc-soft: rgba(255, 255, 255, .16);
    }
    .dark body.bf-wf-contrast {
        --bf-wc-bg: #eef1f6; --bf-wc-fg: #0f172a;
        --bf-wc-mute: rgba(15, 23, 42, .58); --bf-wc-soft: rgba(15, 23, 42, .14);
    }
    body.bf-wf-contrast .bf-w { box-shadow: none; }
    body.bf-wf-contrast .bf-w-kpi {
        background: var(--bf-wc-bg); border-color: var(--bf-wc-bg); color: var(--bf-wc-fg);
    }
    body.bf-wf-contrast .bf-w-kpi .bf-w-value { color: var(--bf-wc-fg); }
    body.bf-wf-contrast .bf-w-kpi .bf-w-label,
    body.bf-wf-contrast .bf-w-kpi .bf-w-foot { color: var(--bf-wc-mute); }
    /* Один светлый показатель в ряду тёмных читается как ошибка вёрстки. */
    body.bf-wf-contrast .bf-w-kpi .bf-w-bar { background: var(--bf-wc-soft); }
    body.bf-wf-contrast .bf-w-kpi .bf-w-bar span { background: var(--bf-wc-fg); }
    body.bf-wf-contrast .bf-w-kpi .bf-w-icon { color: var(--bf-wc-fg); }
    body.bf-wf-contrast .bf-w-kpi .bf-w-spark path.line { stroke: var(--bf-wc-fg); }
    body.bf-wf-contrast .bf-w-kpi .bf-w-spark path.area { fill: var(--bf-wc-soft); }

    /* Мягкая: крупный радиус, подкрашенные поверхности, никаких теней.
       Для клиентских и «человеческих» продуктов. */
    body.bf-wf-soft { --w-bar-radius: 99px; --w-pad-x: 16px; --w-pad-y: 14px; }
    body.bf-wf-soft .bf-w { box-shadow: none; border-color: transparent; border-radius: var(--radius-lg); background: color-mix(in srgb, var(--primary) 6%, var(--surface)); }

    @media (prefers-reduced-motion: reduce) {
        .bf-w { transition: none; }
    }

/* Плотность действует и на виджеты — но ЗНАЧЕНИЯМИ (`--d-w-*` выше), а не
   правилами: правило с классом на <body> било бы облик молча. */

/* ── Сведение с эталоном: числа сняты с библиотеки, не выдуманы ───────────
   Эталон (1440×900, характер 01): сайдбар 206px · над таблицей ДВЕ полосы
   46+32 · шапка таблицы 24 · ряд 26 при тексте 13/18.85 · до первой строки 168.
   Ниже — приведение наших размеров к тем же величинам. Всё в «максимальной»
   плотности: она и задумана как «как у эталона».
   ────────────────────────────────────────────────────────────────────────── */
body.bf-density-dense .fi-ta-header-cell {
  padding: 3px 10px !important;
  font-size: 13px !important; font-weight: 700 !important;
  line-height: 18.85px !important;
}

/* Тулбар таблицы: у эталона поиска отдельной полосой нет вовсе — он стоит в
   строке заголовка. Разметку не трогаем, но полосу ужимаем до высоты поля. */

/* Заголовок группы: у эталона это одна строка в 26px вместе с описанием. */
/* Заголовок группы в ОДНУ строку: «Электронная подпись: не подписан ·
   3 позиции · на 3 853 543,79 ₽». Filament ставит описание под названием, и
   каждый заголовок занимал две строки вместо одной — на пяти группах это
   лишние 65px. Описание — сосед названия, а не его подпись. */
body.bf-density-dense .fi-ta-group-header { padding-block: 2px !important; }
body.bf-density-dense .fi-ta-group-header > div:has(.fi-ta-group-heading) {
  display: flex !important; align-items: baseline; gap: 10px; flex-wrap: wrap;
}
body.bf-density-dense .fi-ta-group-description { margin: 0 !important; }
body.bf-density-dense .fi-ta-group-description::before { content: '· '; }
body.bf-density-dense .fi-ta-group-heading { font-size: 12.5px !important; line-height: 17px !important; }
body.bf-density-dense .fi-ta-group-description { font-size: 11.5px !important; line-height: 15px !important; }

/* Зазоры между полосами. Замер: между вкладками и чипами 32px, между чипами и
   таблицей 16 — при том что сами полосы 36 и 28. Половина высоты над таблицей
   уходила в пустоту между блоками, а не в содержимое. */
body.bf-density-dense .fi-page,
body.bf-density-dense .fi-page-main,
body.bf-density-dense .fi-page-content { gap: 8px !important; }
body.bf-density-dense .fi-header { margin-bottom: 4px !important; }
body.bf-density-dense .fi-page-sub-navigation-tabs { margin-bottom: 0 !important; }
body.bf-density-dense .bf-deadline { margin-bottom: 6px !important; }
body.bf-density-dense .fi-main { padding: 8px 12px 12px !important; }


/* ── часть: actions.css ─────────────────────── */
/* ============================================================================
   Кнопки, действия, плашки.

   Что уже сделано в admin-theme.css и здесь НЕ повторяется:
     .fi-btn            — радиус и насыщенность шрифта;
     .fi-btn.fi-color-primary — заливка (700-я ступень), наведение, тень-подсветка;
     .fi-icon-btn       — радиус;
     .fi-badge          — радиус и насыщенность шрифта;
     .fi-ta-cell .fi-badge — тихая плашка в реестре (точка вместо заливки);
     body.bf-density-*  — шаг плотности для .fi-btn.
   Здесь — всё остальное: размеры, остальные цвета, контур, состояния,
   ссылки-действия, группы, пункты меню и ось характера плашки.

   ── Ось, на которой уже один раз сломались ────────────────────────────────
   Цвет состояния в тёмной теме СВЕТЛЕЕТ, чтобы читаться текстом на тёмном
   фоне. Тем же цветом заливается кнопка — и белая надпись на светлой заливке
   проваливается по контрасту (эталонное «Отклонить» вышло 2.75:1 при норме
   4.5). Значит у каждого состояния своя пара: `--<state>-fill` — чем залить,
   `--on-<state>` — чем писать НА этой заливке. Пара `--bad-fill`/`--on-bad`
   уже заведена эталоном; здесь достраиваются остальные. Ни одного `#fff`.
   ========================================================================= */

/* ── Каналы цвета элемента ────────────────────────────────────────────────
   Канал объявляется НА самом элементе, а не на общем `.fi-color-*`: иначе
   цвет протекает вниз по дереву и вложенная плашка без цвета красится тоном
   родителя. Сброс — нейтральный, дальше перебивается парой класса. */
.fi-btn,
.fi-icon-btn,
.fi-link,
.fi-badge,
.fi-dropdown-list-item {
  --act-fill:    var(--neutral-fill);
  --act-on-fill: var(--on-neutral);
  --act-tone:    var(--neutral);
  --act-soft:    var(--neutral-soft);
}

.fi-btn.fi-color-primary,
.fi-icon-btn.fi-color-primary,
.fi-link.fi-color-primary,
.fi-badge.fi-color-primary,
.fi-dropdown-list-item.fi-color-primary {
  --act-fill:    var(--primary);
  --act-on-fill: var(--on-primary);
  --act-tone:    var(--primary);
  --act-soft:    var(--primary-soft);
}

.fi-btn.fi-color-danger,
.fi-icon-btn.fi-color-danger,
.fi-link.fi-color-danger,
.fi-badge.fi-color-danger,
.fi-dropdown-list-item.fi-color-danger {
  --act-fill:    var(--bad-fill);
  --act-on-fill: var(--on-bad);
  --act-tone:    var(--bad);
  --act-soft:    var(--bad-soft);
}

.fi-btn.fi-color-success,
.fi-icon-btn.fi-color-success,
.fi-link.fi-color-success,
.fi-badge.fi-color-success,
.fi-dropdown-list-item.fi-color-success {
  --act-fill:    var(--ok-fill);
  --act-on-fill: var(--on-ok);
  --act-tone:    var(--ok);
  --act-soft:    var(--ok-soft);
}

.fi-btn.fi-color-warning,
.fi-icon-btn.fi-color-warning,
.fi-link.fi-color-warning,
.fi-badge.fi-color-warning,
.fi-dropdown-list-item.fi-color-warning {
  --act-fill:    var(--warn-fill);
  --act-on-fill: var(--on-warn);
  --act-tone:    var(--warn);
  --act-soft:    var(--warn-soft);
}

.fi-btn.fi-color-info,
.fi-icon-btn.fi-color-info,
.fi-link.fi-color-info,
.fi-badge.fi-color-info,
.fi-dropdown-list-item.fi-color-info {
  --act-fill:    var(--info-fill);
  --act-on-fill: var(--on-info);
  --act-tone:    var(--info);
  --act-soft:    var(--info-soft);
}

/* Filament отдаёт серому цвету пустой список классов (HasDefaultGrayColor),
   поэтому `.fi-color-gray` на кнопке и плашке почти не встречается. Правило
   стоит на случай явного `Color::Gray` у компонентов без этого договора. */
.fi-btn.fi-color-gray,
.fi-icon-btn.fi-color-gray,
.fi-link.fi-color-gray,
.fi-badge.fi-color-gray,
.fi-dropdown-list-item.fi-color-gray {
  --act-fill:    var(--neutral-fill);
  --act-on-fill: var(--on-neutral);
  --act-tone:    var(--neutral);
  --act-soft:    var(--neutral-soft);
}

/* ══ КНОПКА ═══════════════════════════════════════════════════════════════ */

/* ── Размер ───────────────────────────────────────────────────────────────
   Высота задаётся `min-height`, а не `height`: кнопка у Filament — грид, и
   ей случается переносить длинную подпись. Вертикальные поля сняты, высоту
   держит один токен, ступени считаются от него — тогда характер меняет одно
   число, а не пять. Без `!important`: шаг плотности (`body.bf-density-*`)
   обязан оставаться главнее облика. */
.fi-btn {
  min-height: var(--btn-h);
  padding-block: 0;
  padding-inline: var(--btn-pad-x);
  font-size: var(--btn-font);
  line-height: 1.25;
  gap: 6px;
  transition: background-color .12s ease, color .12s ease,
              box-shadow .12s ease, opacity .12s ease;
}

.fi-btn.fi-size-xs {
  min-height: calc(var(--btn-h) - 8px);
  padding-inline: calc(var(--btn-pad-x) - 5px);
  font-size: var(--font-sm);
  gap: 4px;
}
.fi-btn.fi-size-sm {
  min-height: calc(var(--btn-h) - 4px);
  padding-inline: calc(var(--btn-pad-x) - 3px);
  gap: 5px;
}
.fi-btn.fi-size-md {
  min-height: var(--btn-h);
  padding-inline: var(--btn-pad-x);
}
.fi-btn.fi-size-lg {
  min-height: calc(var(--btn-h) + 4px);
  padding-inline: calc(var(--btn-pad-x) + 3px);
}
.fi-btn.fi-size-xl {
  min-height: calc(var(--btn-h) + 8px);
  padding-inline: calc(var(--btn-pad-x) + 6px);
}

/* ── Обычная кнопка (без цвета) ───────────────────────────────────────────
   Обводка — внутренней тенью, а не рамкой. Filament рисует своё кольцо тем же
   `box-shadow`, и рамка добавила бы кнопке лишний пиксель к размеру: ряд
   кнопок разъехался бы относительно полей ввода. Внутренняя тень заодно
   гарантированно вытесняет кольцо Tailwind. */
.fi-btn:not(.fi-color):not(.fi-outlined) {
  background: var(--surface);
  color: var(--body);
  box-shadow: inset 0 0 0 1px var(--line-strong);
}
.fi-btn:not(.fi-color):not(.fi-outlined):not(.fi-disabled):not([disabled]):hover {
  background: var(--hover);
  color: var(--ink);
}
.fi-btn:not(.fi-color):not(.fi-outlined):not(.fi-disabled):not([disabled]):active {
  background: var(--surface-2);
  box-shadow: inset 0 0 0 1px var(--line-strong);
}
.fi-btn:not(.fi-color) > .fi-icon {
  color: var(--mute);
}
.fi-btn:not(.fi-color):not(.fi-disabled):not([disabled]):hover > .fi-icon {
  color: var(--ink);
}

/* ── Цветная заливка ──────────────────────────────────────────────────────
   Надпись берётся из парного токена заливки. Затемнение при наведении и
   нажатии — подмесом `--ink`: в светлой теме он почти чёрный и цвет
   темнеет, в тёмной почти белый и цвет светлеет. Одно правило работает в
   обеих темах, без развилки на `.dark`.
   Главная кнопка (`fi-color-primary`) в этот блок не входит: её заливку и
   наведение осознанно держит admin-theme (700-я ступень против провала
   контраста), и переопределять их отсюда нельзя. */
.fi-btn.fi-color-danger:not(.fi-outlined),
.fi-btn.fi-color-success:not(.fi-outlined),
.fi-btn.fi-color-warning:not(.fi-outlined),
.fi-btn.fi-color-info:not(.fi-outlined),
.fi-btn.fi-color-gray:not(.fi-outlined) {
  background: var(--act-fill) !important;
  color: var(--act-on-fill) !important;
  box-shadow: none !important;
}
.fi-btn.fi-color-danger:not(.fi-outlined):not(.fi-disabled):not([disabled]):hover,
.fi-btn.fi-color-success:not(.fi-outlined):not(.fi-disabled):not([disabled]):hover,
.fi-btn.fi-color-warning:not(.fi-outlined):not(.fi-disabled):not([disabled]):hover,
.fi-btn.fi-color-info:not(.fi-outlined):not(.fi-disabled):not([disabled]):hover,
.fi-btn.fi-color-gray:not(.fi-outlined):not(.fi-disabled):not([disabled]):hover {
  background: color-mix(in srgb, var(--act-fill) 90%, var(--ink)) !important;
  color: var(--act-on-fill) !important;
}
.fi-btn.fi-color:not(.fi-outlined):not(.fi-disabled):not([disabled]):active {
  background: color-mix(in srgb, var(--act-fill) 80%, var(--ink)) !important;
  transform: none !important;
}
/* Значок внутри залитой кнопки — тем же «текстом на заливке», иначе он
   остаётся серым от Filament и на цветном фоне пропадает. */
.fi-btn.fi-color:not(.fi-outlined) > .fi-icon {
  color: var(--act-on-fill) !important;
}

/* ── Контурная кнопка ─────────────────────────────────────────────────────
   Ни заливки, ни тени: только тонкая обводка тоном и подпись тоном. */
.fi-btn.fi-outlined {
  background: transparent;
  color: var(--ink);
  box-shadow: inset 0 0 0 1px var(--line-strong);
}
.fi-btn.fi-outlined:not(.fi-disabled):not([disabled]):hover {
  background: var(--hover);
}
.fi-btn.fi-outlined:not(.fi-disabled):not([disabled]):active {
  background: var(--surface-2);
}
.fi-btn.fi-outlined.fi-color {
  color: var(--act-tone) !important;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--act-tone) 55%, transparent) !important;
}
.fi-btn.fi-outlined.fi-color:not(.fi-disabled):not([disabled]):hover {
  background: var(--act-soft) !important;
  box-shadow: inset 0 0 0 1px var(--act-tone) !important;
}
.fi-btn.fi-outlined.fi-color:not(.fi-disabled):not([disabled]):active {
  background: color-mix(in srgb, var(--act-soft) 70%, var(--act-tone)) !important;
}
.fi-btn.fi-outlined.fi-color > .fi-icon {
  color: var(--act-tone) !important;
}

/* ── Фокус с клавиатуры ───────────────────────────────────────────────────
   Обводка `outline`, а не кольцо: `box-shadow` у кнопки уже занят обводкой и
   подсветкой главной кнопки, и второе кольцо их бы стёрло. Кольцо Tailwind
   гасится через его же переменную, чтобы рядом не оказалось двух ободков. */
.fi-btn:focus-visible,
.fi-btn-group > .fi-btn:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 1px;
  --tw-ring-shadow: 0 0 0 0 transparent;
  z-index: 1;
}

/* ── Отключённая и «в работе» ─────────────────────────────────────────────
   Отключённая гасится и лишается подсветки: приподнятая тень на неактивной
   кнопке читается как приглашение нажать. «В работе» — курсор ожидания,
   форма не меняется, чтобы строка кнопок не дёргалась. */
.fi-btn.fi-disabled:not(.fi-force-enabled),
.fi-btn[disabled]:not(.fi-force-enabled) {
  opacity: .55;
  cursor: not-allowed;
  box-shadow: inset 0 0 0 1px var(--line) !important;
  transform: none !important;
  filter: saturate(.75);
}
.fi-btn.fi-disabled:not(.fi-force-enabled):not(.fi-color),
.fi-btn[disabled]:not(.fi-force-enabled):not(.fi-color) {
  background: var(--surface-2) !important;
  color: var(--faint) !important;
}
.fi-btn.fi-processing {
  cursor: wait;
  opacity: .7;
  transform: none !important;
}

/* ── Плашка-счётчик на кнопке ─────────────────────────────────────────────
   Подложка у Filament белая наглухо; на тёмном облике это белый прямоугольник
   поверх кнопки. Отдаём её поверхности облика. */
.fi-btn-badge-ctn,
.fi-icon-btn-badge-ctn,
.fi-link-badge-ctn {
  background: var(--surface) !important;
  border-radius: var(--radius-sm) !important;
}

/* Счётчик висит над правым верхним углом кнопки и на плотной панели вылезал
   за её край — на воронке фильтров это заметно, на неё и указывали. Панель
   инструментов ниже стоковой, поэтому вынос считаем от высоты кнопки, а не
   фиксированным числом: подтянется на любом характере. */
/* Счётчик на воронке фильтров показывал «0»: Filament отдаёт в плашку число
   активных фильтров, а `filled(0)` в PHP истинно — красная плашка про пустоту
   висела на каждом реестре. Сколько фильтров включено, и так видно: под
   панелью Filament рисует их перечнем, с крестиком у каждого. Убираем цифру,
   а не двигаем её — двигать бессмысленно, её не должно быть. */
.fi-ta-header-toolbar .fi-icon-btn-badge-ctn {
  display: none !important;
}

/* ── Группа кнопок ────────────────────────────────────────────────────────
   Разделитель у Filament прибит к серой палитре Tailwind — переводим на
   линию облика. Скругление снаружи группы, внутри — стык без зазора. */
.fi-btn-group {
  border-radius: var(--radius);
  box-shadow: inset 0 0 0 1px var(--line-strong);
}
.fi-btn-group > .fi-btn:first-child {
  border-start-start-radius: var(--radius) !important;
  border-end-start-radius: var(--radius) !important;
}
.fi-btn-group > .fi-btn:last-child {
  border-start-end-radius: var(--radius) !important;
  border-end-end-radius: var(--radius) !important;
}
.fi-btn-group > .fi-btn + .fi-btn {
  box-shadow: inset 1px 0 0 0 var(--line) !important;
}
.fi-btn-group > .fi-btn.fi-processing {
  cursor: wait;
  opacity: .7;
}

/* ══ КНОПКА-ЗНАЧОК ════════════════════════════════════════════════════════
   Размер отдан токену, но след в потоке сохранён: Filament держит значок на
   отрицательном поле `-8px` при коробке 36px, то есть в раскладке кнопка
   занимает 20px. Поле пересчитывается от размера, чтобы соседние элементы
   не поехали, когда облик сожмёт коробку. */
.fi-icon-btn {
  --icon-btn-size: var(--icon-btn-size-md);
  width: var(--icon-btn-size) !important;
  height: var(--icon-btn-size) !important;
  margin: calc((20px - var(--icon-btn-size)) / 2) !important;
  color: var(--mute);
  transition: background-color .12s ease, color .12s ease;
}
.fi-icon-btn.fi-size-xs { --icon-btn-size: calc(var(--icon-btn-size-md) - 8px); }
.fi-icon-btn.fi-size-sm { --icon-btn-size: calc(var(--icon-btn-size-md) - 4px); }
.fi-icon-btn.fi-size-md { --icon-btn-size: var(--icon-btn-size-md); }
.fi-icon-btn.fi-size-lg { --icon-btn-size: calc(var(--icon-btn-size-md) + 4px); }
.fi-icon-btn.fi-size-xl { --icon-btn-size: calc(var(--icon-btn-size-md) + 8px); }

.fi-icon-btn:not(.fi-disabled):not([disabled]):hover {
  background: var(--hover);
  color: var(--ink);
}
.fi-icon-btn:not(.fi-disabled):not([disabled]):active {
  background: var(--surface-2);
}
.fi-icon-btn.fi-color {
  color: var(--act-tone) !important;
}
.fi-icon-btn.fi-color:not(.fi-disabled):not([disabled]):hover {
  background: var(--act-soft) !important;
  color: var(--act-tone) !important;
}
.fi-icon-btn.fi-color:not(.fi-disabled):not([disabled]):active {
  background: color-mix(in srgb, var(--act-soft) 70%, var(--act-tone)) !important;
}
.fi-icon-btn:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 1px;
  --tw-ring-shadow: 0 0 0 0 transparent;
}
.fi-icon-btn.fi-disabled:not(.fi-force-enabled),
.fi-icon-btn[disabled]:not(.fi-force-enabled) {
  opacity: .5;
  cursor: not-allowed;
  background: transparent !important;
  color: var(--faint) !important;
}

/* ══ ССЫЛКА-ДЕЙСТВИЕ ══════════════════════════════════════════════════════
   Подчёркивание Filament ставит сам; здесь только цвет, размер и состояния.
   Действие-ссылкой по умолчанию идёт акцентом: это единственный вид действия,
   который стоит внутри текста и обязан читаться как ссылка. */
.fi-link {
  color: var(--body);
  font-size: var(--font-base);
  transition: color .12s ease;
}
.fi-link.fi-size-xs { font-size: var(--font-sm); }
.fi-link.fi-size-sm { font-size: var(--font-sm); }
.fi-link.fi-size-md,
.fi-link.fi-size-lg,
.fi-link.fi-size-xl { font-size: var(--font-base); }

.fi-ac-link-action:not(.fi-color) {
  color: var(--primary);
}
.fi-link.fi-color {
  color: var(--act-tone) !important;
}
.fi-link:not(.fi-color):not(.fi-disabled):not([disabled]):hover {
  color: var(--primary-hover);
}
.fi-link:not(.fi-color):not(.fi-disabled):not([disabled]):active {
  color: color-mix(in srgb, var(--primary-hover) 80%, var(--ink));
}
.fi-link.fi-color:not(.fi-disabled):not([disabled]):hover {
  color: color-mix(in srgb, var(--act-tone) 80%, var(--ink)) !important;
}
.fi-link.fi-color:not(.fi-disabled):not([disabled]):active {
  color: color-mix(in srgb, var(--act-tone) 70%, var(--ink)) !important;
}
.fi-link:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}
.fi-link:not(.fi-color) > .fi-icon {
  color: var(--mute);
}
.fi-link.fi-color > .fi-icon {
  color: var(--act-tone) !important;
}
.fi-link.fi-disabled:not(.fi-force-enabled),
.fi-link[disabled]:not(.fi-force-enabled) {
  opacity: .55;
  cursor: not-allowed;
  color: var(--faint) !important;
  text-decoration: none !important;
}

/* ══ ГРУППА ДЕЙСТВИЙ ══════════════════════════════════════════════════════
   Зазор 12px у Filament ставит действия шапки вразрядку и съедает ширину
   строки. Учётный шаг — один токен на всю панель действий. */
.fi-ac {
  gap: var(--act-gap);
}
.fi-ac.fi-width-full {
  gap: var(--act-gap);
}
/* Кнопка-«ещё», раскрывающая свёрнутую группу. Она же .fi-icon-btn, поэтому
   здесь только то, чего не даёт общий значок: собственная поверхность, чтобы
   след группы был виден среди отдельных действий строки. */
.fi-ac-icon-btn-group:not(.fi-disabled):not([disabled]):hover {
  background: var(--hover) !important;
}
.fi-ac-btn-group {
  gap: 6px;
}

/* ══ ДЕЙСТВИЕ В МЕНЮ ══════════════════════════════════════════════════════ */
.fi-dropdown-list {
  padding: 4px;
  gap: 1px;
}
.fi-dropdown-list-item {
  border-radius: var(--radius-sm);
  padding: 5px 8px;
  font-size: var(--font-base);
  color: var(--body);
  gap: 8px;
  transition: background-color .1s ease, color .1s ease;
}
.fi-dropdown-list-item-label {
  color: var(--body);
  font-size: var(--font-base);
}
.fi-dropdown-list-item:not(.fi-disabled):not([disabled]):hover,
.fi-dropdown-list-item:not(.fi-disabled):not([disabled]):focus-visible,
.fi-dropdown-list-item:not(.fi-disabled):not([disabled]).fi-selected {
  background: var(--hover);
  color: var(--ink);
}
.fi-dropdown-list-item:not(.fi-disabled):not([disabled]):hover .fi-dropdown-list-item-label,
.fi-dropdown-list-item:not(.fi-disabled):not([disabled]):focus-visible .fi-dropdown-list-item-label {
  color: var(--ink);
}
.fi-dropdown-list-item:not(.fi-disabled):not([disabled]):active {
  background: var(--selected);
}
.fi-dropdown-list-item:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: -2px;
}
/* Цветной пункт — обычно «Удалить». Слово красится тоном сразу, подложка
   появляется только под указателем: список из шести пунктов, где один горит
   красным фоном, читается как ошибка, а не как выбор. */
.fi-dropdown-list-item.fi-color .fi-dropdown-list-item-label {
  color: var(--act-tone) !important;
}
.fi-dropdown-list-item.fi-color > .fi-icon {
  color: var(--act-tone) !important;
}
.fi-dropdown-list-item.fi-color:not(.fi-disabled):not([disabled]):hover,
.fi-dropdown-list-item.fi-color:not(.fi-disabled):not([disabled]):focus-visible,
.fi-dropdown-list-item.fi-color:not(.fi-disabled):not([disabled]).fi-selected {
  background: var(--act-soft) !important;
}
.fi-dropdown-list-item.fi-color:not(.fi-disabled):not([disabled]):hover .fi-dropdown-list-item-label,
.fi-dropdown-list-item.fi-color:not(.fi-disabled):not([disabled]):focus-visible .fi-dropdown-list-item-label {
  color: var(--act-tone) !important;
}
.fi-dropdown-list-item.fi-disabled,
.fi-dropdown-list-item[disabled] {
  opacity: .5;
  cursor: not-allowed;
  background: transparent !important;
}
.fi-dropdown-list-item.fi-disabled .fi-dropdown-list-item-label,
.fi-dropdown-list-item[disabled] .fi-dropdown-list-item-label {
  color: var(--faint) !important;
}
.fi-dropdown-list-item-badge-placeholder {
  color: var(--faint);
}
.fi-dropdown-header {
  color: var(--mute);
  font-size: var(--font-sm);
}

/* ══ ПЛАШКА ═══════════════════════════════════════════════════════════════

   Ось характера. Плашка — самый узнаваемый признак эпохи интерфейса, и
   разные облики решают её по-разному. Три решения переключаются тремя
   значениями, правила при этом одни и те же:

     сплошная заливка   --badge-bg не задан · --badge-border: transparent · --badge-dot: 0
     точка со словом    --badge-bg: transparent · --badge-border: transparent · --badge-dot: 6px
     контур             --badge-bg: transparent · --badge-border: currentColor · --badge-dot: 0

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

   Проверено на живой админке: точка, обводка и скругление переключаются
   везде, заливка — везде, КРОМЕ ячейки реестра. Там заливку держит
   admin-theme (`.fi-ta-cell .fi-badge` и её вариант для отказа) — своим
   `!important` и более сильной выборкой. Это осознанное правило «тихого
   реестра», и снаружи его не перебить: если ось заливки понадобится и в
   таблице, ту пару строк надо перевести на `var(--badge-bg, …)` там же. */
.fi-badge {
  background: var(--badge-bg, var(--act-soft)) !important;
  color: var(--act-tone) !important;
  box-shadow: inset 0 0 0 1px var(--badge-border, transparent) !important;
  border-radius: var(--badge-radius) !important;
  padding-block: 1px;
  padding-inline: var(--badge-pad-x);
  font-size: var(--badge-font);
  gap: 5px;
  min-width: 0;
}
/* Точка ведёт тот же тон, что и слово. `content` пустой — это форма, а не
   текст: содержимого в псевдоэлементе быть не должно. */
.fi-badge::before {
  content: '';
  flex: none;
  width: var(--badge-dot, 0);
  height: var(--badge-dot, 0);
  border-radius: 50%;
  background: var(--act-tone);
}
/* Мост к реестру. admin-theme задаёт точку в ячейке жёстко (6px) и своей,
   более сильной выборкой — без этого правила ось характера работала бы
   везде, кроме таблицы, то есть там, где плашек больше всего. */
.fi-ta-cell .fi-badge::before {
  width: var(--badge-dot, 0) !important;
  height: var(--badge-dot, 0) !important;
  background: var(--act-tone) !important;
}
.fi-badge-label-ctn {
  min-width: 0;
}
.fi-badge-label {
  color: inherit;
  font-weight: inherit;
}
.fi-badge > .fi-icon {
  color: var(--act-tone) !important;
}

.fi-badge.fi-size-xs {
  padding-block: 0;
  padding-inline: calc(var(--badge-pad-x) - 4px);
  font-size: calc(var(--badge-font) - 1px);
  gap: 4px;
}
.fi-badge.fi-size-sm {
  padding-block: 0;
  padding-inline: calc(var(--badge-pad-x) - 2px);
  font-size: var(--badge-font);
  gap: 4px;
}
.fi-badge.fi-size-lg,
.fi-badge.fi-size-xl {
  padding-block: 2px;
  padding-inline: calc(var(--badge-pad-x) + 2px);
  font-size: var(--font-base);
}

/* Крестик снятия. Обычно — приглушённый, чтобы не спорить со словом; под
   указателем становится цветом отказа, потому что это и есть отказ. */
.fi-badge-delete-btn {
  color: var(--faint) !important;
  border-radius: var(--radius-sm);
  transition: color .12s ease, background-color .12s ease;
}
.fi-badge-delete-btn > .fi-icon {
  color: var(--faint) !important;
}
.fi-badge:not(.fi-disabled):not([disabled]) .fi-badge-delete-btn:hover > .fi-icon,
.fi-badge:not(.fi-disabled):not([disabled]) .fi-badge-delete-btn:focus-visible > .fi-icon {
  color: var(--bad) !important;
}
.fi-badge-delete-btn:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: -1px;
}
.fi-badge.fi-disabled:not(.fi-force-enabled),
.fi-badge[disabled]:not(.fi-force-enabled) {
  opacity: .55;
  cursor: not-allowed;
  filter: saturate(.6);
}

/* ============================================================================
   НОВЫЕ ТОКЕНЫ — значения свести в :root словаря, здесь их намеренно нет.

   ── Пары «заливка / текст на заливке» ──────────────────────────────────────
   Достраивают ось, которую эталон завёл только для отказа (--bad-fill/--on-bad).
   В тёмной теме «текст на заливке» ОБЯЗАН стать тёмным — иначе белая надпись
   на посветлевшей заливке проваливается по контрасту.

   --bad-fill      чем залить кнопку отказа          светлая var(--bad)  тёмная var(--bad)
                   (есть у эталона, но в admin-theme.css ещё НЕ объявлен)
   --ok-fill       чем залить кнопку успеха          светлая var(--ok)   тёмная var(--ok)
   --warn-fill     чем залить кнопку предупреждения  светлая var(--warn) тёмная var(--warn)
   --info-fill     чем залить кнопку сведений        светлая var(--info) тёмная var(--info)
   --neutral-fill  чем залить нейтральную заливку    светлая var(--neutral) тёмная var(--neutral)
   --on-neutral    надпись на нейтральной заливке    светлая var(--surface)
                                                     тёмная  var(--skin-bg)
   (--on-ok / --on-warn / --on-info / --on-bad уже есть в словаре.)

   ── Кнопка ────────────────────────────────────────────────────────────────
   --btn-h         высота средней кнопки             светлая 28px   тёмная 28px
   --btn-pad-x     боковое поле средней кнопки       светлая 12px   тёмная 12px
   --btn-font      кегль подписи кнопки              светлая 12.5px тёмная 12.5px

   ── Кнопка-значок ─────────────────────────────────────────────────────────
   --icon-btn-size-md  коробка значка среднего размера   светлая 30px тёмная 30px
   (--icon-btn-size — внутренний канал ступени, значение в :root не нужно.)

   ── Панель действий ───────────────────────────────────────────────────────
   --act-gap       зазор между действиями в строке   светлая 8px    тёмная 8px

   ── Плашка (ось характера) ────────────────────────────────────────────────
   --badge-bg      заливка плашки; не задан — мягкая заливка тоном,
                   `transparent` — плашка без заливки
                   светлая не задан   тёмная не задан
   --badge-border  цвет обводки плашки; `currentColor` даёт контурный характер
                   светлая transparent тёмная transparent
   --badge-dot     диаметр точки состояния; `0` — без точки
                   светлая 6px        тёмная 6px
   --badge-radius  скругление плашки; `999px` даёт пилюлю
                   светлая var(--radius-sm) тёмная var(--radius-sm)
   --badge-pad-x   боковое поле плашки               светлая 8px    тёмная 8px
   --badge-font    кегль подписи плашки              светлая var(--font-sm) тёмная var(--font-sm)

   ── Внутренние каналы (значения в :root НЕ нужны) ─────────────────────────
   --act-fill --act-on-fill --act-tone --act-soft
   Объявляются на самом элементе правилами выше и переключаются классом
   цвета Filament. В словарь не выносить: канал, а не настройка облика.
   ========================================================================= */


/* ── часть: feedback.css ─────────────────────── */
/* ============================================================================
   ОБРАТНАЯ СВЯЗЬ — всё, чем панель отвечает человеку:
   модальное окно, уведомление, выноска, загрузка, пустое состояние.

   До этого файла все пять рендерились стоковым Filament: белое окно с
   `rounded-xl`, тень `shadow-xl`, затемнение `bg-gray-950/50`, текст 16px/14px.
   То есть ровно те места, где облик обрывался — а видно их чаще прочего:
   любое подтверждение, любое сохранение проходит через них.

   Метрики сняты с эталона «Характер 01 — учётный плотный», экран «Инвентарь»:
   окно — рамка `--line` + радиус `--radius-lg` + тень `--shadow`, шапка и
   подвал по 10px, подвал залит `--surface-2`; уведомление — 360px шириной,
   отступ 9/11, слева полоса 3px цветом состояния, заголовок `--font-base`,
   подпись `--font-sm` цветом `--mute`.

   Все правила ниже — с `!important`: стоковые селекторы Filament идут в четыре
   класса (`.fi-modal > .fi-modal-window-ctn > .fi-modal-window .fi-modal-header`),
   короткой записью их не перебить.
   ============================================================================ */

/* ── Модальное окно · затемнение фона ───────────────────────────────────────
   Ловушка, ради которой затемнение вынесено отдельным блоком: чернила брать
   у `--ink` можно ТОЛЬКО в светлой теме. В тёмной `--ink` почти белый (текст
   на тёмном фоне) — и `color-mix` дал бы молочную вуаль вместо затемнения.
   Поэтому в тёмной теме чернила берутся у холста `--skin-bg`, он там чёрный.
   Оба варианта пропускают через себя необязательный `--overlay-ink`, если
   облик захочет назначить затемнению собственный цвет.
   ────────────────────────────────────────────────────────────────────────── */
.fi-modal > .fi-modal-close-overlay {
  background-color: color-mix(in srgb, var(--overlay-ink, var(--ink)) 45%, transparent) !important;
}
.dark .fi-modal > .fi-modal-close-overlay {
  background-color: color-mix(in srgb, var(--overlay-ink, var(--skin-bg)) 72%, transparent) !important;
}

/* ── Модальное окно · само окно ────────────────────────────────────────── */
.fi-modal .fi-modal-window {
  background: var(--surface) !important;
  border: 1px solid var(--line) !important;
  border-radius: var(--radius-lg) !important;
  box-shadow: var(--shadow) !important;
  color: var(--body);
  font-size: var(--font-base);
}
/* Экранный режим и шторка идут вплотную к краю окна браузера — скруглять и
   обводить со всех сторон нечего. */
.fi-modal .fi-modal-window.fi-width-screen {
  border: 0 !important;
  border-radius: 0 !important;
}

/* ── Модальное окно · ширины ────────────────────────────────────────────────
   Селекторы обязаны быть привязаны к окну: `fi-width-*` носят ещё выпадающие
   меню и контейнер таблицы, и голое `.fi-width-md` перекроило бы заодно их.
   Шкала поджата против стоковой (эталон держит подтверждение в 460px). */
.fi-modal .fi-modal-window.fi-width-xs  { max-width: 300px !important; }
.fi-modal .fi-modal-window.fi-width-sm  { max-width: 360px !important; }
.fi-modal .fi-modal-window.fi-width-md  { max-width: 440px !important; }
.fi-modal .fi-modal-window.fi-width-lg  { max-width: 520px !important; }
.fi-modal .fi-modal-window.fi-width-xl  { max-width: 600px !important; }
.fi-modal .fi-modal-window.fi-width-2xl { max-width: 680px !important; }
.fi-modal .fi-modal-window.fi-width-3xl { max-width: 780px !important; }
.fi-modal .fi-modal-window.fi-width-4xl { max-width: 880px !important; }
.fi-modal .fi-modal-window.fi-width-5xl { max-width: 980px !important; }
.fi-modal .fi-modal-window.fi-width-6xl { max-width: 1080px !important; }
.fi-modal .fi-modal-window.fi-width-7xl { max-width: 1180px !important; }

/* ── Модальное окно · шапка ────────────────────────────────────────────── */
.fi-modal .fi-modal-header {
  display: flex;
  gap: 10px;
  padding: 10px var(--pad) !important;
  border-bottom: 1px solid var(--line) !important;
  background: var(--surface) !important;
  border-top-left-radius: var(--radius-lg);
  border-top-right-radius: var(--radius-lg);
}
/* Окно-подтверждение (значок, заголовок, кнопки — без содержимого посередине)
   собирает две линии подряд: низ шапки и верх подвала легли бы вплотную и
   дали двойную черту. Верхнюю снимаем — подвал сам себя отбивает. */
.fi-modal .fi-modal-window:not(.fi-modal-window-has-content) .fi-modal-header {
  border-bottom-color: transparent !important;
}
.fi-modal .fi-modal-heading {
  font-size: var(--font-base) !important;
  font-weight: 600 !important;
  line-height: 1.35 !important;
  color: var(--ink) !important;
}
.fi-modal .fi-modal-description {
  margin-top: 2px !important;
  font-size: var(--font-sm) !important;
  line-height: 1.45 !important;
  color: var(--mute) !important;
}

/* ── Модальное окно · значок состояния ─────────────────────────────────── */
.fi-modal .fi-modal-window-has-icon .fi-modal-header { gap: 10px; }
.fi-modal .fi-modal-icon-ctn { margin-bottom: 0 !important; }
.fi-modal .fi-modal-window.fi-align-center .fi-modal-icon-ctn { margin-bottom: 10px !important; }
.fi-modal .fi-modal-icon-bg {
  padding: 7px !important;
  border-radius: var(--radius) !important;
  background: var(--neutral-soft) !important;
}
.fi-modal .fi-modal-icon-bg > .fi-icon { color: var(--neutral) !important; }
.fi-modal .fi-modal-icon-bg.fi-color-danger  { background: var(--bad-soft) !important; }
.fi-modal .fi-modal-icon-bg.fi-color-danger  > .fi-icon { color: var(--bad) !important; }
.fi-modal .fi-modal-icon-bg.fi-color-warning { background: var(--warn-soft) !important; }
.fi-modal .fi-modal-icon-bg.fi-color-warning > .fi-icon { color: var(--warn) !important; }
.fi-modal .fi-modal-icon-bg.fi-color-success { background: var(--ok-soft) !important; }
.fi-modal .fi-modal-icon-bg.fi-color-success > .fi-icon { color: var(--ok) !important; }
.fi-modal .fi-modal-icon-bg.fi-color-info    { background: var(--info-soft) !important; }
.fi-modal .fi-modal-icon-bg.fi-color-info    > .fi-icon { color: var(--info) !important; }
.fi-modal .fi-modal-icon-bg.fi-color-primary { background: var(--primary-soft) !important; }
.fi-modal .fi-modal-icon-bg.fi-color-primary > .fi-icon { color: var(--primary) !important; }

/* ── Модальное окно · содержимое ───────────────────────────────────────── */
.fi-modal .fi-modal-content {
  padding: var(--pad) !important;
  gap: 10px !important;
  font-size: var(--font-base);
  color: var(--body);
}
/* Выравнивание «под заголовок»: при значке слева Filament уводит текст на его
   ширину (значок 24px + два по 7 + промежуток 10). Отступ сохранён, но пересчитан
   под наши размеры — иначе абзац поехал бы к левому краю значка. */
.fi-modal.fi-align-start > .fi-modal-window-ctn > .fi-modal-window-has-icon .fi-modal-content,
.fi-modal.fi-align-start > .fi-modal-window-ctn > .fi-modal-window-has-icon .fi-modal-footer:not(.fi-align-center) {
  padding-inline-start: calc(var(--pad) + 48px) !important;
}

/* ── Модальное окно · подвал ───────────────────────────────────────────── */
.fi-modal .fi-modal-footer {
  margin-top: 0 !important;
  padding: 10px var(--pad) !important;
  border-top: 1px solid var(--line) !important;
  background: var(--surface-2) !important;
  border-bottom-left-radius: calc(var(--radius-lg) - 1px);
  border-bottom-right-radius: calc(var(--radius-lg) - 1px);
}
/* Кнопки подвала — компактной строкой у правого края, как в эталоне: взгляд
   идёт по строке и упирается в главное действие последним. Стоковая раскладка
   для окон по центру растягивает их сеткой во всю ширину (`grid-cols-auto-fit`),
   и в плотной панели пара кнопок выходит по 200px каждая. */
.fi-modal .fi-modal-footer-actions {
  display: flex !important;
  flex-direction: row !important;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end !important;
  gap: 8px !important;
}

/* ── Модальное окно · кнопка закрытия ──────────────────────────────────── */
.fi-modal .fi-modal-close-btn {
  inset-inline-end: 9px !important;
  top: 9px !important;
  width: 22px !important;
  height: 22px !important;
  padding: 0 !important;
  display: grid;
  place-items: center;
  background: transparent !important;
  border: 0 !important;
  border-radius: var(--radius-sm) !important;
  box-shadow: none !important;
  color: var(--mute) !important;
  transition: color .12s, background .12s;
}
.fi-modal .fi-modal-close-btn:hover {
  background: var(--hover) !important;
  color: var(--ink) !important;
}
.fi-modal .fi-modal-close-btn .fi-icon { width: 13px !important; height: 13px !important; }
/* Заголовок не должен заезжать под крестик: 9 отступа + 22 кнопки = 31. */
.fi-modal .fi-modal-window-has-close-btn .fi-modal-heading { margin-inline-end: 32px !important; }
.fi-modal .fi-modal-window-has-close-btn.fi-align-center:not(.fi-modal-window-has-icon) .fi-modal-heading {
  margin-inline-start: 32px !important;
}

/* ── Модальное окно · липкие шапка и подвал ────────────────────────────── */
.fi-modal.fi-modal-has-sticky-header > .fi-modal-window-ctn > .fi-modal-window > .fi-modal-header {
  border-bottom: 1px solid var(--line) !important;
  background: var(--surface) !important;
  padding-bottom: 10px !important;
}
.fi-modal.fi-modal-has-sticky-footer > .fi-modal-window-ctn > .fi-modal-window > .fi-modal-footer {
  border-top: 1px solid var(--line) !important;
  background: var(--surface-2) !important;
  padding-block: 10px !important;
}

/* ── Модальное окно · шторка ───────────────────────────────────────────────
   Шторка прижата к правому краю на всю высоту: скруглять её незачем, а
   отделяет её от страницы одна линия слева плюс общая тень. */
.fi-modal.fi-modal-slide-over > .fi-modal-window-ctn > .fi-modal-window {
  border: 0 !important;
  border-inline-start: 1px solid var(--line) !important;
  border-radius: 0 !important;
  box-shadow: var(--shadow) !important;
}
.fi-modal.fi-modal-slide-over .fi-modal-close-btn {
  inset-inline-end: var(--pad) !important;
  top: 10px !important;
}
.fi-modal.fi-modal-slide-over .fi-modal-header { gap: 10px !important; }
.fi-modal.fi-modal-slide-over .fi-modal-icon-bg { margin: 0 !important; padding: 7px !important; }
.fi-modal.fi-modal-slide-over > .fi-modal-window-ctn > .fi-modal-window > .fi-modal-footer {
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
}

/* ── Уведомление · раскладка стопки ────────────────────────────────────── */
.fi-no {
  inset: 12px !important;
  gap: 8px !important;
}

/* ── Уведомление · карточка ────────────────────────────────────────────────
   Эталон не красит уведомление целиком: подложка остаётся `--surface`, а
   состояние держит полоса слева и цвет значка. Тонированный фон (стоковое
   поведение `.fi-color`) на плотной сетке спорит с карточкой таблицы под ним.

   Селекторы НЕ привязаны к `.fi-no` намеренно: та же карточка с `fi-inline`
   живёт в списке колокольчика (`.fi-no-database`), а он лежит в модалке, не в
   стопке. Привязка к стопке оставила бы половину уведомлений стоковыми.
   ────────────────────────────────────────────────────────────────────────── */
.fi-no-notification {
  gap: 9px !important;
  padding: 9px 11px !important;
  background: var(--surface) !important;
  font-size: var(--font-base);
}
/* Всплывающая карточка: своя рамка, тень и предел ширины. */
.fi-no-notification:not(.fi-inline) {
  max-width: 360px !important;
  border: 1px solid var(--line) !important;
  border-inline-start: 3px solid var(--neutral) !important;
  border-radius: var(--radius) !important;
  box-shadow: var(--shadow) !important;
}
/* Встроенная строка списка: ни рамки, ни тени — их держит список. Полосу
   состояния тоже снимаем: у непрочитанных Filament рисует свою у самого края
   (`fi-no-notification-unread-ctn::before`), и две рядом читались бы браком. */
.fi-no-notification.fi-inline {
  max-width: none !important;
  border: 0 !important;
  border-radius: 0 !important;
  box-shadow: none !important;
  background: transparent !important;
}
.fi-no-notification-icon { color: var(--neutral) !important; margin-top: 1px; flex: none; }
.fi-no-notification-main { margin-top: 0 !important; gap: 6px !important; }
.fi-no-notification-text { gap: 2px !important; }
.fi-no-notification-title {
  font-size: var(--font-base) !important;
  font-weight: 600 !important;
  line-height: 1.35 !important;
  color: var(--ink) !important;
}
.fi-no-notification-body {
  font-size: var(--font-sm) !important;
  line-height: 1.45 !important;
  color: var(--mute) !important;
}
.fi-no-notification-date {
  font-size: var(--font-sm) !important;
  color: var(--faint) !important;
}
.fi-no-notification-actions { gap: 8px !important; margin-top: 1px; }

/* ── Уведомление · четыре состояния ────────────────────────────────────── */
.fi-no-notification.fi-status-success:not(.fi-inline) { border-inline-start-color: var(--ok) !important; }
.fi-no-notification.fi-status-success .fi-no-notification-icon { color: var(--ok) !important; }
.fi-no-notification.fi-status-warning:not(.fi-inline) { border-inline-start-color: var(--warn) !important; }
.fi-no-notification.fi-status-warning .fi-no-notification-icon { color: var(--warn) !important; }
.fi-no-notification.fi-status-danger:not(.fi-inline)  { border-inline-start-color: var(--bad) !important; }
.fi-no-notification.fi-status-danger .fi-no-notification-icon { color: var(--bad) !important; }
.fi-no-notification.fi-status-info:not(.fi-inline)    { border-inline-start-color: var(--info) !important; }
.fi-no-notification.fi-status-info .fi-no-notification-icon { color: var(--info) !important; }

/* ── Уведомление · список колокольчика ─────────────────────────────────────
   Список бьётся в край модалки отрицательными полями, посчитанными от стокового
   отступа содержимого (`-mx-6` = −24px). Отступ у нас теперь `--pad`, и старое
   число вынесло бы строки за рамку окна. Пересчитываем от токена.
   ────────────────────────────────────────────────────────────────────────── */
.fi-no-database .fi-modal-window .fi-modal-content {
  margin-inline: calc(var(--pad) * -1) !important;
  margin-top: calc(var(--pad) * -1) !important;
  gap: 0 !important;
}
.fi-no-database .fi-modal-window:not(.fi-modal-window-has-footer) .fi-modal-content {
  margin-bottom: calc(var(--pad) * -1) !important;
}
.fi-no-database .fi-modal-content > * + * { border-top: 1px solid var(--line-soft) !important; }
.fi-no-database .fi-no-notification-read-ctn .fi-no-notification-title { font-weight: 500 !important; }

/* ── Уведомление · кнопка закрытия ─────────────────────────────────────── */
.fi-no-notification-close-btn {
  width: 18px !important;
  height: 18px !important;
  padding: 0 !important;
  display: grid;
  place-items: center;
  flex: none;
  background: transparent !important;
  border: 0 !important;
  border-radius: var(--radius-sm) !important;
  box-shadow: none !important;
  color: var(--faint) !important;
  transition: color .12s, background .12s;
}
.fi-no-notification-close-btn:hover {
  background: var(--hover) !important;
  color: var(--ink) !important;
}
.fi-no-notification-close-btn .fi-icon { width: 11px !important; height: 11px !important; }

/* ── Выноска ───────────────────────────────────────────────────────────────
   Эталон рисует её тонированной плашкой цвета состояния (в модалке —
   предупреждение о превышении лимита): заливка `*-soft`, текст самим цветом.
   ────────────────────────────────────────────────────────────────────────── */
.fi-callout {
  gap: 9px !important;
  padding: 8px 10px !important;
  background: var(--neutral-soft) !important;
  border: 1px solid var(--line) !important;
  border-radius: var(--radius) !important;
  box-shadow: none !important;
  font-size: var(--font-sm) !important;
}
.fi-callout .fi-callout-icon { color: var(--neutral) !important; margin-top: 1px; flex: none; }
.fi-callout .fi-callout-main { margin-top: 0 !important; gap: 6px !important; }
.fi-callout .fi-callout-text { gap: 2px !important; }
.fi-callout .fi-callout-heading {
  font-size: var(--font-base) !important;
  font-weight: 600 !important;
  line-height: 1.35 !important;
  color: var(--ink) !important;
}
.fi-callout .fi-callout-description {
  font-size: var(--font-sm) !important;
  line-height: 1.45 !important;
  color: var(--body) !important;
}
.fi-callout .fi-callout-footer { gap: 8px !important; }

.fi-callout.fi-color-danger {
  background: var(--bad-soft) !important;
  border-color: color-mix(in srgb, var(--bad) 26%, transparent) !important;
}
.fi-callout.fi-color-danger .fi-callout-icon,
.fi-callout.fi-color-danger .fi-callout-heading { color: var(--bad) !important; }

.fi-callout.fi-color-warning {
  background: var(--warn-soft) !important;
  border-color: color-mix(in srgb, var(--warn) 26%, transparent) !important;
}
.fi-callout.fi-color-warning .fi-callout-icon,
.fi-callout.fi-color-warning .fi-callout-heading { color: var(--warn) !important; }

.fi-callout.fi-color-success {
  background: var(--ok-soft) !important;
  border-color: color-mix(in srgb, var(--ok) 26%, transparent) !important;
}
.fi-callout.fi-color-success .fi-callout-icon,
.fi-callout.fi-color-success .fi-callout-heading { color: var(--ok) !important; }

.fi-callout.fi-color-info {
  background: var(--info-soft) !important;
  border-color: color-mix(in srgb, var(--info) 26%, transparent) !important;
}
.fi-callout.fi-color-info .fi-callout-icon,
.fi-callout.fi-color-info .fi-callout-heading { color: var(--info) !important; }

.fi-callout.fi-color-primary {
  background: var(--primary-soft) !important;
  border-color: color-mix(in srgb, var(--primary) 26%, transparent) !important;
}
.fi-callout.fi-color-primary .fi-callout-icon,
.fi-callout.fi-color-primary .fi-callout-heading { color: var(--primary) !important; }

/* ── Индикатор загрузки ────────────────────────────────────────────────────
   Цвет НЕ задаём намеренно: индикатор живёт внутри кнопок и полей и обязан
   наследовать их текст, иначе на фирменной заливке он станет серым пятном.
   ────────────────────────────────────────────────────────────────────────── */
@keyframes bf-spin { to { transform: rotate(360deg); } }
.fi-loading-indicator {
  animation: bf-spin .7s linear infinite !important;
  transform-origin: 50% 50%;
}

/* ── Скелет раздела ────────────────────────────────────────────────────────
   Заглушка на месте будущего раздела: форма уже занята, содержимого ещё нет.
   Блик проходит по плашке слева направо — «идёт», а не «сломалось».
   ────────────────────────────────────────────────────────────────────────── */
@keyframes bf-skeleton { from { background-position: 200% 0; } to { background-position: -200% 0; } }
.fi-loading-section {
  background-color: var(--surface-2) !important;
  background-image: linear-gradient(
    90deg,
    transparent 0%,
    color-mix(in srgb, var(--ink) 6%, transparent) 50%,
    transparent 100%
  ) !important;
  background-size: 200% 100%;
  background-repeat: no-repeat;
  border: 1px solid var(--line-soft) !important;
  border-radius: var(--radius) !important;
  box-shadow: none !important;
  animation: bf-skeleton 1.5s linear infinite !important;
  opacity: 1 !important;
}

/* ── Пустое состояние ──────────────────────────────────────────────────── */
.fi-empty-state {
  padding: 28px var(--pad) !important;
  font-size: var(--font-base);
}
.fi-empty-state:not(.fi-empty-state-not-contained) {
  background: var(--surface) !important;
  border: 1px solid var(--line) !important;
  border-radius: var(--radius) !important;
  box-shadow: var(--shadow-sm) !important;
}
.fi-empty-state .fi-empty-state-icon-bg {
  margin-bottom: 10px !important;
  padding: 9px !important;
  border-radius: var(--radius) !important;
  background: var(--neutral-soft) !important;
}
.fi-empty-state .fi-empty-state-icon-bg .fi-icon { color: var(--neutral) !important; }
.fi-empty-state .fi-empty-state-icon-bg.fi-color-danger  { background: var(--bad-soft) !important; }
.fi-empty-state .fi-empty-state-icon-bg.fi-color-danger .fi-icon { color: var(--bad) !important; }
.fi-empty-state .fi-empty-state-icon-bg.fi-color-warning { background: var(--warn-soft) !important; }
.fi-empty-state .fi-empty-state-icon-bg.fi-color-warning .fi-icon { color: var(--warn) !important; }
.fi-empty-state .fi-empty-state-icon-bg.fi-color-success { background: var(--ok-soft) !important; }
.fi-empty-state .fi-empty-state-icon-bg.fi-color-success .fi-icon { color: var(--ok) !important; }
.fi-empty-state .fi-empty-state-icon-bg.fi-color-info    { background: var(--info-soft) !important; }
.fi-empty-state .fi-empty-state-icon-bg.fi-color-info .fi-icon { color: var(--info) !important; }
.fi-empty-state .fi-empty-state-icon-bg.fi-color-primary { background: var(--primary-soft) !important; }
.fi-empty-state .fi-empty-state-icon-bg.fi-color-primary .fi-icon { color: var(--primary) !important; }
.fi-empty-state .fi-empty-state-heading {
  font-size: calc(var(--font-base) + 1px) !important;
  font-weight: 600 !important;
  line-height: 1.35 !important;
  color: var(--ink) !important;
}
.fi-empty-state .fi-empty-state-description {
  margin-top: 3px !important;
  font-size: var(--font-sm) !important;
  line-height: 1.45 !important;
  color: var(--mute) !important;
}
.fi-empty-state .fi-empty-state-footer { margin-top: 12px !important; }
/* Компактный вариант живёт внутри карточки таблицы — там своя рамка, и вторая
   вокруг пустого состояния была бы рамкой в рамке. */
.fi-empty-state.fi-compact { padding: 14px var(--pad) !important; }
.fi-empty-state.fi-compact .fi-empty-state-icon-bg { margin-bottom: 0 !important; }
.fi-empty-state.fi-compact .fi-empty-state-footer { margin-top: 8px !important; }

/* ── Уважение к настройке «меньше движения» ───────────────────────────────
   Крутящийся индикатор и бегущий блик — единственные бесконечные анимации в
   этом файле; при выключенном движении они обязаны замереть, но остаться
   видимыми, иначе исчезнет сам признак ожидания. */
@media (prefers-reduced-motion: reduce) {
  .fi-loading-indicator { animation-duration: 1.6s !important; }
  .fi-loading-section {
    background-image: none !important;
    animation: none !important;
  }
}

/* ============================================================================
   НОВЫЕ ТОКЕНЫ (значения в `:root` не пишу — сведение словаря за ведущим)

   --overlay-ink — чернила затемнения фона под модальным окном. Отдельная ось,
     потому что ни `--ink`, ни `--skin-bg` не годятся в обеих темах сразу:
     в светлой чернила почти чёрные (совпадают с `--ink`), в тёмной — темнее
     холста (`--ink` там светлый и дал бы белую вуаль). Правило работает и без
     токена: подставлены запасные `var(--ink)` для светлой и `var(--skin-bg)`
     для тёмной.
       светлая: #0d1117
       тёмная:  #05070a

   Больше ничего не заведено: остальное собралось из словаря — плотность из
   `--pad`, текст из `--font-base`/`--font-sm`, состояния из
   `--ok/--warn/--bad/--info` вместе с их парами `*-soft`.
   ============================================================================ */


/* ── часть: form-fields.css ─────────────────────── */
/* Поля формы — Filament v5.
 *
 * Ось характера, ради которой заведены токены: у «учётного плотного» поле
 * ввода — это ЗАЛИВКА без видимой рамки (`--input-bg` + прозрачный
 * `--input-border`), а селект наоборот — белый по рамке (`--select-bg` +
 * `--select-border`). У другого характера они могут поменяться местами, и ни
 * одно правило ниже об этом знать не должно.
 *
 * Filament рисует обводку не рамкой, а кольцом в `box-shadow`
 * (`--tw-ring-shadow`). Поэтому почти везде, где нужен свой контур, кольцо
 * гасится, а форма задаётся честной `border` — она же даёт стабильную высоту:
 * рамка есть всегда, меняется только её цвет.
 */

/* ── обёртка поля, подпись, ошибка ───────────────────────────────────── */

.fi-fo-field {
  row-gap: var(--field-gap);
}

.fi-fo-field .fi-fo-field-label-col {
  row-gap: var(--field-gap);
}

.fi-fo-field .fi-fo-field-label,
.fi-fo-field .fi-fo-field-label-content {
  font-size: var(--font-sm);
  font-weight: var(--label-weight);
  color: var(--label-ink);
}

.fi-fo-field .fi-fo-field-label-content .fi-fo-field-label-required-mark {
  color: var(--bad);
  font-weight: var(--label-weight);
}

.fi-fo-field:has(.fi-invalid) .fi-fo-field-label,
.fi-fo-field:has(.fi-invalid) .fi-fo-field-label-content {
  color: var(--bad);
}

.fi-fo-field .fi-fo-field-wrp-error-message {
  font-size: var(--font-sm);
  line-height: 1.4;
  color: var(--bad);
}

.fi-fo-field .fi-fo-field-wrp-error-list {
  font-size: var(--font-sm);
  color: var(--bad);
}

.fi-fo-field .fi-fo-field-content-ctn {
  column-gap: var(--input-pad-x);
}

/* ── общая оболочка вводимого (текст, селект, дата, теги, ключ-значение) ─ */

.fi-input-wrp {
  display: flex;
  align-items: center;
  min-height: var(--input-h);
  border: 1px solid var(--input-border);
  border-radius: var(--radius);
  background: var(--input-bg);
  box-shadow: none !important;
  transition: background-color .12s ease, border-color .12s ease, box-shadow .12s ease;
}

.fi-input-wrp:hover:not(.fi-disabled):not(.fi-invalid):not(:focus-within) {
  border-color: var(--input-border-hover);
}

.fi-input-wrp:not(.fi-disabled):not(:has(.fi-ac-action:focus)):focus-within {
  background: var(--input-bg-focus);
  border-color: var(--primary);
  box-shadow: 0 0 0 var(--input-ring-w) var(--primary-soft) !important;
}

.fi-input-wrp.fi-invalid {
  border-color: var(--bad);
  background: color-mix(in srgb, var(--bad) 10%, var(--surface));
}

.fi-input-wrp.fi-invalid:not(.fi-disabled):focus-within {
  border-color: var(--bad);
  box-shadow: 0 0 0 var(--input-ring-w) color-mix(in srgb, var(--bad) 22%, transparent) !important;
}

.fi-input-wrp:has(.fi-input[readonly]),
.fi-input-wrp:has(textarea[readonly]) {
  background: var(--input-readonly-bg);
  border-color: var(--line);
}

.fi-input-wrp:has(.fi-input[readonly]) .fi-input,
.fi-input-wrp:has(textarea[readonly]) textarea {
  color: var(--input-readonly-ink);
}

.fi-input-wrp.fi-disabled {
  background: var(--input-disabled-bg);
  border-style: dashed;
  border-color: var(--line);
  cursor: not-allowed;
}

.fi-input-wrp.fi-disabled:focus-within {
  box-shadow: none !important;
}

/* префикс и суффикс: разделитель — линия темы, подпись — приглушённый текст */

.fi-input-wrp .fi-input-wrp-prefix,
.fi-input-wrp .fi-input-wrp-suffix {
  column-gap: calc(var(--input-pad-x) - 2px);
}

.fi-input-wrp .fi-input-wrp-prefix:not(.fi-inline) {
  border-inline-end-color: var(--line);
  padding-inline: var(--input-pad-x);
}

.fi-input-wrp .fi-input-wrp-suffix:not(.fi-inline) {
  border-inline-start-color: var(--line);
  padding-inline-start: var(--input-pad-x);
}

.fi-input-wrp .fi-input-wrp-prefix.fi-inline {
  padding-inline-start: var(--input-pad-x);
}

.fi-input-wrp .fi-input-wrp-suffix.fi-inline {
  padding-inline-end: var(--input-pad-x);
}

.fi-input-wrp .fi-input-wrp-label {
  font-size: var(--font-sm);
  color: var(--mute);
}

.fi-input-wrp .fi-input-wrp-prefix > .fi-icon,
.fi-input-wrp .fi-input-wrp-suffix > .fi-icon {
  color: var(--faint);
}

/* `.fi-fo-field-content-col` — грид, и его единственная строка тянется на всю
   высоту поля. Стоит соседу по ряду показать ошибку — и поле рядом вырастает
   вслед за ним (замерено: 50px против 26px). Раз высота однострочных задана
   токеном, они и так вровень, тянуться им незачем. */
.fi-fo-field-content-col > .fi-input-wrp.fi-fo-text-input,
.fi-fo-field-content-col > .fi-input-wrp.fi-fo-select,
.fi-fo-field-content-col > .fi-input-wrp.fi-fo-date-time-picker,
.fi-fo-field-content-col > .fi-input-wrp.fi-fo-color-picker {
  align-self: start;
}

/* ── однострочное текстовое поле ─────────────────────────────────────── */

.fi-input-wrp.fi-fo-text-input {
  min-height: var(--input-h);
}

.fi-input-wrp .fi-input {
  padding-inline: var(--input-pad-x);
  padding-block: 0;
  min-height: calc(var(--input-h) - 2px);
  line-height: calc(var(--input-h) - 2px);
  font-size: var(--font-base);
  color: var(--input-ink);
  background: transparent;
}

.fi-input-wrp .fi-input::placeholder {
  color: var(--input-placeholder);
  opacity: 1;
}

.fi-input-wrp .fi-input:focus,
.fi-input-wrp .fi-input:focus-visible {
  outline: none;
  box-shadow: none;
}

.fi-input-wrp .fi-input[readonly] {
  color: var(--input-readonly-ink);
  cursor: default;
}

.fi-input-wrp .fi-input:disabled {
  color: var(--input-disabled-ink);
  -webkit-text-fill-color: var(--input-disabled-ink);
  cursor: not-allowed;
}

.fi-input-wrp .fi-input.fi-input-has-inline-prefix {
  padding-inline-start: 0;
}

.fi-input-wrp .fi-input.fi-input-has-inline-suffix {
  padding-inline-end: 0;
}

/* ── многострочное ───────────────────────────────────────────────────── */

.fi-input-wrp.fi-fo-textarea {
  align-items: stretch;
  padding-block: calc(var(--field-gap) + 1px);
}

.fi-input-wrp.fi-fo-textarea textarea {
  padding-inline: var(--input-pad-x);
  padding-block: 0;
  font-size: var(--font-base);
  line-height: 1.5;
  color: var(--input-ink);
  background: transparent;
}

.fi-input-wrp.fi-fo-textarea textarea::placeholder {
  color: var(--input-placeholder);
  opacity: 1;
}

.fi-input-wrp.fi-fo-textarea textarea:focus,
.fi-input-wrp.fi-fo-textarea textarea:focus-visible {
  outline: none;
  box-shadow: none;
}

.fi-input-wrp.fi-fo-textarea textarea[readonly] {
  color: var(--input-readonly-ink);
}

.fi-input-wrp.fi-fo-textarea textarea:disabled {
  color: var(--input-disabled-ink);
  -webkit-text-fill-color: var(--input-disabled-ink);
  cursor: not-allowed;
}

/* ── селект: вторая половина оси характера — заливка своя, рамка видимая ─ */

.fi-input-wrp.fi-fo-select {
  background: var(--select-bg);
  border-color: var(--select-border);
}

.fi-input-wrp.fi-fo-select:hover:not(.fi-disabled):not(.fi-invalid):not(:focus-within) {
  border-color: var(--line-strong);
  background: var(--hover);
}

.fi-input-wrp.fi-fo-select:not(.fi-disabled):focus-within {
  background: var(--select-bg);
  border-color: var(--primary);
}

.fi-input-wrp.fi-fo-select.fi-invalid {
  border-color: var(--bad);
  background: color-mix(in srgb, var(--bad) 10%, var(--surface));
}

.fi-input-wrp.fi-fo-select.fi-disabled {
  background: var(--input-disabled-bg);
  border-color: var(--line);
}

.fi-input-wrp .fi-select-input {
  min-height: calc(var(--input-h) - 2px);
  padding-block: 0;
  padding-inline-start: var(--input-pad-x);
  /* У НАТИВНОГО селекта стрелка нарисована ФОНОМ у правого края, а не
     отдельным узлом: место под неё держит только отступ. `padding-inline`
     задавал оба края разом и это место стирал — «Источник данных» уезжал
     буквами под стрелку. Ширина стрелки постоянная, поэтому и прибавка
     постоянная, а не доля от отступа: на характере с отступом 6px доля не
     спасала. */
  padding-inline-end: calc(var(--input-pad-x) + 18px);
  font-size: var(--font-base);
  line-height: calc(var(--input-h) - 2px);
  color: var(--input-ink);
  background-color: transparent;
  border-radius: var(--radius);
}

.fi-input-wrp .fi-select-input:focus,
.fi-input-wrp .fi-select-input:focus-visible {
  outline: none;
  box-shadow: none;
}

.fi-input-wrp .fi-select-input:disabled {
  color: var(--input-disabled-ink);
  cursor: not-allowed;
}

.fi-input-wrp .fi-select-input option,
.fi-input-wrp .fi-select-input optgroup {
  background: var(--surface);
  color: var(--body);
}

/* У Alpine-селекта высоту держит не кнопка, а её обёртка: без этой строки
   поле остаётся на стоковых 36px, а плотность рассыпается. */
.fi-select-input div[x-ref=select] {
  min-height: calc(var(--input-h) - 2px);
}

.fi-select-input .fi-select-input-btn {
  min-height: calc(var(--input-h) - 2px);
  padding-block: 0;
  padding-inline-start: var(--input-pad-x);
  padding-inline-end: calc(var(--input-pad-x) * 3);
  font-size: var(--font-base);
  line-height: calc(var(--input-h) - 2px);
  color: var(--input-ink);
  border-radius: var(--radius);
}

.fi-select-input .fi-select-input-btn:focus,
.fi-select-input .fi-select-input-btn:focus-visible {
  outline: none;
  box-shadow: none;
}

.fi-select-input .fi-select-input-value-ctn {
  align-items: center;
  gap: calc(var(--field-gap) + 1px);
  color: var(--input-ink);
  font-size: var(--font-base);
}

.fi-select-input .fi-select-input-value-label {
  color: var(--input-ink);
}

.fi-select-input .fi-select-input-placeholder {
  color: var(--input-placeholder);
}

.fi-select-input .fi-disabled .fi-select-input-placeholder,
.fi-select-input .fi-disabled .fi-select-input-value-ctn {
  color: var(--input-disabled-ink);
}

.fi-select-input .fi-select-input-value-remove-btn {
  color: var(--faint);
  border-radius: var(--radius-sm);
}

.fi-select-input .fi-select-input-value-remove-btn:hover {
  color: var(--bad);
  background: var(--hover);
}

.fi-select-input .fi-select-input-value-remove-btn:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 1px;
}

.fi-select-input .fi-select-input-search-ctn {
  background: var(--surface);
}

.fi-select-input .fi-select-input-option {
  font-size: var(--font-base);
  color: var(--body);
  border-radius: var(--radius-sm);
}

.fi-select-input .fi-select-input-option:hover {
  background: var(--hover);
}

.fi-select-input .fi-select-input-option.fi-selected {
  background: var(--selected);
  color: var(--primary);
}

.fi-select-input .fi-select-input-message {
  font-size: var(--font-sm);
  color: var(--mute);
}

/* ── флажок ──────────────────────────────────────────────────────────── */

input[type=checkbox].fi-checkbox-input {
  width: var(--check-size);
  height: var(--check-size);
  border: 1px solid var(--check-border);
  border-radius: var(--radius-sm);
  background-color: var(--check-bg);
  box-shadow: none !important;
  cursor: pointer;
  transition: background-color .12s ease, border-color .12s ease, box-shadow .12s ease;
}

input[type=checkbox].fi-checkbox-input:hover:not(:disabled) {
  border-color: var(--primary);
}

input[type=checkbox].fi-checkbox-input:checked {
  background-color: var(--check-on);
  border-color: var(--check-on);
}

input[type=checkbox].fi-checkbox-input:focus-visible {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 var(--input-ring-w) var(--primary-soft) !important;
}

input[type=checkbox].fi-checkbox-input.fi-invalid {
  border-color: var(--bad);
}

input[type=checkbox].fi-checkbox-input.fi-invalid:checked {
  background-color: var(--bad);
  border-color: var(--bad);
}

input[type=checkbox].fi-checkbox-input.fi-invalid:focus-visible {
  box-shadow: 0 0 0 var(--input-ring-w) color-mix(in srgb, var(--bad) 22%, transparent) !important;
}

input[type=checkbox].fi-checkbox-input[readonly] {
  pointer-events: none;
  border-color: var(--line);
}

input[type=checkbox].fi-checkbox-input:disabled {
  background-color: var(--input-disabled-bg);
  border-color: var(--line);
  border-style: dashed;
  cursor: not-allowed;
}

input[type=checkbox].fi-checkbox-input:disabled:checked {
  background-color: var(--neutral);
  border-color: var(--neutral);
  border-style: solid;
}

/* список флажков */

.fi-fo-checkbox-list .fi-fo-checkbox-list-search-input-wrp {
  margin-bottom: var(--pad);
}

.fi-fo-checkbox-list .fi-fo-checkbox-list-actions {
  margin-bottom: var(--field-gap);
}

.fi-fo-checkbox-list .fi-fo-checkbox-list-options {
  gap: calc(var(--field-gap) * 2);
}

.fi-fo-checkbox-list .fi-fo-checkbox-list-options.fi-grid-direction-col {
  margin-top: calc(var(--field-gap) * -2);
}

.fi-fo-checkbox-list .fi-fo-checkbox-list-options.fi-grid-direction-col .fi-fo-checkbox-list-option-ctn {
  padding-top: calc(var(--field-gap) * 2);
}

.fi-fo-checkbox-list .fi-fo-checkbox-list-option {
  column-gap: calc(var(--input-pad-x) - 1px);
  align-items: center;
}

.fi-fo-checkbox-list .fi-fo-checkbox-list-option .fi-checkbox-input {
  margin-top: 0;
}

.fi-fo-checkbox-list .fi-fo-checkbox-list-option .fi-fo-checkbox-list-option-text {
  font-size: var(--font-base);
  line-height: 1.5;
}

.fi-fo-checkbox-list .fi-fo-checkbox-list-option .fi-fo-checkbox-list-option-label {
  color: var(--body);
  font-weight: 400;
}

.fi-fo-checkbox-list .fi-fo-checkbox-list-option .fi-fo-checkbox-list-option-description {
  font-size: var(--font-sm);
  color: var(--mute);
}

.fi-fo-checkbox-list .fi-fo-checkbox-list-option:hover .fi-fo-checkbox-list-option-label {
  color: var(--ink);
}

.fi-fo-checkbox-list .fi-fo-checkbox-list-option:has(.fi-checkbox-input:disabled) .fi-fo-checkbox-list-option-label,
.fi-fo-checkbox-list .fi-fo-checkbox-list-option:has(.fi-checkbox-input:disabled) .fi-fo-checkbox-list-option-description {
  color: var(--faint);
}

.fi-fo-checkbox-list .fi-fo-checkbox-list-no-search-results-message {
  font-size: var(--font-sm);
  color: var(--mute);
}

/* ── переключатель ───────────────────────────────────────────────────── */

.fi-toggle {
  width: var(--toggle-w);
  height: var(--toggle-h);
  padding: 1px;
  border: 1px solid var(--toggle-off-border);
  border-radius: calc(var(--toggle-h) / 2);
  background-color: var(--toggle-off-bg) !important;
  align-items: center;
  box-shadow: none;
  transition: background-color .12s ease, border-color .12s ease, box-shadow .12s ease;
}

.fi-toggle:hover:not(:disabled) {
  border-color: var(--primary);
}

.fi-toggle:focus-visible {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 var(--input-ring-w) var(--primary-soft) !important;
}

.fi-toggle.fi-invalid {
  border-color: var(--bad);
}

.fi-toggle:disabled,
.fi-toggle[disabled] {
  background-color: var(--input-disabled-bg) !important;
  border-color: var(--line);
  cursor: not-allowed;
  opacity: 1;
}

.fi-toggle.fi-toggle-off {
  background-color: var(--toggle-off-bg) !important;
  border-color: var(--toggle-off-border);
}

.fi-toggle.fi-toggle-on {
  background-color: var(--toggle-on-bg) !important;
  border-color: var(--toggle-on-bg);
}

.fi-toggle > :first-child {
  width: calc(var(--toggle-h) - 4px);
  height: calc(var(--toggle-h) - 4px);
  border-radius: 50%;
  box-shadow: var(--shadow-sm);
  transition: translate .16s ease, background-color .12s ease;
}

.fi-toggle.fi-toggle-off > :first-child {
  background-color: var(--toggle-knob-off) !important;
  translate: 0 0 !important;
}

.fi-toggle.fi-toggle-on > :first-child {
  background-color: var(--toggle-knob-on) !important;
  translate: calc(var(--toggle-w) - var(--toggle-h)) 0 !important;
}

.fi-toggle .fi-icon {
  color: var(--toggle-off-bg);
}

/* ── радио ───────────────────────────────────────────────────────────── */

input[type=radio].fi-radio-input {
  width: var(--check-size);
  height: var(--check-size);
  border: 1px solid var(--check-border);
  border-radius: 50%;
  background-color: var(--check-bg);
  box-shadow: none !important;
  cursor: pointer;
  transition: background-color .12s ease, border-color .12s ease, box-shadow .12s ease;
}

input[type=radio].fi-radio-input:hover:not(:disabled) {
  border-color: var(--primary);
}

input[type=radio].fi-radio-input:checked {
  background-color: var(--check-on);
  border-color: var(--check-on);
}

input[type=radio].fi-radio-input:focus-visible {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 var(--input-ring-w) var(--primary-soft) !important;
}

input[type=radio].fi-radio-input.fi-invalid {
  border-color: var(--bad);
}

input[type=radio].fi-radio-input.fi-invalid:checked {
  background-color: var(--bad);
  border-color: var(--bad);
}

input[type=radio].fi-radio-input.fi-invalid:focus-visible {
  box-shadow: 0 0 0 var(--input-ring-w) color-mix(in srgb, var(--bad) 22%, transparent) !important;
}

input[type=radio].fi-radio-input[readonly] {
  pointer-events: none;
  border-color: var(--line);
}

input[type=radio].fi-radio-input:disabled {
  background-color: var(--input-disabled-bg);
  border-color: var(--line);
  border-style: dashed;
  cursor: not-allowed;
}

input[type=radio].fi-radio-input:disabled:checked {
  background-color: var(--neutral);
  border-color: var(--neutral);
  border-style: solid;
}

.fi-fo-radio {
  gap: calc(var(--field-gap) * 2);
}

.fi-fo-radio:not(.fi-inline).fi-grid-direction-col {
  margin-top: calc(var(--field-gap) * -2);
}

.fi-fo-radio:not(.fi-inline).fi-grid-direction-col > .fi-fo-radio-label {
  padding-top: calc(var(--field-gap) * 2);
}

.fi-fo-radio > .fi-fo-radio-label {
  column-gap: calc(var(--input-pad-x) - 2px);
  align-items: center;
  cursor: pointer;
}

.fi-fo-radio > .fi-fo-radio-label > .fi-radio-input {
  margin-top: 0;
}

.fi-fo-radio > .fi-fo-radio-label > .fi-fo-radio-label-text {
  font-size: var(--font-base);
  line-height: 1.5;
  font-weight: 400;
  color: var(--body);
}

.fi-fo-radio > .fi-fo-radio-label:hover > .fi-fo-radio-label-text {
  color: var(--ink);
}

.fi-fo-radio > .fi-fo-radio-label .fi-fo-radio-label-description {
  font-size: var(--font-sm);
  color: var(--mute);
}

.fi-fo-radio > .fi-fo-radio-label:has(.fi-radio-input:disabled) {
  cursor: not-allowed;
}

.fi-fo-radio > .fi-fo-radio-label:has(.fi-radio-input:disabled) > .fi-fo-radio-label-text,
.fi-fo-radio > .fi-fo-radio-label:has(.fi-radio-input:disabled) .fi-fo-radio-label-description {
  color: var(--faint);
}

/* ── кнопки-переключатели ────────────────────────────────────────────── */

.fi-fo-toggle-buttons:not(.fi-btn-group) {
  gap: var(--field-gap);
}

.fi-fo-toggle-buttons:not(.fi-btn-group):not(.fi-inline).fi-grid-direction-col {
  margin-top: calc(var(--field-gap) * -1);
}

.fi-fo-toggle-buttons:not(.fi-btn-group):not(.fi-inline).fi-grid-direction-col .fi-fo-toggle-buttons-btn-ctn {
  padding-top: var(--field-gap);
}

.fi-fo-toggle-buttons .fi-fo-toggle-buttons-btn-ctn > label.fi-btn {
  min-height: var(--input-h);
  padding-block: 0;
  padding-inline: calc(var(--input-pad-x) + 3px);
  font-size: var(--font-base);
  line-height: calc(var(--input-h) - 2px);
  border-radius: var(--radius);
  cursor: pointer;
}

.fi-fo-toggle-buttons .fi-fo-toggle-buttons-input:not(:checked) + label.fi-btn {
  background: var(--select-bg);
  color: var(--body);
  border: 1px solid var(--select-border);
  box-shadow: none;
}

.fi-fo-toggle-buttons .fi-fo-toggle-buttons-input:not(:checked) + label.fi-btn:hover {
  background: var(--hover);
  color: var(--ink);
}

.fi-fo-toggle-buttons .fi-fo-toggle-buttons-input:checked + label.fi-btn {
  background: var(--primary);
  color: var(--on-primary);
  border: 1px solid var(--primary);
  box-shadow: none;
}

.fi-fo-toggle-buttons .fi-fo-toggle-buttons-input:checked + label.fi-btn:hover {
  background: var(--primary-hover);
  border-color: var(--primary-hover);
}

.fi-fo-toggle-buttons .fi-fo-toggle-buttons-input:focus-visible + label.fi-btn {
  outline: none;
  box-shadow: 0 0 0 var(--input-ring-w) var(--primary-soft);
}

.fi-fo-toggle-buttons.fi-invalid .fi-fo-toggle-buttons-input:not(:checked) + label.fi-btn {
  border-color: var(--bad);
}

.fi-fo-toggle-buttons .fi-fo-toggle-buttons-input[readonly] + label.fi-btn {
  pointer-events: none;
}

.fi-fo-toggle-buttons .fi-fo-toggle-buttons-input:disabled + label.fi-btn {
  background: var(--input-disabled-bg);
  color: var(--input-disabled-ink);
  border: 1px solid var(--line);
  cursor: not-allowed;
}

/* ── дата и время ────────────────────────────────────────────────────── */

.fi-fo-date-time-picker .fi-fo-date-time-picker-trigger {
  cursor: pointer;
}

.fi-fo-date-time-picker .fi-fo-date-time-picker-display-text-input {
  padding-inline: var(--input-pad-x);
  padding-block: 0;
  min-height: calc(var(--input-h) - 2px);
  line-height: calc(var(--input-h) - 2px);
  font-size: var(--font-base);
  color: var(--input-ink);
  background: transparent;
  cursor: pointer;
}

.fi-fo-date-time-picker .fi-fo-date-time-picker-display-text-input::placeholder {
  color: var(--input-placeholder);
  opacity: 1;
}

.fi-fo-date-time-picker .fi-fo-date-time-picker-display-text-input:focus,
.fi-fo-date-time-picker .fi-fo-date-time-picker-display-text-input:focus-visible {
  outline: none;
  box-shadow: none;
}

.fi-fo-date-time-picker .fi-fo-date-time-picker-display-text-input[readonly]:not([x-ref]) {
  color: var(--input-readonly-ink);
}

.fi-fo-date-time-picker .fi-fo-date-time-picker-display-text-input:disabled {
  color: var(--input-disabled-ink);
  -webkit-text-fill-color: var(--input-disabled-ink);
  cursor: not-allowed;
}

.fi-fo-date-time-picker .fi-fo-date-time-picker-panel {
  padding: var(--pad);
  border: 1px solid var(--picker-panel-border);
  border-radius: var(--radius-lg);
  background: var(--picker-panel-bg);
  box-shadow: var(--shadow);
}

.fi-fo-date-time-picker .fi-fo-date-time-picker-panel-header {
  margin-bottom: var(--field-gap);
}

.fi-fo-date-time-picker .fi-fo-date-time-picker-month-select,
.fi-fo-date-time-picker .fi-fo-date-time-picker-year-input {
  font-size: var(--font-base);
  color: var(--ink);
  background: transparent;
  border-radius: var(--radius-sm);
}

.fi-fo-date-time-picker .fi-fo-date-time-picker-month-select:focus-visible,
.fi-fo-date-time-picker .fi-fo-date-time-picker-year-input:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 1px;
}

.fi-fo-date-time-picker .fi-fo-date-time-picker-calendar-header .fi-fo-date-time-picker-calendar-header-day {
  font-size: var(--font-sm);
  color: var(--faint);
  font-weight: 500;
}

.fi-fo-date-time-picker .fi-fo-date-time-picker-calendar .fi-fo-date-time-picker-calendar-day {
  font-size: var(--font-base);
  line-height: calc(var(--input-h) - 2px);
  border-radius: var(--radius-sm);
  color: var(--body);
}

.fi-fo-date-time-picker .fi-fo-date-time-picker-calendar .fi-fo-date-time-picker-calendar-day:not(.fi-disabled):hover {
  background: var(--hover);
  color: var(--ink);
}

.fi-fo-date-time-picker .fi-fo-date-time-picker-calendar .fi-fo-date-time-picker-calendar-day.fi-focused:not(.fi-selected):not(.fi-disabled) {
  background: var(--hover);
}

.fi-fo-date-time-picker .fi-fo-date-time-picker-calendar .fi-fo-date-time-picker-calendar-day.fi-selected {
  background: var(--selected);
  color: var(--primary);
  font-weight: 600;
}

.fi-fo-date-time-picker .fi-fo-date-time-picker-calendar .fi-fo-date-time-picker-calendar-day.fi-fo-date-time-picker-calendar-day-today:not(.fi-focused):not(.fi-selected):not(.fi-disabled) {
  color: var(--primary);
  box-shadow: inset 0 0 0 1px var(--primary);
}

.fi-fo-date-time-picker .fi-fo-date-time-picker-calendar .fi-fo-date-time-picker-calendar-day.fi-disabled {
  color: var(--faint);
  opacity: 1;
}

.fi-fo-date-time-picker .fi-fo-date-time-picker-time-inputs {
  margin-top: var(--field-gap);
}

.fi-fo-date-time-picker .fi-fo-date-time-picker-time-inputs input {
  font-size: var(--font-base);
  color: var(--ink);
  background: var(--input-bg);
  border: 1px solid var(--input-border);
  border-radius: var(--radius-sm);
}

.fi-fo-date-time-picker .fi-fo-date-time-picker-time-inputs input:focus-visible {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 var(--input-ring-w) var(--primary-soft);
}

.fi-fo-date-time-picker .fi-fo-date-time-picker-time-inputs .fi-fo-date-time-picker-time-input-separator {
  font-size: var(--font-base);
  color: var(--mute);
}

/* ── теги ────────────────────────────────────────────────────────────── */

.fi-input-wrp.fi-fo-tags-input {
  align-items: stretch;
  flex-direction: column;
}

.fi-fo-tags-input .fi-fo-tags-input-tags-ctn {
  gap: var(--field-gap);
  padding: calc(var(--field-gap) + 1px) var(--input-pad-x);
  border-top: 1px solid var(--line);
}

.fi-fo-tags-input .fi-fo-tags-input-tags-ctn > .fi-badge {
  font-size: var(--font-sm);
  border-radius: var(--radius-sm);
}

.fi-fo-tags-input.fi-disabled .fi-fo-tags-input-tags-ctn {
  border-top-color: var(--line-soft);
}

/* ── ключ-значение ───────────────────────────────────────────────────── */

.fi-input-wrp.fi-fo-key-value {
  align-items: stretch;
  flex-direction: column;
  padding: 0;
}

.fi-fo-key-value .fi-fo-key-value-table > thead > tr > th {
  padding-inline: var(--input-pad-x);
  padding-block: var(--field-gap);
  font-size: var(--font-sm);
  font-weight: 500;
  color: var(--mute);
  border-bottom: 1px solid var(--line);
}

.fi-fo-key-value .fi-fo-key-value-table > tbody > tr:not(:last-child) > td {
  border-bottom: 1px solid var(--line-soft);
}

.fi-fo-key-value .fi-fo-key-value-table > tbody > tr:hover > td {
  background: var(--hover);
}

.fi-fo-key-value .fi-fo-key-value-table > tbody > tr > td .fi-input {
  font-size: var(--font-sm);
  color: var(--input-ink);
}

.fi-fo-key-value .fi-fo-key-value-table-row-sortable-handle {
  color: var(--faint);
  cursor: grab;
}

.fi-fo-key-value .fi-fo-key-value-add-action-ctn {
  padding-inline: var(--input-pad-x);
  padding-block: var(--field-gap);
  border-top: 1px solid var(--line);
}

.fi-input-wrp.fi-fo-key-value.fi-disabled .fi-fo-key-value-table > tbody > tr:hover > td {
  background: transparent;
}

/* ── повторитель ─────────────────────────────────────────────────────── */

.fi-fo-repeater {
  row-gap: var(--pad);
}

.fi-fo-repeater .fi-fo-repeater-items {
  gap: var(--pad);
}

.fi-fo-repeater .fi-fo-repeater-item {
  border: 1px solid var(--repeater-item-border);
  border-radius: var(--radius);
  background: var(--repeater-item-bg);
  box-shadow: var(--shadow-sm) !important;
}

.fi-fo-repeater .fi-fo-repeater-item:hover {
  border-color: var(--line-strong);
}

.fi-fo-repeater .fi-fo-repeater-item.fi-invalid,
.fi-fo-repeater .fi-fo-repeater-item:has(.fi-fo-field-wrp-error-message) {
  border-color: var(--bad);
}

.fi-fo-repeater .fi-fo-repeater-item:focus-within {
  border-color: var(--primary);
}

.fi-fo-repeater .fi-fo-repeater-item-header {
  padding-inline: var(--pad);
  padding-block: calc(var(--field-gap) * 2);
  background: var(--surface-2);
  border-radius: calc(var(--radius) - 1px) calc(var(--radius) - 1px) 0 0;
}

.fi-fo-repeater .fi-fo-repeater-item-header-label {
  font-size: var(--font-base);
  font-weight: 600;
  color: var(--ink);
}

.fi-fo-repeater .fi-fo-repeater-item-has-header > .fi-fo-repeater-item-content {
  border-top: 1px solid var(--line);
}

.fi-fo-repeater .fi-fo-repeater-item-content {
  padding: var(--pad);
}

.fi-fo-repeater .fi-fo-repeater-add-between-items {
  background: var(--surface);
  border-radius: var(--radius);
}

.fi-fo-repeater .fi-fo-repeater-label-between-items {
  font-size: var(--font-sm);
  color: var(--mute);
}

.fi-fo-repeater .fi-fo-repeater-label-between-items-divider-before,
.fi-fo-repeater .fi-fo-repeater-label-between-items-divider-after {
  border-top-color: var(--line);
}

.fi-fo-repeater.fi-disabled .fi-fo-repeater-item,
.fi-fo-repeater .fi-fo-repeater-item.fi-disabled {
  background: var(--input-disabled-bg);
  border-style: dashed;
}

/* ── загрузка файла ──────────────────────────────────────────────────── */

.fi-fo-file-upload {
  row-gap: var(--field-gap);
}

.fi-fo-file-upload .filepond--root {
  border: 1px dashed var(--upload-border);
  border-radius: var(--radius);
  background-color: var(--input-bg);
  box-shadow: none !important;
  font-size: var(--font-base);
  transition: border-color .12s ease, background-color .12s ease;
}

.fi-fo-file-upload .filepond--root:hover {
  border-color: var(--primary);
  background-color: var(--hover);
}

.fi-fo-file-upload .filepond--root:focus-within {
  border-color: var(--primary);
  box-shadow: 0 0 0 var(--input-ring-w) var(--primary-soft) !important;
}

.fi-fo-file-upload.fi-invalid .filepond--root {
  border-color: var(--bad);
}

.fi-fo-file-upload .filepond--root[data-disabled=disabled] {
  background-color: var(--input-disabled-bg);
  border-color: var(--line);
  cursor: not-allowed;
}

.fi-fo-file-upload .filepond--root[data-disabled=disabled]:hover {
  border-color: var(--line);
  background-color: var(--input-disabled-bg);
}

.fi-fo-file-upload .filepond--drop-label label {
  font-size: var(--font-sm);
  color: var(--mute);
}

.fi-fo-file-upload .filepond--label-action {
  color: var(--primary);
  text-decoration-color: var(--primary);
}

.fi-fo-file-upload .filepond--label-action:hover {
  color: var(--primary-hover);
}

.fi-fo-file-upload .fi-fo-file-upload-error-message {
  font-size: var(--font-sm);
  color: var(--bad);
}

.fi-fo-file-upload .fi-fo-file-upload-editor-window {
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--surface);
  box-shadow: var(--shadow) !important;
}

.fi-fo-file-upload .fi-fo-file-upload-editor-control-panel {
  background: var(--surface-2);
}

.fi-fo-file-upload .fi-fo-file-upload-editor-control-panel-group-title {
  font-size: var(--font-sm);
  color: var(--mute);
}

/* ── ползунок ────────────────────────────────────────────────────────── */

.fi-fo-slider {
  gap: var(--pad);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: none !important;
}

.fi-fo-slider .noUi-connects {
  border-radius: var(--radius);
  background-color: var(--slider-track);
}

.fi-fo-slider .noUi-connect {
  background-color: var(--slider-fill);
}

.fi-fo-slider .noUi-handle {
  border: 1px solid var(--check-border);
  border-radius: 50%;
  background-color: var(--slider-handle-bg);
  box-shadow: var(--shadow-sm);
  cursor: grab;
}

.fi-fo-slider .noUi-handle:hover {
  border-color: var(--primary);
}

.fi-fo-slider .noUi-handle:focus,
.fi-fo-slider .noUi-handle:focus-visible {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 var(--input-ring-w) var(--primary-soft);
}

.fi-fo-slider[disabled] .noUi-handle,
.fi-fo-slider .noUi-handle[disabled] {
  background-color: var(--input-disabled-bg);
  border-color: var(--line);
  cursor: not-allowed;
}

.fi-fo-slider .noUi-tooltip {
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background-color: var(--surface);
  color: var(--ink);
  font-size: var(--font-sm);
  box-shadow: var(--shadow-sm);
}

.fi-fo-slider .noUi-pips .noUi-value {
  font-size: var(--font-sm);
  color: var(--mute);
}

/* ── выбор цвета ─────────────────────────────────────────────────────── */

.fi-fo-color-picker .fi-fo-color-picker-preview {
  width: calc(var(--input-h) - 12px);
  height: calc(var(--input-h) - 12px);
  margin-inline-end: calc(var(--input-pad-x) - 2px);
  border: 1px solid var(--line-strong);
  box-shadow: none !important;
}

.fi-fo-color-picker .fi-fo-color-picker-preview.fi-empty {
  border-style: dashed;
  border-color: var(--line-strong);
}

.fi-fo-color-picker .fi-fo-color-picker-panel {
  padding: var(--pad);
  border: 1px solid var(--picker-panel-border);
  border-radius: var(--radius-lg);
  background: var(--picker-panel-bg);
  box-shadow: var(--shadow) !important;
}

/* ─────────────────────────────────────────────────────────────────────
 * НОВЫЕ ТОКЕНЫ (значения свести в словарь — здесь их объявлять нельзя)
 *
 * Смысл · предлагаемое значение для светлой / тёмной темы
 *
 * --input-h            высота однострочного поля · 26px / 26px
 * --input-pad-x        боковой отступ внутри поля · 8px / 8px
 * --input-bg           заливка поля ввода · var(--surface-2) / var(--surface-2)
 * --input-border       рамка поля ввода, у «учётного» невидима · transparent / transparent
 * --input-border-hover рамка поля при наведении · var(--line-strong) / var(--line-strong)
 * --input-bg-focus     заливка поля в фокусе · var(--surface) / var(--surface)
 * --input-ink          цвет введённого текста · var(--ink) / var(--ink)
 * --input-placeholder  цвет подсказки в пустом поле · var(--faint) / var(--faint)
 * --input-ring-w       толщина свечения фокуса · 3px / 3px
 * --input-readonly-bg  заливка поля только для чтения · transparent / transparent
 * --input-readonly-ink текст поля только для чтения · var(--mute) / var(--mute)
 * --input-disabled-bg  заливка отключённого поля · var(--skin-bg) / var(--skin-bg)
 * --input-disabled-ink текст отключённого поля · var(--faint) / var(--faint)
 * --select-bg          заливка селекта — вторая половина оси характера · var(--surface) / var(--surface)
 * --select-border      рамка селекта, у «учётного» видима · var(--line-strong) / var(--line-strong)
 * --label-ink          цвет подписи поля · var(--mute) / var(--mute)
 * --label-weight       насыщенность подписи · 400 / 400
 * --field-gap          зазор подпись↔поле и шаг мелких сеток · 3px / 3px
 * --check-size         сторона флажка и радио · 12px / 12px
 * --check-bg           заливка неотмеченного флажка · var(--surface) / var(--surface-2)
 * --check-border       рамка неотмеченного флажка · var(--line-strong) / var(--line-strong)
 * --check-on           заливка отмеченного флажка (галка от Filament белая — держать тёмным) · var(--primary) / var(--primary)
 * --toggle-w           ширина переключателя · 30px / 30px
 * --toggle-h           высота переключателя · 17px / 17px
 * --toggle-off-bg      заливка выключенного переключателя · var(--surface-2) / var(--surface-2)
 * --toggle-off-border  рамка выключенного переключателя · var(--line-strong) / var(--line-strong)
 * --toggle-on-bg       заливка включённого переключателя · var(--primary) / var(--primary)
 * --toggle-knob-off    кружок выключенного · var(--mute) / var(--mute)
 * --toggle-knob-on     кружок включённого · var(--on-primary) / var(--on-primary)
 * --picker-panel-bg    фон выпадающей панели даты и цвета · var(--surface) / var(--surface)
 * --picker-panel-border рамка той же панели · var(--line) / var(--line)
 * --repeater-item-bg   фон карточки повторителя · var(--surface) / var(--surface)
 * --repeater-item-border рамка карточки повторителя · var(--line) / var(--line)
 * --upload-border      пунктирная рамка зоны загрузки · var(--line-strong) / var(--line-strong)
 * --slider-track       дорожка ползунка · var(--surface-2) / var(--surface-2)
 * --slider-fill        пройденная часть ползунка · var(--primary) / var(--primary)
 * --slider-handle-bg   ручка ползунка · var(--surface) / var(--surface)
 * ───────────────────────────────────────────────────────────────────── */


/* ── часть: layout.css ─────────────────────── */
/* ============================================================================
   РАСКЛАДКА — секции, наборы полей, вкладки схемы, мастер, сетка, виджеты
   ----------------------------------------------------------------------------
   Всё держится на токенах словаря. Ни одного цвета, кегля, радиуса и тени
   в правилах — иначе половина панели сменит облик, а половина останется.

   Ось характеров для секции — три токена:
     --section-bg      заливка;
     --section-border  рамка (transparent → «лист без рамки»);
     --section-shadow  тень (none → «плоская коробка»).
   Комбинацией получаются все три знакомых облика:
     коробка   = bg surface  + border line      + shadow none
     лист      = bg surface  + border transparent + shadow shadow-sm
     без формы = bg transparent + border transparent + shadow none
                 (тогда секцию держат только заголовок и его волосок)

   Метрики сняты с эталона «Характер 01 — учётный плотный», экраны «Форма»,
   «Мастер», «Документ»: секция padding 12–16, волосок --line-soft, радиус
   --radius, тень --shadow-sm; шаг мастера 49px высотой, кружок номера 20px;
   вкладка 28px, подчёркивание 1.5px.
   ============================================================================ */

/* ── Секция: коробка ─────────────────────────────────────────────────────────
   Двойное имя класса — не описка: в admin-theme.css коробка задана селектором
   `.fi-fo-component-ctn > .fi-section` (вес 0-2-0), и одиночный `.fi-section`
   его не перебивает даже с !important. Разметку это не трогает.
   Заодно чинит три расхождения с обликом, замеренные на живой панели:
   радиус брался из `--bf-radius` (9px) вместо `--radius` (6px), тень — большая
   поповерная `--shadow` вместо `--shadow-sm`, и рамка не умела исчезать. */
.fi-section.fi-section {
    background: var(--section-bg, var(--surface)) !important;
    border: 1px solid var(--section-border, var(--line-soft)) !important;
    border-radius: var(--radius) !important;
    box-shadow: var(--section-shadow, var(--shadow-sm)) !important;
}

/* ── Волосок под шапкой секции ───────────────────────────────────────────────
   На живой панели их было ДВА: свой (`--line-soft` на низу шапки) и родной
   филаментовский на верху контейнера содержимого — тот вообще не знал облика
   (жёсткий gray-200 в oklch). Оставляем свой, родной гасим. */
.fi-section.fi-section-has-header > .fi-section-content-ctn {
    border-top: 0 !important;
}

/* Свёрнутая секция не должна тащить за собой висящий волосок. */
.fi-section.fi-collapsed > .fi-section-header {
    border-bottom-color: transparent !important;
}

/* ── Шапка секции: типографика ───────────────────────────────────────────────
   Родной кегль `text-base` (16px) в плотной панели читается как заголовок
   страницы. У эталона заголовок секции — тот же корпус, что и тело, весом. */
.fi-section-header-heading {
    font-size: var(--font-base) !important;
    line-height: 1.45 !important;
    letter-spacing: -.005em;
}

.fi-section-header-description {
    font-size: var(--font-sm) !important;
    color: var(--mute) !important;
}

.fi-section-header-text-ctn {
    gap: 2px !important;
    min-width: 0;
}

.fi-section-header > .fi-icon {
    color: var(--mute) !important;
}

/* ── Подвал секции ───────────────────────────────────────────────────────── */
.fi-section > .fi-section-content-ctn > .fi-section-footer {
    padding: calc(var(--section-pad, var(--pad)) * .75) var(--section-pad, var(--pad)) !important;
    border-top: 1px solid var(--line-soft) !important;
    background: var(--section-footer-bg, transparent) !important;
    border-bottom-left-radius: var(--radius);
    border-bottom-right-radius: var(--radius);
}

/* ── Вариант: сворачиваемая ──────────────────────────────────────────────── */
.fi-section.fi-collapsible > .fi-section-header {
    cursor: pointer;
    transition: background .12s;
}

.fi-section.fi-collapsible > .fi-section-header:hover {
    background: var(--hover) !important;
}

/* ── Вариант: компактная ─────────────────────────────────────────────────── */
.fi-section.fi-compact {
    border-radius: var(--radius-sm) !important;
}

.fi-section.fi-compact:not(.fi-aside) > .fi-section-header {
    padding: calc(var(--section-pad, var(--pad)) * .55) calc(var(--section-pad, var(--pad)) * .85) !important;
}

.fi-section.fi-compact:not(.fi-divided) > .fi-section-content-ctn > .fi-section-content {
    padding: calc(var(--section-pad, var(--pad)) * .85) !important;
}

.fi-section.fi-compact.fi-divided > .fi-section-content-ctn > .fi-section-content > * {
    padding: calc(var(--section-pad, var(--pad)) * .85) !important;
}

.fi-section.fi-compact > .fi-section-content-ctn > .fi-section-footer {
    padding: calc(var(--section-pad, var(--pad)) * .55) calc(var(--section-pad, var(--pad)) * .85) !important;
}

/* ── Вариант: второстепенная ─────────────────────────────────────────────── */
.fi-section.fi-secondary:not(.fi-aside) {
    background: var(--section-secondary-bg, var(--surface-2)) !important;
}

.fi-section.fi-secondary.fi-aside > .fi-section-content-ctn {
    background: var(--section-secondary-bg, var(--surface-2)) !important;
}

/* ── Вариант: с боковым заголовком ───────────────────────────────────────────
   Коробка съезжает с самой секции на контейнер содержимого: слева остаётся
   голый заголовок, справа — карточка. */
.fi-section.fi-aside {
    background: transparent !important;
    border: 0 !important;
    border-radius: 0 !important;
    box-shadow: none !important;
    gap: var(--grid-gap-y, 10px) var(--grid-gap-x, 16px) !important;
}

.fi-section.fi-aside:not(.fi-section-not-contained) > .fi-section-content-ctn {
    background: var(--section-bg, var(--surface)) !important;
    border: 1px solid var(--section-border, var(--line-soft)) !important;
    border-radius: var(--radius) !important;
    box-shadow: var(--section-shadow, var(--shadow-sm)) !important;
}

.fi-section.fi-aside.fi-compact > .fi-section-content-ctn {
    border-radius: var(--radius-sm) !important;
}

.fi-section.fi-aside > .fi-section-header {
    padding-inline: 0 !important;
    border-bottom: 0 !important;
}

/* ── Вариант: с разделителями ────────────────────────────────────────────── */
.fi-section.fi-divided > .fi-section-content-ctn > .fi-section-content > * + * {
    border-top: 1px solid var(--line-soft) !important;
}

.fi-section.fi-divided > .fi-section-content-ctn > .fi-section-content {
    gap: 0 !important;
}

/* ── Вариант: без контейнера ─────────────────────────────────────────────────
   Ни заливки, ни рамки, ни тени — только заголовок и его волосок. */
.fi-section.fi-section-not-contained {
    background: transparent !important;
    border: 0 !important;
    border-radius: 0 !important;
    box-shadow: none !important;
    row-gap: var(--grid-gap-y, 10px) !important;
}

.fi-section.fi-section-not-contained > .fi-section-content-ctn {
    row-gap: var(--grid-gap-y, 10px) !important;
}

.fi-section.fi-section-not-contained > .fi-section-header {
    padding-inline: 0 !important;
    padding-block: 0 0 calc(var(--section-pad, var(--pad)) * .5) !important;
}

.fi-section.fi-section-not-contained > .fi-section-content-ctn > .fi-section-content {
    padding: 0 !important;
}

.fi-section.fi-section-not-contained > .fi-section-content-ctn > .fi-section-footer {
    padding-inline: 0 !important;
}

/* ── Обёртка секции схемы (заголовок группы без коробки) ─────────────────── */
.fi-sc-section {
    gap: calc(var(--grid-gap-y, 10px) * .6) !important;
    min-width: 0;
}

.fi-sc-section-label-ctn {
    gap: 8px !important;
}

.fi-sc-section-label {
    font-size: var(--font-base) !important;
    font-weight: 600 !important;
    line-height: 1.45 !important;
    color: var(--ink) !important;
}

/* ── Набор полей ─────────────────────────────────────────────────────────── */
.fi-fieldset:not(.fi-fieldset-not-contained) {
    padding: var(--section-pad, var(--pad)) !important;
    border: 1px solid var(--fieldset-border, var(--line)) !important;
    border-radius: var(--radius) !important;
    background: var(--fieldset-bg, transparent) !important;
}

.fi-fieldset.fi-fieldset-not-contained {
    padding-top: var(--grid-gap-y, 10px) !important;
}

.fi-fieldset > legend {
    padding-inline: 6px !important;
    margin-inline-start: -6px;
    font-size: var(--font-base) !important;
    font-weight: 600 !important;
    line-height: 1.45 !important;
    color: var(--ink) !important;
}

.fi-fieldset > legend .fi-fieldset-label-required-mark {
    color: var(--bad) !important;
}

/* Подпись спрятана — верхний отступ под неё больше не нужен. */
.fi-fieldset.fi-fieldset-label-hidden.fi-fieldset-not-contained {
    padding-top: 0 !important;
}

.fi-sc-fieldset {
    min-width: 0;
}

/* ── Вкладки схемы ───────────────────────────────────────────────────────────
   Эталон: полоса вкладок без коробки, активная держится подчёркиванием
   (inset-тень 1.5px цветом --ink) и весом, неактивная — тише цветом. */
.fi-sc-tabs {
    min-width: 0;
}

.fi-sc-tabs > .fi-tabs {
    gap: 0 !important;
    padding: 0 !important;
    margin: 0 !important;
    background: transparent !important;
    border-radius: 0 !important;
    box-shadow: none !important;
    border-bottom: 1px solid var(--line) !important;
}

.fi-sc-tabs > .fi-tabs .fi-tabs-item {
    height: 28px;
    padding: 0 11px !important;
    border-radius: 0 !important;
    background: transparent !important;
    font-size: var(--font-base) !important;
    font-weight: 400 !important;
}

.fi-sc-tabs > .fi-tabs .fi-tabs-item .fi-tabs-item-label {
    color: var(--mute) !important;
}

.fi-sc-tabs > .fi-tabs .fi-tabs-item:hover .fi-tabs-item-label {
    color: var(--body) !important;
}

.fi-sc-tabs > .fi-tabs .fi-tabs-item.fi-active {
    font-weight: 500 !important;
    box-shadow: inset 0 -1.5px 0 0 var(--tab-active-underline, var(--ink)) !important;
}

.fi-sc-tabs > .fi-tabs .fi-tabs-item.fi-active .fi-tabs-item-label,
.fi-sc-tabs > .fi-tabs .fi-tabs-item.fi-active > .fi-icon {
    color: var(--tab-active-ink, var(--ink)) !important;
}

/* Вкладки, не влезшие в полосу, уезжают в выпадающий список. */
.fi-sc-tabs .fi-dropdown-list-item.fi-selected {
    background: var(--selected) !important;
    color: var(--ink) !important;
}

/* Панель вкладки. */
.fi-sc-tabs-tab.fi-active {
    margin-top: var(--grid-gap-y, 10px) !important;
}

.fi-sc-tabs.fi-contained {
    background: var(--section-bg, var(--surface)) !important;
    border: 1px solid var(--section-border, var(--line-soft)) !important;
    border-radius: var(--radius) !important;
    box-shadow: var(--section-shadow, var(--shadow-sm)) !important;
}

.fi-sc-tabs.fi-contained > .fi-tabs {
    padding: 4px 8px 0 !important;
    border-bottom: 1px solid var(--line-soft) !important;
}

.fi-sc-tabs.fi-contained > .fi-sc-tabs-tab.fi-active {
    margin-top: 0 !important;
    padding: var(--section-pad, var(--pad)) !important;
}

.fi-sc-tabs.fi-vertical > .fi-tabs {
    border-bottom: 0 !important;
    border-inline-end: 1px solid var(--line) !important;
    padding-inline-end: 6px !important;
}

.fi-sc-tabs.fi-vertical > .fi-tabs .fi-tabs-item {
    border-radius: var(--radius-sm) !important;
    box-shadow: none !important;
}

.fi-sc-tabs.fi-vertical > .fi-tabs .fi-tabs-item.fi-active {
    background: var(--selected) !important;
    box-shadow: none !important;
}

.fi-sc-tabs.fi-vertical > .fi-sc-tabs-tab.fi-active {
    margin-top: 0 !important;
    margin-inline-start: var(--grid-gap-x, 16px) !important;
}

/* ── Мастер ──────────────────────────────────────────────────────────────────
   Эталон, экран «Мастер»: шаги — четыре равные плитки в один ряд, зазор 2px,
   каждая 49px высотой, padding 6/10, радиус --radius-sm. Активная — заливка
   --selected и рамка --primary; пройденные и будущие — --surface-2 и --line,
   будущие вдобавок притушены. Шевроны-разделители в эталоне убраны. */
.fi-sc-wizard {
    min-width: 0;
}

.fi-sc-wizard .fi-sc-wizard-header {
    gap: 2px !important;
    padding: 0 !important;
    background: transparent !important;
    border: 0 !important;
    border-radius: 0 !important;
    box-shadow: none !important;
}

.fi-sc-wizard .fi-sc-wizard-header-step {
    flex: 1 1 0;
    min-width: 0;
}

.fi-sc-wizard .fi-sc-wizard-header-step-separator {
    display: none !important;
}

.fi-sc-wizard .fi-sc-wizard-header-step-btn {
    width: 100%;
    gap: 8px !important;
    padding: 6px 10px !important;
    border: 1px solid var(--step-border, var(--line)) !important;
    border-radius: var(--radius-sm) !important;
    background: var(--step-bg, var(--surface-2)) !important;
    transition: background .12s, border-color .12s;
}

.fi-sc-wizard .fi-sc-wizard-header-step:not(.fi-active):not(.fi-completed) .fi-sc-wizard-header-step-btn {
    opacity: .62;
}

.fi-sc-wizard .fi-sc-wizard-header-step-icon-ctn {
    width: 20px;
    height: 20px;
    flex: 0 0 20px;
    border: 0 !important;
    background: var(--step-marker-bg, var(--line-strong)) !important;
}

.fi-sc-wizard .fi-sc-wizard-header-step-icon-ctn .fi-icon {
    width: 12px;
    height: 12px;
    color: var(--on-primary) !important;
}

.fi-sc-wizard .fi-sc-wizard-header-step-number {
    font-size: var(--font-sm) !important;
    font-weight: 700 !important;
    color: var(--on-primary) !important;
}

.fi-sc-wizard .fi-sc-wizard-header-step-text {
    min-width: 0;
    max-width: none !important;
}

.fi-sc-wizard .fi-sc-wizard-header-step-label {
    font-size: var(--font-base) !important;
    font-weight: 600 !important;
    color: var(--ink) !important;
}

.fi-sc-wizard .fi-sc-wizard-header-step-description {
    font-size: var(--font-sm) !important;
    color: var(--mute) !important;
}

/* Текущий шаг. */
.fi-sc-wizard .fi-sc-wizard-header-step.fi-active .fi-sc-wizard-header-step-btn {
    background: var(--step-active-bg, var(--selected)) !important;
    border-color: var(--step-active-border, var(--primary)) !important;
}

.fi-sc-wizard .fi-sc-wizard-header-step.fi-active .fi-sc-wizard-header-step-icon-ctn {
    background: var(--primary) !important;
}

/* Пройденный шаг: галочка на заливке акцента, плитка спокойная. */
.fi-sc-wizard .fi-sc-wizard-header-step.fi-completed .fi-sc-wizard-header-step-btn {
    background: var(--surface) !important;
    border-color: var(--line) !important;
}

.fi-sc-wizard .fi-sc-wizard-header-step.fi-completed .fi-sc-wizard-header-step-icon-ctn {
    background: var(--primary) !important;
}

/* Недоступный шаг: и по классу, и по родному атрибуту кнопки. */
.fi-sc-wizard .fi-sc-wizard-header-step.fi-disabled .fi-sc-wizard-header-step-btn,
.fi-sc-wizard .fi-sc-wizard-header-step-btn:disabled {
    opacity: .45;
    cursor: not-allowed;
}

.fi-sc-wizard .fi-sc-wizard-header-step:not(.fi-disabled) .fi-sc-wizard-header-step-btn:not(:disabled):hover {
    border-color: var(--line-strong) !important;
}

/* Панель шага. */
.fi-sc-wizard:not(.fi-sc-wizard-header-hidden) .fi-sc-wizard-step.fi-active {
    margin-top: var(--grid-gap-y, 10px) !important;
}

.fi-sc-wizard .fi-sc-wizard-footer {
    gap: 8px !important;
    margin-top: var(--grid-gap-y, 10px) !important;
    padding-top: calc(var(--section-pad, var(--pad)) * .75) !important;
    border-top: 1px solid var(--line-soft) !important;
}

.fi-sc-wizard.fi-contained {
    background: var(--section-bg, var(--surface)) !important;
    border: 1px solid var(--section-border, var(--line-soft)) !important;
    border-radius: var(--radius) !important;
    box-shadow: var(--section-shadow, var(--shadow-sm)) !important;
}

.fi-sc-wizard.fi-contained .fi-sc-wizard-header {
    padding: 8px !important;
    border-bottom: 1px solid var(--line-soft) !important;
}

.fi-sc-wizard.fi-contained .fi-sc-wizard-step.fi-active {
    margin-top: 0 !important;
    padding: var(--section-pad, var(--pad)) !important;
}

.fi-sc-wizard.fi-contained .fi-sc-wizard-footer {
    margin-top: 0 !important;
    padding: calc(var(--section-pad, var(--pad)) * .75) var(--section-pad, var(--pad)) var(--section-pad, var(--pad)) !important;
}

/* ── Сетка схемы ─────────────────────────────────────────────────────────────
   Эталон: между полями 9–10px по вертикали и 14–16px по горизонтали.
   Родные 24px (gap-6) в плотной панели съедают экран. */
.fi-sc.fi-sc-has-gap {
    gap: var(--grid-gap-y, 10px) var(--grid-gap-x, 16px) !important;
}

.fi-sc.fi-sc-has-gap.fi-sc-dense {
    gap: var(--grid-gap-dense, 6px) !important;
}

/* Колонка сетки без min-width:0 распирается длинным содержимым, и грид
   выезжает за экран — это не гипотетика, а обычное поведение CSS Grid. */
.fi-grid,
.fi-grid-col {
    min-width: 0;
}

.fi-grid-col > .fi-sc-component {
    min-width: 0;
}

/* ── Флекс схемы ─────────────────────────────────────────────────────────── */
.fi-sc-flex {
    gap: var(--grid-gap-x, 16px) !important;
    min-width: 0;
}

.fi-sc-flex.fi-dense {
    gap: var(--grid-gap-dense, 6px) !important;
}

.fi-sc-flex > .fi-growable {
    min-width: 0;
}

/* ── Действия схемы ──────────────────────────────────────────────────────── */
.fi-sc-actions {
    gap: calc(var(--grid-gap-y, 10px) * .6) !important;
}

.fi-sc-actions-label-ctn {
    gap: 8px !important;
}

.fi-sc-actions-label {
    font-size: var(--font-base) !important;
    font-weight: 600 !important;
    line-height: 1.45 !important;
    color: var(--ink) !important;
}

/* Липкая панель действий — та же коробка, что и секция, но тень поповерная:
   панель лежит НАД содержимым и обязана от него отделяться. */
.fi-sc-actions.fi-sticky .fi-ac {
    padding: calc(var(--section-pad, var(--pad)) * .75) var(--section-pad, var(--pad)) !important;
    background: var(--section-bg, var(--surface)) !important;
    border: 1px solid var(--line) !important;
    border-radius: var(--radius) !important;
    box-shadow: var(--shadow) !important;
}

/* ── Слитая группа полей ─────────────────────────────────────────────────────
   Родная обводка — ring на gray-950/10, облику неподвластна. */
.fi-sc-fused-group > .fi-sc {
    box-shadow: 0 0 0 1px var(--line-strong) !important;
    border-radius: var(--radius) !important;
}

.fi-sc-fused-group > .fi-sc:focus-within {
    box-shadow: 0 0 0 2px var(--focus) !important;
}

.fi-sc-fused-group .fi-sc {
    border-radius: var(--radius) !important;
    border-color: var(--line) !important;
}

.fi-sc-fused-group .fi-sc > * + * {
    border-color: var(--line) !important;
}

.fi-sc-fused-group .fi-input-wrp {
    background: var(--surface) !important;
}

/* ── Заголовок страницы ──────────────────────────────────────────────────────
   Кегль и цвет `.fi-header-heading` уже заданы в admin-theme.css (и меняются
   по плотности) — здесь только то, чего там нет. */
.fi-header-subheading {
    margin-top: 4px !important;
    max-width: 72ch !important;
    font-size: var(--font-base) !important;
    line-height: 1.5 !important;
    color: var(--mute) !important;
}

/* ── Виджеты ─────────────────────────────────────────────────────────────────
   Свои виджеты (`bf-w*`) живут внутри `.fi-wi-widget` и здесь не трогаются:
   ниже — только родная обвязка. */
.fi-wi-widget {
    min-width: 0;
    /* Ячейка сетки тянется по самому высокому соседу, а сам виджет — нет:
       замер живой инфопанели дал ячейку 179px при виджете 158, и ряд карточек
       выходил рваным, будто их роняли по одной. Тянуться обязана вся цепочка. */
    height: 100%;
}

.fi-wi-widget > .fi-section {
    height: 100%;
}

/* Зазор сетки инфопанели. Дашборд печатается своим генератором и несёт
   `gap:16px` прямо в атрибуте `style` — перебить его может только `!important`.
   У эталона между карточками 8px, между полосами 10: 16 на четырёх колонках
   съедали ширину целой карточки. */
.fi-page-content > div:has(> div > .fi-wi-widget) {
    gap: var(--w-grid-gap, var(--d-w-grid-gap, 12px)) !important;
}

/* График: родной холст держит квадрат (aspect-square), и на инфопанели пончик
   вытягивал карточку вдвое выше соседей — замерено на живой панели. */
.fi-wi-chart .fi-wi-chart-canvas-ctn:not(.fi-wi-chart-canvas-ctn-no-aspect-ratio) {
    aspect-ratio: var(--chart-aspect, 1.9) !important;
}

/* Цвета графика Chart.js читает вычисленным `color` этих служебных узлов —
   через них облик достаёт до самой картинки. */
.fi-wi-chart .fi-wi-chart-grid-color {
    color: var(--line) !important;
}

.fi-wi-chart .fi-wi-chart-text-color {
    color: var(--mute) !important;
}

/* `.fi-color` сидит на самом холсте (`->color()` на виджете) — у явно
   покрашенного графика свой цвет не отбираем. */
.fi-wi-chart .fi-wi-chart-canvas-ctn:not(.fi-color) .fi-wi-chart-border-color {
    color: var(--primary) !important;
}

.fi-wi-chart .fi-wi-chart-canvas-ctn:not(.fi-color) .fi-wi-chart-bg-color {
    color: var(--primary-soft) !important;
}

.fi-wi-chart .fi-wi-chart-filter-content {
    gap: var(--grid-gap-y, 10px) !important;
    padding: var(--section-pad, var(--pad)) !important;
}

.fi-wi-chart .fi-wi-chart-filter-content-actions-ctn {
    gap: 8px !important;
}

/* ============================================================================
   НОВЫЕ ТОКЕНЫ (значения в :root не пишу — сводит их владелец словаря)

   --section-bg        заливка секции/карточки.       светлая var(--surface)      тёмная var(--surface)
   --section-border    цвет рамки секции; transparent → «лист без рамки».
                                                      светлая var(--line-soft)    тёмная var(--line)
   --section-shadow    тень секции; none → плоская коробка.
                                                      светлая var(--shadow-sm)    тёмная var(--shadow-sm)
   --section-pad       внутренний отступ секции и производных поверхностей
                       (подвал, панель вкладки, шаг мастера, набор полей).
                                                      светлая 12px                тёмная 12px
   --section-secondary-bg  заливка второстепенной секции (.fi-secondary).
                                                      светлая var(--surface-2)    тёмная var(--surface-2)
   --section-footer-bg заливка подвала секции.        светлая transparent         тёмная transparent
   --fieldset-border   рамка набора полей.            светлая var(--line)         тёмная var(--line)
   --fieldset-bg       заливка набора полей.          светлая transparent         тёмная transparent
   --tab-active-underline  цвет подчёркивания активной вкладки схемы.
                                                      светлая var(--ink)          тёмная var(--ink)
   --tab-active-ink    цвет надписи активной вкладки. светлая var(--ink)          тёмная var(--ink)
   --step-bg           заливка плитки шага мастера.   светлая var(--surface-2)    тёмная var(--surface-2)
   --step-border       рамка плитки шага мастера.     светлая var(--line)         тёмная var(--line)
   --step-active-bg    заливка текущего шага.         светлая var(--selected)     тёмная var(--selected)
   --step-active-border рамка текущего шага.          светлая var(--primary)      тёмная var(--primary)
   --step-marker-bg    кружок номера непройденного шага.
                                                      светлая var(--line-strong)  тёмная var(--line-strong)
   --grid-gap-x        зазор между колонками сетки схемы.  светлая 16px           тёмная 16px
   --grid-gap-y        зазор между строками сетки схемы.   светлая 10px           тёмная 10px
   --grid-gap-dense    зазор в плотном режиме (.fi-sc-dense / .fi-dense).
                                                      светлая 6px                 тёмная 6px
   --chart-aspect      соотношение сторон холста графика (ширина/высота).
                                                      светлая 1.9                 тёмная 1.9
   ============================================================================ */

/* Промежуток внутри секции — один хозяин, значение приходит извне: уровень
   плотности даёт запасное, характер вправе назвать своё. Раньше это было
   правилом в блоке плотности и весом класса било любой облик. */
.fi-section-content {
  gap: var(--section-gap, var(--d-section-gap, 10px)) !important;
}


/* ── часть: navigation.css ─────────────────────── */
/* ============================================================================
   Навигация и всплывающее — на словаре обликов.

   Что здесь: боковое меню (шапка, пункты, подвал, переключатель темы), меню
   пользователя, выпадающие меню, вкладки, подчинённая навигация, пагинация,
   аватар. Ни одного значения — только имена токенов.

   Что НЕ здесь, потому что уже стоит в `admin-theme.css` и не переписывается:
   геометрия рельса (`.fi-sidebar-nav` padding, отступы групп), базовые отступы
   пункта меню и три уровня плотности (`body.bf-density-*`), типографика
   `.fi-sidebar-group-label`, поля полосы вкладок кластера. Оттуда берётся
   РАЗМЕР, отсюда — ЦВЕТ и ФОРМА активного состояния.

   Две оси характера, ради которых файл и заведён:
   · вкладка активна подчёркиванием / пилюлей / сегментом —
     `--tabs-bg` + `--tab-active-bg` + `--tab-active-underline` + `--tab-radius`;
   · пункт бокового меню активен подложкой / полосой слева —
     `--nav-active-bg` + `--nav-active-bar`.
   Оба состояния рисуются ОДНИМ набором правил; характер меняет значения, а не
   правила. Значения — в конце файла отдельным блоком.

   Правила специально начинаются с родителя (`.fi-sidebar …`, `.fi-pagination …`):
   у Filament тёмная тема компилируется в `.dark .fi-…`, то есть на класс
   специфичнее светлой, и без этого запаса половина цветов чинилась бы только
   `!important`.
   ============================================================================ */

/* ── Боковое меню: поверхность рельса ──────────────────────────────────────
   У словаря под боковую панель заведена своя пара поверхность/текст
   (`--rail`, `--rail-ink`, `--rail-mute`, `--rail-active`) — рельс имеет право
   отличаться от карточек, и в половине характеров он темнее полотна. Тема до
   сих пор красила его в `--surface`, и эта грань характера просто не работала. */
.fi-sidebar,
.fi-main-sidebar {
  background: var(--rail) !important;
  border-right: 1px solid var(--line) !important;
}
.fi-sidebar-header {
  background: var(--rail) !important;
  border-bottom: 1px solid var(--line-soft) !important;
  box-shadow: none !important;
  justify-content: flex-start !important;
  gap: 8px;
  padding-inline: var(--pad) !important;
}
.fi-sidebar-header-logo-ctn { min-width: 0; }

/* Логотип. Filament ставит 20px жирным — на рельсе шириной в 206px это спорит
   с первым пунктом меню за внимание. Название приложения не заголовок экрана. */
.fi-logo {
  align-items: center;
  color: var(--ink) !important;
  font-size: var(--font-base) !important;
  font-weight: 600 !important;
  letter-spacing: 0 !important;
  line-height: 1.2;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ── Боковое меню: пункты ──────────────────────────────────────────────────
   Подчинённая навигация страницы (`.fi-page-sub-navigation-sidebar`) собрана
   из ТЕХ ЖЕ классов пункта, но лежит не внутри `.fi-sidebar` — поэтому каждый
   селектор ниже перечисляет обе площадки. Пропустишь вторую — на карточке с
   вкладками-сбоку останется фабричный Filament. */
.fi-sidebar .fi-sidebar-group-label,
.fi-page-sub-navigation-sidebar .fi-sidebar-group-label {
  color: var(--rail-mute) !important;
  font-size: var(--font-sm) !important;
  font-weight: 600 !important;
  letter-spacing: 0 !important;
  text-transform: none !important;
}
.fi-sidebar .fi-sidebar-group-btn .fi-icon,
.fi-page-sub-navigation-sidebar .fi-sidebar-group-btn .fi-icon {
  color: var(--rail-mute) !important;
}
.fi-sidebar .fi-sidebar-item-btn,
.fi-page-sub-navigation-sidebar .fi-sidebar-item-btn {
  border-radius: var(--radius-sm) !important;
  color: var(--rail-ink) !important;
  font-size: var(--font-base) !important;
  transition: background-color .12s, color .12s, box-shadow .12s;
}
.fi-sidebar .fi-sidebar-item-label,
.fi-page-sub-navigation-sidebar .fi-sidebar-item-label {
  color: inherit !important;
  font-size: var(--font-base) !important;
}
/* Иконку в v5 зовут `.fi-icon` прямым потомком, но живая сгенерированная
   админка отдаёт ещё и `.fi-sidebar-item-icon` — версии панели расходятся,
   поэтому названы обе. */
.fi-sidebar .fi-sidebar-item-btn > .fi-icon,
.fi-sidebar .fi-sidebar-item-icon,
.fi-page-sub-navigation-sidebar .fi-sidebar-item-btn > .fi-icon,
.fi-page-sub-navigation-sidebar .fi-sidebar-item-icon {
  color: var(--rail-mute) !important;
  transition: color .12s;
}
.fi-sidebar .fi-sidebar-item.fi-sidebar-item-has-url > .fi-sidebar-item-btn:hover,
.fi-sidebar .fi-sidebar-item.fi-sidebar-item-has-url > .fi-sidebar-item-btn:focus-visible,
.fi-page-sub-navigation-sidebar .fi-sidebar-item.fi-sidebar-item-has-url > .fi-sidebar-item-btn:hover,
.fi-page-sub-navigation-sidebar .fi-sidebar-item.fi-sidebar-item-has-url > .fi-sidebar-item-btn:focus-visible {
  background: var(--rail-active) !important;
  color: var(--ink) !important;
}
.fi-sidebar .fi-sidebar-item.fi-sidebar-item-has-url > .fi-sidebar-item-btn:hover > .fi-icon,
.fi-sidebar .fi-sidebar-item.fi-sidebar-item-has-url > .fi-sidebar-item-btn:hover .fi-sidebar-item-icon,
.fi-page-sub-navigation-sidebar .fi-sidebar-item.fi-sidebar-item-has-url > .fi-sidebar-item-btn:hover > .fi-icon {
  color: var(--rail-ink) !important;
}
.fi-sidebar .fi-sidebar-group-dropdown-trigger-btn:hover,
.fi-sidebar .fi-sidebar-group-dropdown-trigger-btn:focus-visible {
  background: var(--rail-active) !important;
  border-radius: var(--radius-sm) !important;
}

/* ОСЬ ХАРАКТЕРА: активный пункт. Подложка и полоса слева — независимые слои.
   Характер, который живёт полосой, гасит подложку (`--nav-active-bg:
   transparent`), характер с подложкой гасит полосу (`--nav-active-bar:
   transparent`); третий берёт оба. Правило одно на все случаи. */
.fi-sidebar .fi-sidebar-item.fi-active > .fi-sidebar-item-btn,
.fi-page-sub-navigation-sidebar .fi-sidebar-item.fi-active > .fi-sidebar-item-btn {
  background: var(--nav-active-bg, var(--rail-active)) !important;
  box-shadow: inset 2px 0 0 var(--nav-active-bar, transparent) !important;
  color: var(--nav-active-ink, var(--ink)) !important;
  font-weight: 600 !important;
}
.fi-sidebar .fi-sidebar-item.fi-active > .fi-sidebar-item-btn > .fi-icon,
.fi-sidebar .fi-sidebar-item.fi-active > .fi-sidebar-item-btn .fi-sidebar-item-icon,
.fi-sidebar .fi-sidebar-item.fi-active > .fi-sidebar-item-btn > .fi-sidebar-item-label,
.fi-page-sub-navigation-sidebar .fi-sidebar-item.fi-active > .fi-sidebar-item-btn > .fi-icon,
.fi-page-sub-navigation-sidebar .fi-sidebar-item.fi-active > .fi-sidebar-item-btn > .fi-sidebar-item-label {
  color: var(--nav-active-ink, var(--ink)) !important;
}
/* Точка-маркер вложенного пункта: у активного она того же цвета, что и полоса,
   иначе на характере без подложки активный ребёнок ничем не отличается. */
.fi-sidebar .fi-sidebar-item.fi-active > .fi-sidebar-item-btn .fi-sidebar-item-grouped-border-part,
.fi-page-sub-navigation-sidebar .fi-sidebar-item.fi-active > .fi-sidebar-item-btn .fi-sidebar-item-grouped-border-part {
  background: var(--nav-active-ink, var(--ink)) !important;
}
.fi-sidebar .fi-sidebar-item-grouped-border-part {
  background: var(--rail-mute) !important;
}
.fi-sidebar .fi-sidebar-item-grouped-border-part-not-first,
.fi-sidebar .fi-sidebar-item-grouped-border-part-not-last {
  background: var(--line) !important;
}
.fi-sidebar .fi-sidebar-item.fi-active > .fi-sidebar-item-btn .fi-sidebar-item-grouped-border-part-not-first,
.fi-sidebar .fi-sidebar-item.fi-active > .fi-sidebar-item-btn .fi-sidebar-item-grouped-border-part-not-last {
  background: var(--line) !important;
}

/* Колокольчик уведомлений в рельсе — тот же пункт меню, только кнопкой. */
.fi-sidebar .fi-sidebar-database-notifications-btn {
  border-radius: var(--radius-sm) !important;
  color: var(--rail-ink) !important;
  font-size: var(--font-base) !important;
}
.fi-sidebar .fi-sidebar-database-notifications-btn:hover,
.fi-sidebar .fi-sidebar-database-notifications-btn:focus-visible {
  background: var(--rail-active) !important;
}
.fi-sidebar .fi-sidebar-database-notifications-btn-label {
  color: inherit !important;
  font-size: var(--font-base) !important;
}
.fi-sidebar .fi-sidebar-database-notifications-btn > .fi-icon {
  color: var(--rail-mute) !important;
}

/* ── Подвал рельса ─────────────────────────────────────────────────────────
   Filament отбивает подвал полями (`mx-4 my-3`) и он висит в воздухе. Подвал —
   низ рельса: линия сверху, поля как у пунктов. */
.fi-sidebar-footer {
  border-top: 1px solid var(--line-soft);
  margin: 0 !important;
  padding: 8px var(--pad) !important;
  row-gap: 8px !important;
}

/* ── Длинная подпись не рвёт панель ────────────────────────────────────────
   Подвал — колоночный flex, и ребёнок в нём не может стать уже своей
   МИНИМАЛЬНОЙ ширины. Подпись «Открыть уведомления 1 · Администратор» не
   переносится, её min-content выходит 231px при подвале в 205 — и кнопки
   вылезают за панель прямо на содержимое страницы.

   ЖИВОЙ ЗАМЕР 10.09.2026, заказ cookie: 38px наружу, и НЕ вспышка — держится
   и через три секунды (у credus подписи короче, и там было впору: −6px).
   Обход нашёл это на десятке экранов подряд.

   `min-width: 0` возвращает детям право сжиматься, подписи получают многоточие.
   Обрезаем ТОЛЬКО текст: `overflow` на самом выпадающем меню спрятал бы его
   список при открытии. Проверено живьём — меню открывается так же, как и без
   правила. */
.fi-sidebar-footer > *,
.fi-sidebar-footer .fi-user-menu-trigger,
.fi-sidebar-footer .fi-sidebar-database-notifications-btn,
.fi-sidebar-footer button,
.fi-sidebar-footer a {
  min-width: 0;
  max-width: 100%;
}
.fi-sidebar-footer .fi-user-menu-trigger-text,
.fi-sidebar-footer .fi-btn-label,
.fi-sidebar-footer .fi-sidebar-item-label {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ── Меню пользователя ─────────────────────────────────────────────────── */
.fi-sidebar .fi-user-menu-trigger {
  border-radius: var(--radius-sm) !important;
  color: var(--rail-ink) !important;
  font-size: var(--font-base) !important;
  padding: 5px 6px !important;
  transition: background-color .12s;
}
.fi-sidebar .fi-user-menu-trigger:hover,
.fi-sidebar .fi-user-menu-trigger:focus-visible {
  background: var(--rail-active) !important;
}
.fi-sidebar .fi-user-menu-trigger .fi-icon {
  color: var(--rail-mute) !important;
}
.fi-user-menu-trigger-text {
  color: var(--ink) !important;
  font-size: var(--font-base) !important;
  font-weight: 500 !important;
  line-height: 1.3;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.fi-topbar .fi-user-menu-trigger {
  border-radius: 50%;
}
.fi-user-menu .fi-dropdown-header {
  color: var(--ink) !important;
}

/* ── Аватар ────────────────────────────────────────────────────────────────
   Аватар приходит картинкой со светлой подложкой и на белой поверхности
   растворяется по краю. Волосяная обводка тем же цветом, что и линии таблицы,
   возвращает ему границу и в светлой, и в тёмной теме. */
.fi-avatar {
  background-color: var(--neutral-soft);
  border-radius: var(--radius-sm) !important;
  box-shadow: 0 0 0 1px var(--line);
  object-fit: cover;
}
.fi-avatar.fi-circular {
  border-radius: 50% !important;
}
.fi-user-avatar,
.fi-tenant-avatar {
  background-color: var(--primary-soft);
  flex: none;
}

/* ── Переключатель темы ───────────────────────────────────────────────────
   Три кнопки подряд, и обычно их видно только на подвале рельса. Активная
   отмечается фирменным цветом на выделенной подложке — тем же способом, что и
   активная страница пагинации, чтобы «выбрано» читалось одинаково везде. */
.fi-theme-switcher {
  gap: 2px;
}
.fi-theme-switcher-btn {
  border-radius: var(--radius-sm) !important;
  color: var(--rail-mute) !important;
  padding: 5px !important;
  transition: background-color .12s, color .12s;
}
.fi-theme-switcher-btn:hover,
.fi-theme-switcher-btn:focus-visible {
  background: var(--rail-active) !important;
  color: var(--rail-ink) !important;
}
.fi-theme-switcher-btn.fi-active {
  background: var(--selected) !important;
  color: var(--primary) !important;
}

/* ── Выпадающее меню ──────────────────────────────────────────────────────
   Панель Filament рисует обводку кольцом (`ring-1`), то есть тем же
   `box-shadow`, которым мы ставим тень — одно затирает другое. Поэтому граница
   тут РАМКОЙ, а тень остаётся тенью (та же мина, что была с полями ввода). */
.fi-dropdown-trigger {
  border-radius: var(--radius-sm);
}
.fi-dropdown-panel {
  background: var(--surface) !important;
  border: 1px solid var(--line) !important;
  border-radius: var(--radius) !important;
  box-shadow: var(--shadow) !important;
  color: var(--body);
  padding-block: 4px;
}
/* Разделители между секциями панели (Filament делит их `divide-y`). */
.fi-dropdown-panel:not(.fi-dropdown-list) > :not([hidden]) ~ :not([hidden]) {
  border-color: var(--line-soft) !important;
}
.fi-dropdown-list {
  gap: 1px;
  padding: 3px;
}
.fi-dropdown-list-item {
  border-radius: var(--radius-sm) !important;
  column-gap: 8px;
  font-size: var(--font-base) !important;
  padding: 5px 9px !important;
  transition: background-color .1s, color .1s;
}
.fi-dropdown-list-item:not(.fi-color) .fi-dropdown-list-item-label,
.fi-dropdown-list-item.fi-color-gray .fi-dropdown-list-item-label {
  color: var(--body) !important;
}
.fi-dropdown-list-item > .fi-icon {
  color: var(--mute) !important;
}
.fi-dropdown-list-item:not(.fi-disabled):not([disabled]):hover,
.fi-dropdown-list-item:not(.fi-disabled):not([disabled]):focus-visible {
  background: var(--hover) !important;
}
.fi-dropdown-list-item:not(.fi-disabled):not([disabled]).fi-selected {
  background: var(--selected) !important;
}
/* Отключённый пункт: Filament гасит его прозрачностью, и вместе с текстом
   выцветает иконка и бейдж — пункт становится грязным пятном. Гасим ЦВЕТОМ,
   тем же `--faint`, каким в эталоне помечена недоступная вкладка. */
.fi-dropdown-list-item.fi-disabled,
.fi-dropdown-list-item[disabled] {
  opacity: 1 !important;
}
.fi-dropdown-list-item.fi-disabled .fi-dropdown-list-item-label,
.fi-dropdown-list-item[disabled] .fi-dropdown-list-item-label,
.fi-dropdown-list-item.fi-disabled > .fi-icon,
.fi-dropdown-list-item[disabled] > .fi-icon {
  color: var(--faint) !important;
}
/* Цветные пункты (чаще всего «Удалить» в меню строки) переводятся на словарь:
   иначе половина меню одевается характером, а половина остаётся в палитре
   Filament — и расходятся они там, где заметнее всего. */
.fi-dropdown-list-item.fi-color-danger .fi-dropdown-list-item-label,
.fi-dropdown-list-item.fi-color-danger > .fi-icon {
  color: var(--bad) !important;
}
.fi-dropdown-list-item.fi-color-danger:not(.fi-disabled):not([disabled]):hover,
.fi-dropdown-list-item.fi-color-danger:not(.fi-disabled):not([disabled]):focus-visible {
  background: color-mix(in srgb, var(--bad) 12%, transparent) !important;
}
.fi-dropdown-list-item.fi-color-primary .fi-dropdown-list-item-label,
.fi-dropdown-list-item.fi-color-primary > .fi-icon {
  color: var(--primary) !important;
}
.fi-dropdown-list-item.fi-color-success .fi-dropdown-list-item-label,
.fi-dropdown-list-item.fi-color-success > .fi-icon {
  color: var(--ok) !important;
}
.fi-dropdown-list-item.fi-color-warning .fi-dropdown-list-item-label,
.fi-dropdown-list-item.fi-color-warning > .fi-icon {
  color: var(--warn) !important;
}
.fi-dropdown-list-item.fi-color-info .fi-dropdown-list-item-label,
.fi-dropdown-list-item.fi-color-info > .fi-icon {
  color: var(--info) !important;
}
.fi-dropdown-list-item-image {
  box-shadow: 0 0 0 1px var(--line);
}
.fi-dropdown-list-item-badge-placeholder {
  color: var(--faint) !important;
}
.fi-dropdown-list-item .fi-badge {
  font-size: var(--font-sm) !important;
}
/* Заголовок секции меню: та же роль, что у названия группы в рельсе, — значит
   и выглядеть обязан так же, иначе в панели окажется два разных «тихих» текста. */
.fi-dropdown-header {
  color: var(--faint) !important;
  font-size: var(--font-sm) !important;
  font-weight: 600 !important;
  padding: 7px 9px !important;
}
.fi-dropdown-header > span {
  color: var(--faint) !important;
}
.fi-dropdown-header .fi-icon {
  color: var(--faint) !important;
}

/* ── Вкладки ──────────────────────────────────────────────────────────────
   Две раскладки Filament: «карточка» (полоса на своей подложке, ею живут
   вкладки кластера) и `.fi-contained` (полоса, прижатая к линии-подложке).
   Обе обслуживаются одними и теми же токенами. */
.fi-tabs {
  gap: 2px;
}
.fi-tabs:not(.fi-contained) {
  background: var(--tabs-bg, var(--surface)) !important;
  border: 1px solid var(--line) !important;
  border-radius: var(--radius) !important;
  box-shadow: var(--shadow-sm) !important;
  padding: 3px !important;
}
/* У прижатой раскладки подчёркивание активной вкладки обязано лечь НА линию
   снизу — значит нижнего внутреннего отступа у полосы быть не должно. */
/* `--tabs-bg` сюда не приходит намеренно: прижатая полоса лежит на полотне
   страницы, и подложка у неё — само полотно. Иначе характер, одевший полосу
   карточкой, залил бы фоном ещё и линию под шапкой раздела. */
.fi-tabs.fi-contained {
  background: transparent !important;
  border-bottom: 1px solid var(--line) !important;
  padding: 0 8px !important;
}
.fi-tabs.fi-vertical:not(.fi-contained) {
  padding: 3px !important;
}
.fi-tabs-item {
  border-radius: var(--tab-radius, var(--radius-sm)) !important;
  color: var(--mute) !important;
  column-gap: 6px;
  font-size: var(--font-base) !important;
  font-weight: 500 !important;
  padding: 5px 10px !important;
  transition: background-color .12s, box-shadow .12s, color .12s;
}
.fi-tabs-item .fi-tabs-item-label {
  color: var(--mute) !important;
}
.fi-tabs-item > .fi-icon {
  color: var(--faint) !important;
}
.fi-tabs-item:not(.fi-active):hover,
.fi-tabs-item:not(.fi-active):focus-visible {
  background: var(--hover) !important;
}
.fi-tabs-item:not(.fi-active):hover .fi-tabs-item-label,
.fi-tabs-item:not(.fi-active):focus-visible .fi-tabs-item-label {
  color: var(--body) !important;
}
/* ОСЬ ХАРАКТЕРА: активная вкладка. Подложка и подчёркивание — независимые
   слои, как у пункта меню. Подчёркиванию достаточно погасить `--tab-active-bg`,
   пилюле — `--tab-active-underline` и задать круглый `--tab-radius`, сегменту —
   развести `--tabs-bg` и `--tab-active-bg` по разным поверхностям. */
.fi-tabs-item.fi-active {
  background: var(--tab-active-bg, var(--selected)) !important;
  box-shadow: inset 0 -2px 0 var(--tab-active-underline, transparent) !important;
  color: var(--tab-active-ink, var(--ink)) !important;
  font-weight: 600 !important;
}
.fi-tabs-item.fi-active .fi-tabs-item-label,
.fi-tabs-item.fi-active > .fi-icon {
  color: var(--tab-active-ink, var(--ink)) !important;
}
.fi-tabs-item-badge-placeholder {
  color: var(--faint) !important;
}
.fi-tabs-item .fi-badge {
  font-size: var(--font-sm) !important;
}

/* ── Подчинённая навигация страницы ───────────────────────────────────────
   Боковой вариант: 288px под пять пунктов — это ширина, отнятая у данных.
   Вкладочный вариант поля и ширину уже получил в `admin-theme.css`; здесь
   только то, чего там нет. */
.fi-page-sub-navigation-sidebar-ctn {
  width: 208px !important;
}
.fi-page-sub-navigation-sidebar {
  gap: 14px !important;
}
.fi-page-sub-navigation-tabs {
  border-radius: var(--radius) !important;
}
/* Группа вкладок, раскрывающаяся меню: её триггер — та же вкладка, и активной
   она бывает так же. Правила выше её уже красят, здесь снимается только
   лишняя обводка фокуса поверх подложки. */
.fi-page-sub-navigation-tabs .fi-dropdown-trigger {
  border-radius: var(--tab-radius, var(--radius-sm));
}

/* ── Пагинация ────────────────────────────────────────────────────────────
   Filament собирает страницы в группу с кольцом-обводкой; кольцо — снова
   `box-shadow`, поэтому граница рамкой, а скругление отдаётся контейнеру
   (`overflow: hidden`), чтобы не считать углы каждой кнопке. */
.fi-pagination {
  column-gap: 10px;
  font-size: var(--font-sm);
}
.fi-pagination .fi-pagination-overview {
  color: var(--mute) !important;
  font-size: var(--font-sm) !important;
  font-weight: 400 !important;
}
.fi-pagination .fi-pagination-items {
  background: var(--surface) !important;
  border: 1px solid var(--line) !important;
  border-radius: var(--radius-sm) !important;
  box-shadow: none !important;
  overflow: hidden;
}
.fi-pagination .fi-pagination-item {
  border-color: var(--line) !important;
}
.fi-pagination .fi-pagination-item-btn {
  border-radius: 0 !important;
  color: var(--body) !important;
  padding: 3px 4px !important;
  transition: background-color .12s, color .12s;
}
.fi-pagination .fi-pagination-item-label {
  color: var(--body) !important;
  font-size: var(--font-sm) !important;
  font-weight: 600 !important;
  padding-inline: 5px !important;
}
.fi-pagination .fi-pagination-item-icon,
.fi-pagination .fi-pagination-item-btn .fi-icon {
  color: var(--mute) !important;
}
.fi-pagination .fi-pagination-item-btn:enabled:hover,
.fi-pagination .fi-pagination-item-btn:enabled:focus-visible {
  background: var(--hover) !important;
}
/* Текущая страница залита фирменным цветом — это единственное место списка,
   где «здесь я сейчас» должно читаться без счёта. Пара `--on-primary` тут
   обязательна: на светлом бренде белая цифра проваливается по контрасту. */
.fi-pagination .fi-pagination-item.fi-active .fi-pagination-item-btn {
  background: var(--primary) !important;
  color: var(--on-primary) !important;
}
.fi-pagination .fi-pagination-item.fi-active .fi-pagination-item-label,
.fi-pagination .fi-pagination-item.fi-active .fi-pagination-item-btn .fi-icon {
  color: var(--on-primary) !important;
}
.fi-pagination .fi-pagination-item.fi-active .fi-pagination-item-btn:enabled:hover {
  background: var(--primary-hover) !important;
}
.fi-pagination .fi-pagination-item.fi-disabled .fi-pagination-item-btn {
  cursor: default;
}
.fi-pagination .fi-pagination-item.fi-disabled .fi-pagination-item-label,
.fi-pagination .fi-pagination-item.fi-disabled .fi-icon {
  color: var(--faint) !important;
}
.fi-pagination .fi-pagination-previous-btn,
.fi-pagination .fi-pagination-next-btn {
  border-radius: var(--radius-sm) !important;
  font-size: var(--font-sm) !important;
}
/* Селектор «строк на странице». В эталоне он единственный на полосе с рамкой:
   поле ввода заливкой, а выпадающий список — рамкой, иначе их не различить. */
.fi-pagination .fi-pagination-records-per-page-select .fi-input-wrp {
  background: var(--surface) !important;
  border: 1px solid var(--line-strong) !important;
  border-radius: var(--radius-sm) !important;
  box-shadow: none !important;
}
.fi-pagination .fi-pagination-records-per-page-select .fi-select-input {
  color: var(--body) !important;
  font-size: var(--font-sm) !important;
  padding-block: 2px !important;
}

/* ============================================================================
   НОВЫЕ ТОКЕНЫ этой группы. Значения в `:root` намеренно не пишутся — словарь
   сводится в одном месте. Ниже: смысл и предлагаемое умолчание (светлая /
   тёмная). Умолчания подобраны под характер 01 «учётный плотный»: вкладка
   подчёркиванием, пункт меню подложкой.

   --tabs-bg             подложка ПОЛОСЫ вкладок; ею характер выбирает раскладку:
                         `transparent` — вкладки лежат прямо на полотне,
                         `--surface` — карточкой, `--surface-2` — сегментами.
                         светлая: transparent · тёмная: transparent

   --tab-active-bg       заливка активной вкладки. `transparent` — характер
                         живёт подчёркиванием; `--selected` — пилюлей;
                         `--surface` в паре с `--tabs-bg: --surface-2` — сегментом.
                         светлая: transparent · тёмная: transparent

   --tab-active-underline  цвет полосы под активной вкладкой (2px, внутрь).
                         `transparent` = характер без подчёркивания.
                         светлая: var(--ink) · тёмная: var(--ink)

   --tab-active-ink      цвет надписи и иконки активной вкладки.
                         светлая: var(--ink) · тёмная: var(--ink)

   --tab-radius          радиус вкладки: 0 — подчёркивание, var(--radius-sm) —
                         сегмент, 999px — пилюля.
                         светлая: 0 · тёмная: 0

   --nav-active-bg       заливка активного пункта бокового меню.
                         `transparent` = характер живёт только полосой слева.
                         светлая: var(--rail-active) · тёмная: var(--rail-active)

   --nav-active-bar      цвет полосы слева у активного пункта (2px, внутрь).
                         `transparent` = характер без полосы.
                         светлая: transparent · тёмная: transparent

   --nav-active-ink      цвет надписи и иконки активного пункта. Отдельно от
                         `--ink`: характер с фирменной подложкой красит активный
                         пункт в `--primary`, характер с серой — в `--ink`.
                         светлая: var(--ink) · тёмная: var(--ink)
   ============================================================================ */


/* ── часть: table.css ─────────────────────── */
/* ============================================================================
   ТАБЛИЦА — часть словаря обликов.

   Контейнер, строка, ячейка, шапка колонки, заголовок группы, итог и тулбар уже
   покрыты в `admin-theme.css` — здесь их НЕ повторяем. Здесь то, чего там нет:
   колонки-элементы (иконка/картинка/тумблер/селект/флажок/цвет/поле ввода),
   раскладки колонок, отбор строк, фильтры, менеджер колонок, поиск, пустое
   состояние, действия строки и состояния сортировки. Плюс ось, по которой
   характеры расходятся сильнее всего, — ХАРАКТЕР СТРОКИ.

   Ось строки. Реестр бывает зеброй, бывает с волоском-разделителем, бывает без
   разделителя вовсе; наведение бывает заливкой, бывает полосой слева, бывает
   и тем и другим. Все четыре варианта здесь переключаются ЗНАЧЕНИЯМИ
   (`--row-stripe`, `--row-separator`, `--row-hover-bg`, `--row-hover-bar`), а не
   правкой правил. Ни одно правило ниже конкретного значения не знает.

   Значения токенов сводятся в один блок в `admin-theme.css` — в конце файла
   перечень новых имён со смыслом и значением по умолчанию для света и тьмы.
   ============================================================================ */

/* ── Ось характера: строка ─────────────────────────────────────────────────
   Зебра. Работает и без флага `->striped()` в PHP: полосатость — свойство
   характера, а не конкретной таблицы. Заголовки групп и итоговые строки из
   чередования исключены — они и так со своим фоном.
   `--row-stripe: transparent` = зебры нет; тот же токен гасит и `->striped()`,
   чтобы одна таблица не спорила с обликом всей панели. */
.fi-ta-table > tbody > .fi-ta-row:nth-child(even):not(.fi-ta-group-header-row):not(.fi-ta-summary-row) {
    background-color: var(--row-stripe);
}
.fi-ta-table > tbody > .fi-ta-row.fi-striped {
    background-color: var(--row-stripe) !important;
}

/* Разделитель. `--row-separator: transparent` = строки без волоска (характеры,
   которые держат ритм воздухом, а не линиями). Специфичность выше, чем у
   базового правила темы, — файл выигрывает независимо от порядка подключения. */
.fi-ta-table .fi-ta-row:not(:last-child) > .fi-ta-cell {
    border-bottom: var(--row-separator-w) solid var(--row-separator) !important;
}

/* Наведение. Заливка и полоса слева — независимые ручки: характер включает одну,
   другую или обе. */
.fi-ta-table .fi-ta-row:hover,
.dark .fi-ta-table .fi-ta-row:hover {
    background-color: var(--row-hover-bg) !important;
}
.fi-ta-table .fi-ta-row > .fi-ta-cell:first-child {
    transition: box-shadow .12s ease;
}
.fi-ta-table .fi-ta-row:hover > .fi-ta-cell:first-child {
    box-shadow: inset var(--row-hover-bar-w) 0 0 0 var(--row-hover-bar);
}

/* ── Отбор строк ───────────────────────────────────────────────────────────
   Выбранная строка. Filament рисует метку слева через `::before` у первой
   ячейки — оставляем механику, забираем цвет и толщину. */
.fi-ta-table .fi-ta-row.fi-selected,
.fi-ta-table .fi-ta-row.fi-selected:not(.fi-striped) {
    background-color: var(--row-selected-bg) !important;
}
/* Наведение на уже выбранную не должно её «сбрасывать» обратно в обычный фон:
   подмешиваем чернила, поэтому в светлой теме темнеет, а в тёмной светлеет. */
.fi-ta-table .fi-ta-row.fi-selected:hover {
    background-color: color-mix(in srgb, var(--row-selected-bg) 92%, var(--ink)) !important;
}
.fi-ta-row.fi-selected > *:first-child::before {
    background-color: var(--row-selected-bar) !important;
    width: var(--row-selected-bar-w) !important;
}
.fi-ta-table-stacked-on-mobile > tbody > tr.fi-selected::before {
    background-color: var(--row-selected-bar) !important;
    width: var(--row-selected-bar-w) !important;
}

/* Ячейка с флажком. Filament даёт ей `px-3 py-4` — в плотном реестре это
   16px воздуха сверху и снизу на каждой строке, больше самой строки. */
.fi-ta-cell.fi-ta-selection-cell,
.fi-ta-cell.fi-ta-group-selection-cell {
    padding: var(--ta-col-pad-y) var(--ta-col-pad-x) !important;
}

/* Сам флажок. Filament рисует контур флажка КОЛЬЦОМ, а кольцо у него — это
   `box-shadow`. Погасить тень, чтобы поставить свою рамку, значит стереть
   контур: белый квадрат на белой строке перестаёт существовать, и человек не
   видит, где отмечать (ровно на этом однажды пропали поля ввода — см. тему).
   Поэтому тень не трогаем, а забираем ЦВЕТ кольца через его собственный канал. */
input[type='checkbox'].fi-ta-record-checkbox,
input[type='checkbox'].fi-ta-page-checkbox,
input[type='checkbox'].fi-ta-group-checkbox {
    inline-size: var(--ta-check-size);
    block-size: var(--ta-check-size);
    border-radius: var(--ta-check-radius);
    background-color: var(--surface);
    --tw-ring-color: var(--ta-check-line);
    cursor: pointer;
    transition: background-color .12s ease, box-shadow .12s ease;
}
input[type='checkbox'].fi-ta-record-checkbox:checked,
input[type='checkbox'].fi-ta-page-checkbox:checked,
input[type='checkbox'].fi-ta-group-checkbox:checked,
input[type='checkbox'].fi-ta-record-checkbox:indeterminate,
input[type='checkbox'].fi-ta-page-checkbox:indeterminate,
input[type='checkbox'].fi-ta-group-checkbox:indeterminate {
    background-color: var(--ta-check-on);
}
input[type='checkbox'].fi-ta-record-checkbox:focus-visible,
input[type='checkbox'].fi-ta-page-checkbox:focus-visible,
input[type='checkbox'].fi-ta-group-checkbox:focus-visible {
    outline: 2px solid var(--focus);
    outline-offset: 1px;
}
input[type='checkbox'].fi-ta-record-checkbox:disabled,
input[type='checkbox'].fi-ta-page-checkbox:disabled,
input[type='checkbox'].fi-ta-group-checkbox:disabled {
    background-color: var(--surface-2);
    opacity: .6;
}

/* Полоса «выбрано N» над таблицей: не тревога, а подтверждение — берёт мягкий
   тон акцента, а не заливку состояния. */
.fi-ta-ctn .fi-ta-selection-indicator {
    background-color: var(--ta-selection-bar-bg) !important;
    border-bottom: 1px solid var(--line) !important;
    padding: calc(var(--ta-col-pad-y) + 2px) var(--pad) !important;
}
.fi-ta-ctn .fi-ta-selection-indicator > :nth-child(1) {
    color: var(--ink) !important;
    font-size: var(--font-base) !important;
    font-weight: 600 !important;
}
.fi-ta-ctn .fi-ta-selection-indicator-actions-ctn {
    gap: var(--ta-actions-gap) !important;
}

/* ── Сортировка ────────────────────────────────────────────────────────────
   Активную колонку видно чернилами и (по желанию характера) подчёркиванием.
   Специфичность держим выше базовой темы: там шапка покрашена `!important`. */
.fi-ta-header-cell .fi-ta-header-cell-sort-btn {
    cursor: pointer;
    border-radius: var(--radius-sm);
    transition: color .12s ease;
}
.fi-ta-header-cell .fi-ta-header-cell-sort-btn:hover {
    color: var(--ink) !important;
}
.fi-ta-header-cell .fi-ta-header-cell-sort-btn:focus-visible {
    outline: 2px solid var(--focus);
    outline-offset: 1px;
}
.fi-ta-header-cell:not(.fi-ta-header-cell-sorted) .fi-icon {
    color: var(--ta-sort-icon) !important;
}
.fi-ta-header-cell.fi-ta-header-cell-sorted,
.fi-ta-header-cell.fi-ta-header-cell-sorted .fi-ta-header-cell-sort-btn,
.fi-ta-header-cell.fi-ta-header-cell-sorted .fi-icon {
    color: var(--th-sorted-ink) !important;
}
.fi-ta-header-cell.fi-ta-header-cell-sorted {
    box-shadow: inset 0 calc(-1 * var(--th-sorted-underline-w)) 0 0 var(--th-sorted-underline);
}

/* Шапка над столбцом действий: подписи там нет, и лишней линии тоже быть не
   должно — колонка прижата к правому краю и сжимается первой. */
.fi-ta-header-cell.fi-ta-actions-header-cell,
th.fi-ta-actions-header-cell {
    text-align: end;
    width: 1%;
    white-space: nowrap;
}

/* ── Колонки-элементы ──────────────────────────────────────────────────────
   Filament даёт каждой `px-3 py-4`. Это и есть главный источник высоты строки:
   текстовая колонка поджата в теме, а иконка, картинка или тумблер рядом
   продолжают распирать ряд, и вся экономия пропадает. Один токен на все. */
.fi-ta-icon:not(.fi-inline),
.fi-ta-image:not(.fi-inline),
.fi-ta-toggle:not(.fi-inline),
.fi-ta-select:not(.fi-inline),
.fi-ta-checkbox:not(.fi-inline),
.fi-ta-color:not(.fi-inline),
.fi-ta-text-input:not(.fi-inline) {
    padding: var(--ta-col-pad-y) var(--ta-col-pad-x) !important;
}
.fi-ta-cell:has(.fi-ta-actions) {
    padding: var(--ta-col-pad-y) var(--ta-col-pad-x) !important;
}

/* ── Колонка действий прижата к правому краю ───────────────────────────────
   Реестр шире экрана — это норма: колонок бывает семь, а ширины на них нет.
   Ненормально, когда вместе с ними уезжает КНОПКА: замер дал строку на 29px
   шире окна, и «⋮» приходилось доскроллить, чтобы удалить запись.
   Действия — не данные, они нужны на каждой строке всегда, поэтому колонка
   остаётся на месте, а данные ездят под ней.
   Фон обязателен: без него уезжающие ячейки просвечивают сквозь кнопку.
   Тень слева появляется только когда есть что прокручивать — рисуем её на
   `::after`, чтобы она не висела на неподвижной таблице. */
.fi-ta-cell:has(.fi-ta-actions),
th.fi-ta-actions-header-cell {
    position: sticky;
    right: 0;
    z-index: 2;
    background: var(--surface);
}
.fi-ta-row:hover .fi-ta-cell:has(.fi-ta-actions) { background: var(--row-hover-bg); }
.fi-ta-row.fi-selected .fi-ta-cell:has(.fi-ta-actions) { background: var(--row-selected-bg); }
.fi-ta-cell:has(.fi-ta-actions)::after,
th.fi-ta-actions-header-cell::after {
    content: '';
    position: absolute;
    inset-block: 0;
    inset-inline-start: 0;
    width: 1px;
    background: var(--line-soft);
}

/* Иконка-колонка. Своего цвета у неё чаще нет — тогда это служебный знак, а не
   акцент. Состояния (галочка/крест/предупреждение) уводим на цвета характера,
   иначе зелёный и красный в реестре разойдутся с плашками статуса. */
.fi-ta-icon > .fi-icon:not(.fi-color),
.fi-ta-icon > a > .fi-icon:not(.fi-color) {
    color: var(--ta-icon-ink) !important;
}
.fi-ta-icon .fi-icon.fi-color-success { color: var(--ok) !important; }
.fi-ta-icon .fi-icon.fi-color-warning { color: var(--warn) !important; }
.fi-ta-icon .fi-icon.fi-color-danger { color: var(--bad) !important; }
.fi-ta-icon .fi-icon.fi-color-info { color: var(--info) !important; }
.fi-ta-icon .fi-icon.fi-color-primary { color: var(--primary) !important; }
.fi-ta-icon .fi-icon.fi-color-gray { color: var(--neutral) !important; }

/* Картинка-колонка. Кольцо вокруг миниатюр в стопке отделяет их друг от друга —
   значит оно обязано совпадать с фоном строки, а не быть белым по умолчанию.
   Забираем канал кольца Tailwind, чтобы не трогать его ширину (ring-1/2/4). */
.fi-ta-image img {
    border-radius: var(--ta-image-radius);
}
.fi-ta-image.fi-circular img {
    border-radius: 50%;
}
.fi-ta-image.fi-ta-image-ring img,
.fi-ta-image.fi-ta-image-ring .fi-ta-image-limited-remaining-text {
    --tw-ring-color: var(--ta-image-ring);
}
.fi-ta-image .fi-ta-image-limited-remaining-text {
    color: var(--mute) !important;
    font-size: var(--font-sm);
    font-weight: 500;
}
.fi-ta-image.fi-stacked .fi-ta-image-limited-remaining-text {
    background-color: var(--surface-2) !important;
}

/* Образец цвета. Белый образец на белой строке пропадает — поэтому у него
   всегда есть волосок по контуру. */
.fi-ta-color > .fi-ta-color-item {
    inline-size: var(--ta-swatch-size);
    block-size: var(--ta-swatch-size);
    border-radius: var(--ta-image-radius);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ink) 14%, transparent);
}

/* Тумблер в ячейке. Стоковый — 44×24 при строке в 22: один тумблер поднимает
   весь реестр. Смещение «включено» считается из размеров, а не задаётся числом,
   поэтому характер меняет две величины и получает целый тумблер. */
.fi-ta-toggle .fi-toggle {
    inline-size: var(--ta-toggle-w);
    block-size: var(--ta-toggle-h);
    border-radius: var(--ta-toggle-radius);
}
.fi-ta-toggle .fi-toggle:not(.fi-color) {
    background-color: var(--ta-toggle-off);
}
.fi-ta-toggle .fi-toggle > :first-child {
    inline-size: calc(var(--ta-toggle-h) - 4px);
    block-size: calc(var(--ta-toggle-h) - 4px);
    border-radius: var(--ta-toggle-radius);
    background-color: var(--surface);
}
.fi-ta-toggle .fi-toggle.fi-toggle-on > :first-child {
    transform: translateX(calc(var(--ta-toggle-w) - var(--ta-toggle-h)));
}
[dir='rtl'] .fi-ta-toggle .fi-toggle.fi-toggle-on > :first-child {
    transform: translateX(calc(-1 * (var(--ta-toggle-w) - var(--ta-toggle-h))));
}

/* Инлайн-редакторы в ячейке. `min-w-48` (192px) в реестре съедает целую колонку.
   Поле ввода и селект разведены намеренно: поле — заливка без рамки, селект —
   поверхность с рамкой, чтобы «здесь выбирают из списка» читалось без клика. */
.fi-ta-text-input,
.fi-ta-select {
    min-inline-size: var(--ta-cell-input-minw) !important;
}
.fi-ta-text-input .fi-input-wrp,
.fi-ta-select .fi-input-wrp {
    min-block-size: var(--ta-field-h) !important;
    border-radius: var(--radius-sm) !important;
}
.fi-ta-text-input .fi-input,
.fi-ta-select .fi-select-input {
    padding-block: 0 !important;
    font-size: var(--font-base) !important;
}
.fi-ta-text-input .fi-input-wrp {
    background-color: var(--ta-cell-input-bg) !important;
    border-color: var(--ta-cell-input-line) !important;
}
.fi-ta-select .fi-input-wrp {
    background-color: var(--ta-cell-select-bg) !important;
    border-color: var(--ta-cell-select-line) !important;
}
.fi-ta-text-input .fi-input-wrp:focus-within,
.fi-ta-select .fi-input-wrp:focus-within {
    border-color: var(--focus) !important;
}

/* Флажок-колонка (редактируемый прямо в строке) — тот же флажок, что и в отборе. */
.fi-ta-checkbox input[type='checkbox'] {
    inline-size: var(--ta-check-size);
    block-size: var(--ta-check-size);
    border-radius: var(--ta-check-radius);
    --tw-ring-color: var(--ta-check-line);
}
.fi-ta-checkbox input[type='checkbox']:checked {
    background-color: var(--ta-check-on);
}

/* ── Раскладки колонок ─────────────────────────────────────────────────────
   Grid и Split собирают несколько колонок в одну ячейку; Stack ставит их
   этажами. Зазоры — часть плотности, поэтому на токенах. Собственные отступы
   вложенных колонок гасим: раскладка сама держит ритм. */
.fi-ta-grid:not(.fi-gap-sm):not(.fi-gap-lg) {
    gap: var(--ta-layout-gap);
}
.fi-ta-split.default\:fi-ta-split {
    gap: var(--ta-layout-gap);
}
.fi-ta-stack:not(.fi-gap-sm):not(.fi-gap-md):not(.fi-gap-lg) > * + * {
    margin-top: var(--ta-stack-gap);
}
.fi-ta-grid > *:not(.fi-inline),
.fi-ta-split > *:not(.fi-inline),
.fi-ta-stack > *:not(.fi-inline) {
    padding-block: 0 !important;
}

/* Панель — вложенный блок внутри строки (карточная раскладка реестра). Это не
   отдельная карточка со своей тенью: тень внутри строки даёт второй уровень
   поверхности там, где его нет. Достаточно подложки и волоска. */
.fi-ta-panel {
    background-color: var(--ta-panel-bg) !important;
    border-radius: var(--radius) !important;
    box-shadow: inset 0 0 0 1px var(--ta-panel-line) !important;
    padding: var(--pad) !important;
}

/* ── Поиск ─────────────────────────────────────────────────────────────────
   Поле поиска — единственный ввод в тулбаре, и в реестре оно не должно
   выглядеть как поле формы: заливка вместо рамки, рамка появляется на фокусе. */
.fi-ta-search-field {
    flex: 0 1 var(--ta-search-w);
    min-inline-size: 76px;
}
.fi-ta-search-field .fi-input-wrp {
    min-block-size: var(--ta-field-h) !important;
    background-color: var(--ta-search-bg) !important;
    border-color: var(--ta-search-line) !important;
    border-radius: var(--radius) !important;
    box-shadow: none !important;
}
.fi-ta-search-field .fi-input-wrp:focus-within {
    border-color: var(--focus) !important;
}
.fi-ta-search-field .fi-input {
    padding-block: 0 !important;
    font-size: var(--font-base) !important;
}
.fi-ta-search-field .fi-input::placeholder {
    color: var(--faint) !important;
}
.fi-ta-search-field .fi-input-wrp .fi-icon {
    color: var(--faint) !important;
}

/* ── Фильтры ───────────────────────────────────────────────────────────────
   Панель фильтров (в поповере, над таблицей или сбоку). */
.fi-ta-filters {
    gap: var(--pad) !important;
}
.fi-ta-ctn .fi-ta-header-toolbar .fi-ta-filters-dropdown .fi-ta-filters,
.fi-ta-ctn .fi-ta-filters-before-content-ctn .fi-ta-filters,
.fi-ta-ctn .fi-ta-filters-after-content-ctn .fi-ta-filters {
    padding: var(--pad) !important;
}
.fi-ta-ctn .fi-ta-filters.fi-ta-filters-below-content,
.fi-ta-ctn .fi-ta-filters-above-content-ctn {
    padding: var(--pad) !important;
    border-color: var(--line-soft) !important;
}
.fi-ta-filters-header .fi-ta-filters-heading {
    color: var(--ink) !important;
    font-size: var(--font-base) !important;
    font-weight: 600 !important;
}
.fi-ta-filters-actions-ctn {
    gap: var(--ta-actions-gap) !important;
}
.fi-ta-filters-before-content-ctn,
.fi-ta-filters-after-content-ctn {
    background-color: var(--surface) !important;
    border-color: var(--line) !important;
}

/* Полоса активных условий. Читается как сводка над данными, а не как ещё одна
   панель: своя подложка, тот же волосок, что и у остальных полос таблицы. */
.fi-ta-ctn .fi-ta-filter-indicators {
    background-color: var(--ta-filter-bar-bg) !important;
    border-bottom: 1px solid var(--line) !important;
    padding: var(--ta-col-pad-y) var(--pad) !important;
}
.fi-ta-filter-indicators .fi-ta-filter-indicators-label {
    color: var(--mute) !important;
    font-size: var(--font-sm) !important;
    font-weight: 500 !important;
}
.fi-ta-filter-indicators .fi-ta-filter-indicators-badges-ctn {
    gap: var(--ta-actions-gap) !important;
}
/* Условие — снимаемая «таблетка», не статус. Цветной заливки не получает:
   иначе фильтр начинает спорить с состояниями строк за внимание. */
.fi-ta-filter-indicators .fi-badge {
    background-color: var(--ta-filter-badge-bg) !important;
    border: 1px solid var(--line) !important;
    border-radius: var(--ta-filter-badge-radius) !important;
    color: var(--body) !important;
    font-size: var(--font-sm) !important;
    font-weight: 400 !important;
}
.fi-ta-filter-indicators .fi-badge .fi-icon-btn:hover {
    color: var(--bad) !important;
}

/* ── Менеджер колонок ──────────────────────────────────────────────────────
   Список «что показывать». Стоковый шаг строки — 24px на пункт; в таблице на
   тридцать колонок это два экрана прокрутки. */
.fi-ta-col-manager {
    gap: var(--pad) !important;
}
.fi-ta-ctn .fi-ta-header-toolbar .fi-ta-col-manager-dropdown .fi-ta-col-manager {
    padding: var(--pad) !important;
}
.fi-ta-col-manager .fi-ta-col-manager-heading {
    color: var(--ink) !important;
    font-size: var(--font-base) !important;
    font-weight: 600 !important;
}
.fi-ta-col-manager .fi-ta-col-manager-item {
    padding-top: var(--ta-colman-step) !important;
    gap: calc(var(--pad) / 2) !important;
}
.fi-ta-col-manager .fi-ta-col-manager-items {
    margin-top: calc(-1 * var(--ta-colman-step)) !important;
}
.fi-ta-col-manager .fi-ta-col-manager-label {
    color: var(--body) !important;
    font-size: var(--font-base) !important;
    font-weight: 400 !important;
    gap: calc(var(--pad) / 2) !important;
    cursor: pointer;
}
.fi-ta-col-manager .fi-ta-col-manager-item:hover .fi-ta-col-manager-label {
    color: var(--ink) !important;
}
.fi-ta-col-manager .fi-ta-col-manager-reorder-handle {
    color: var(--ta-colman-handle) !important;
    border-radius: var(--radius-sm);
    transition: color .12s ease, background-color .12s ease;
}
.fi-ta-col-manager .fi-ta-col-manager-reorder-handle:hover {
    color: var(--ink) !important;
    background-color: var(--hover) !important;
}
.fi-ta-col-manager .fi-ta-col-manager-actions-ctn {
    gap: var(--ta-actions-gap) !important;
}

/* ── Пустое состояние ──────────────────────────────────────────────────────
   Пусто — это тоже экран, а не дырка в таблице: у него есть заголовок, объяснение
   и действие. Подложка иконки — форма характера (круг ↔ квадрат), не украшение. */
.fi-ta-empty-state {
    padding: calc(var(--pad) * 3) calc(var(--pad) * 2) !important;
    border-color: var(--line-soft) !important;
}
.fi-ta-empty-state .fi-ta-empty-state-icon-bg {
    background-color: var(--ta-empty-icon-bg) !important;
    border-radius: var(--ta-empty-icon-radius) !important;
    padding: calc(var(--pad) * .75) !important;
    margin-bottom: var(--pad) !important;
}
.fi-ta-empty-state .fi-ta-empty-state-icon-bg .fi-icon {
    color: var(--mute) !important;
}
.fi-ta-empty-state .fi-ta-empty-state-heading {
    color: var(--ink) !important;
    font-size: calc(var(--font-base) + 2px) !important;
    font-weight: 600 !important;
}
.fi-ta-empty-state .fi-ta-empty-state-description {
    color: var(--mute) !important;
    font-size: var(--font-base) !important;
    margin-top: calc(var(--pad) / 3) !important;
}
.fi-ta-empty-state .fi-ta-actions {
    margin-top: calc(var(--pad) * 1.25) !important;
    justify-content: center;
}

/* ── Действия строки ───────────────────────────────────────────────────────
   Действия висят у каждой строки, и в полную силу они спорят с данными за
   внимание. Поэтому в покое приглушены, при наведении и с клавиатуры — целые.
   `--ta-actions-idle-opacity: 1` возвращает их всегда видимыми, `0` — прячет
   до наведения (учётный характер). Полностью скрывать по умолчанию нельзя:
   на тач-экране наведения не бывает. */
.fi-ta-cell .fi-ta-actions {
    gap: var(--ta-actions-gap) !important;
    opacity: var(--ta-actions-idle-opacity);
    transition: opacity .12s ease;
}
.fi-ta-row:hover .fi-ta-cell .fi-ta-actions,
.fi-ta-row:focus-within .fi-ta-cell .fi-ta-actions {
    opacity: 1;
}
.fi-ta-cell .fi-ta-actions .fi-icon-btn {
    inline-size: var(--ta-action-btn-size);
    block-size: var(--ta-action-btn-size);
    margin: 0;
    border-radius: var(--radius-sm);
    color: var(--mute);
}
.fi-ta-cell .fi-ta-actions .fi-icon-btn .fi-icon {
    inline-size: var(--ta-action-icon-size);
    block-size: var(--ta-action-icon-size);
}
.fi-ta-cell .fi-ta-actions .fi-icon-btn:not(.fi-disabled):not([disabled]):hover {
    background-color: var(--hover);
    color: var(--ink) !important;
}
.fi-ta-cell .fi-ta-actions .fi-icon-btn:focus-visible {
    outline: 2px solid var(--focus);
    outline-offset: 1px;
}
/* Опасное действие узнаётся до клика, а не по тексту в окне подтверждения. */
.fi-ta-cell .fi-ta-actions .fi-icon-btn.fi-color-danger:hover {
    background-color: var(--bad-soft);
    color: var(--bad) !important;
}
.fi-ta-cell .fi-ta-actions .fi-btn {
    font-size: var(--font-sm) !important;
}

/* Действия в шапке таблицы и в пустом состоянии приглушать нечем — там они
   единственное, что можно сделать. */
.fi-ta-header .fi-ta-actions,
.fi-ta-empty-state .fi-ta-actions,
.fi-ta-header-toolbar .fi-ta-actions {
    opacity: 1;
}

/* ============================================================================
   НОВЫЕ ТОКЕНЫ (значения свести в общий блок словаря; здесь только смысл)

   ── Ось характера: строка ───────────────────────────────────────────────────
   --row-stripe          фон чётной строки; transparent = зебры нет
                         light: transparent · dark: transparent
                         полосатый характер: color-mix(in srgb, var(--ink) 3%, transparent)
   --row-separator       цвет волоска между строками; transparent = без разделителя
                         light: var(--line-soft) · dark: var(--line-soft)
   --row-separator-w     толщина волоска          light: 1px · dark: 1px
   --row-hover-bg        заливка строки под курсором
                         light: var(--hover) · dark: var(--hover)
   --row-hover-bar       полоса слева при наведении; transparent = наведение
                         только заливкой   light: transparent · dark: transparent
   --row-hover-bar-w     ширина этой полосы       light: 2px · dark: 2px
   --row-selected-bg     фон выбранной строки     light: var(--selected) · dark: var(--selected)
   --row-selected-bar    метка выбранной строки слева
                         light: var(--primary) · dark: var(--primary)
   --row-selected-bar-w  ширина метки             light: 2px · dark: 2px

   ── Шапка и сортировка ──────────────────────────────────────────────────────
   --th-sorted-ink          заголовок колонки, по которой сортируют
                            light: var(--ink) · dark: var(--ink)
   --th-sorted-underline    подчёркивание активной колонки; transparent = без него
                            light: transparent · dark: transparent
   --th-sorted-underline-w  его толщина           light: 2px · dark: 2px
   --ta-sort-icon           стрелка сортировки в покое
                            light: var(--faint) · dark: var(--faint)

   ── Отбор строк ─────────────────────────────────────────────────────────────
   --ta-check-size        сторона флажка          light: 12px · dark: 12px
   --ta-check-radius      скругление флажка (квадратный ↔ круглый)
                          light: 2px · dark: 2px
   --ta-check-line        кольцо неотмеченного флажка
                          light: var(--line-strong) · dark: var(--line-strong)
   --ta-check-on          заливка отмеченного. ВНИМАНИЕ: галочку Filament рисует
                          белой картинкой — значение обязано оставаться тёмным
                          light: var(--primary) · dark: var(--primary)
   --ta-selection-bar-bg  фон полосы «выбрано N»
                          light: var(--primary-soft) · dark: var(--primary-soft)

   ── Колонки-элементы ────────────────────────────────────────────────────────
   --ta-col-pad-y        вертикальный отступ внутри колонки-элемента — главная
                         ручка высоты строки      light: 4px · dark: 4px
   --ta-col-pad-x        горизонтальный отступ    light: 8px · dark: 8px
   --ta-icon-ink         иконка-колонка без своего цвета
                         light: var(--faint) · dark: var(--faint)
   --ta-image-radius     радиус миниатюры и образца цвета
                         light: var(--radius-sm) · dark: var(--radius-sm)
   --ta-image-ring       кольцо вокруг миниатюр в стопке (обязано совпадать с
                         фоном строки)  light: var(--surface) · dark: var(--surface)
   --ta-swatch-size      сторона образца цвета    light: 18px · dark: 18px
   --ta-toggle-w         ширина тумблера в ячейке light: 30px · dark: 30px
   --ta-toggle-h         высота тумблера          light: 16px · dark: 16px
   --ta-toggle-radius    скругление тумблера      light: 999px · dark: 999px
   --ta-toggle-off       дорожка выключенного тумблера
                         light: var(--line-strong) · dark: var(--line-strong)
   --ta-field-h          высота поля в таблице (поиск и инлайн-редакторы)
                         light: 26px · dark: 26px
   --ta-cell-input-minw  минимальная ширина инлайн-редактора (стоковые 192px в
                         реестре съедают колонку)  light: 120px · dark: 120px
   --ta-cell-input-bg    заливка инлайн-поля ввода
                         light: var(--surface-2) · dark: var(--surface-2)
   --ta-cell-input-line  его рамка                light: transparent · dark: transparent
   --ta-cell-select-bg   заливка инлайн-селекта
                         light: var(--surface) · dark: var(--surface)
   --ta-cell-select-line его рамка (селект видно без клика)
                         light: var(--line-strong) · dark: var(--line-strong)

   ── Раскладки колонок ───────────────────────────────────────────────────────
   --ta-layout-gap   зазор в Grid и Split          light: 8px · dark: 8px
   --ta-stack-gap    зазор между этажами Stack     light: 2px · dark: 2px
   --ta-panel-bg     фон панели внутри строки
                     light: var(--surface-2) · dark: var(--surface-2)
   --ta-panel-line   её волосок
                     light: var(--line-soft) · dark: var(--line-soft)

   ── Поиск, фильтры, менеджер колонок ────────────────────────────────────────
   --ta-search-w            базовая ширина поля поиска  light: 230px · dark: 230px
   --ta-search-bg           его заливка
                            light: var(--surface-2) · dark: var(--surface-2)
   --ta-search-line         его рамка в покое      light: transparent · dark: transparent
   --ta-filter-bar-bg       фон полосы активных условий
                            light: var(--surface-2) · dark: var(--surface-2)
   --ta-filter-badge-bg     фон снимаемого условия
                            light: var(--surface) · dark: var(--surface)
   --ta-filter-badge-radius его форма (таблетка ↔ прямоугольник)
                            light: 999px · dark: 999px
   --ta-colman-handle       ручка перетаскивания колонки
                            light: var(--faint) · dark: var(--faint)
   --ta-colman-step         шаг строки в менеджере колонок  light: 8px · dark: 8px

   ── Пустое состояние и действия строки ──────────────────────────────────────
   --ta-empty-icon-bg        подложка иконки пустого экрана
                             light: var(--surface-2) · dark: var(--surface-2)
   --ta-empty-icon-radius    её форма (круг ↔ квадрат)  light: 999px · dark: 999px
   --ta-actions-gap          зазор между действиями   light: 4px · dark: 4px
   --ta-actions-idle-opacity видимость действий, пока строку не тронули;
                             1 = всегда целые, 0 = проявляются по наведению
                             light: .55 · dark: .55
   --ta-action-btn-size      сторона кнопки-действия  light: 22px · dark: 22px
   --ta-action-icon-size     иконка внутри неё        light: 14px · dark: 14px

   Если сводить с другими группами: --ta-field-h, --ta-cell-input-bg и
   --ta-cell-select-line намеренно названы своими именами, чтобы не спорить с
   токенами форм. Их можно просто приравнять к общим значениям полей.
   ============================================================================ */
