/* Общие блоки оболочки (спека v2.2 §2, §8; лимит файла 400 строк, В75). Токены и сетки страниц — в app.css (лимит 200 строк).
   Блоки: таблицы и списки, строка в два уровня, статусы, числа, заголовки групп, шторка, угол экрана, лента «История», карточка
   «ключ — значение», подсказки. Кнопки, бейджи, вкладки, диалоги берутся из Basecoat; здесь они только получают токены
   (бледные статусы, точка у слова), своих вариантов не заводим (UI_ПРАВИЛА.md п.25). */

/* ---- Таблицы и списки (п.26): между строками одна линия --border, без «зебры» и рамок ячеек, строка не ниже 44 px, шапка с фоном ---- */
.table th { font: 500 12px var(--sans); color: var(--ink-2); text-align: left; }
.table thead { background: var(--surface-2); }
.table td { white-space: normal; vertical-align: middle; overflow-wrap: anywhere; border: 0; padding-block: 8px; }
.table th { border: 0; }
.table tbody tr { height: 44px; border-bottom: 1px solid var(--border); background: none; }
.table tbody tr:last-child { border-bottom: 0; }
.table tbody tr:nth-child(even) { background: none; }
.table th a { color: inherit; text-decoration: none; }
.table th a:hover { color: var(--blue); }
.list2, .history-list { list-style: none; margin: 0; padding: 0; display: grid; }
.main .list2, .main .history-list { list-style: none; padding-left: 0; }
.list2 > li, .history-item { display: grid; align-content: center; gap: 2px; min-height: 44px; padding: 8px 0; border-bottom: 1px solid var(--border); }
.list2 > li:last-child, .history-item:last-child { border-bottom: 0; }

/* Строка в два уровня (п.26): основной текст, под ним серая строка на ступень мельче. Третьего уровня нет. Ячейка или элемент
   списка с двумя уровнями помечены data-lines="2" */
.sub { display: block; margin-top: 2px; font-size: 12px; line-height: 1.35; color: var(--ink-2); font-weight: 400; }
.sub a { color: inherit; }
.history-item .sub, .history-item .muted { font-size: 12px; margin-top: 0; }
.history-item[data-failed] > span:first-child { color: var(--danger); }

/* Числа (п.27): колонка по правому краю, цифры равной ширины. Класс ставят и на th, и на td */
.col-num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.table th.col-num { text-align: right; font-variant-numeric: tabular-nums; }   /* `font` у .table th сбрасывает цифры равной ширины */
/* Итоги таблицы (W-16): строки «Сумма» и «Медиана» под линией, шапка колонок может переноситься */
.table tfoot td, .table tfoot th { border-top: 1px solid var(--border); padding-block: 8px; font-weight: 600; }
.table tfoot tr + tr td, .table tfoot tr + tr th { border-top: 0; }
#worktime-table th.col-num { white-space: normal; }

/* Статусы: точка и слово либо бледная плашка. Насыщенная заливка только у первичной кнопки; «!» непроверенного — бледно-жёлтая
   плашка (app.css), цвета корзин смысловые и остаются как есть */
.badge[data-variant="destructive"] { background: color-mix(in srgb, var(--danger) 10%, var(--surface)); color: var(--danger);
  border-color: color-mix(in srgb, var(--danger) 30%, var(--surface)); }
.badge:not([data-variant]):not([data-flag]) { background: var(--surface-2); color: var(--ink-2); border-color: var(--line); }
.badge[data-dot] { background: none; border-color: transparent; padding-inline: 0; gap: 6px; color: var(--ink); font-weight: 400; }
.badge[data-dot]::before { content: ""; width: 7px; height: 7px; border-radius: 50%; flex: none; background: var(--ink-3); }
.badge[data-dot="ok"]::before { background: var(--b-core); }
.badge[data-dot="warn"]::before { background: var(--b-disputed); }
.badge[data-dot="bad"]::before { background: var(--danger); }
.badge[data-dot="info"]::before { background: var(--blue); }

/* Заголовок группы (правило 6): мелкий, серый, над группой */
.group-title, .groups h3 { font: 500 12px var(--sans); color: var(--ink-2); }

/* Строка с итогом, подсказка-плашка и пустое состояние живут в app.css; смысловые отметки строк */
[data-decided] > td:first-child { box-shadow: inset 3px 0 0 var(--b-core); }
.cut-row--alarm td, tr[data-unmatched] td { background: var(--warn-bg); }
tr[data-ghost] td { background: color-mix(in srgb, var(--danger) 8%, var(--surface)); }
tr[data-ghost] del { text-decoration: line-through; color: var(--danger); }
.prior-reasons { color: var(--ink-2); font-size: 12px; }

/* ---- Шторка — один блок (п.30, §8): шапка с заголовком и крестиком, прокручиваемое тело, необязательный закреплённый низ.
   Esc, крестик и клик по фону закрывают; фокус возвращается на элемент, открывший шторку (base.html, sheetShow/sheetClose).
   Применения: панель слова (шаги 3–4), «История», «Настройки обработки», «Обратная связь». ---- */
.sheet { position: fixed; inset: 0; z-index: 80; visibility: hidden; transition: visibility 0s linear .2s; }
.sheet.open { visibility: visible; transition-delay: 0s; }
.sheet-scrim { position: absolute; inset: 0; background: rgba(0, 0, 0, .35); opacity: 0; transition: opacity .2s ease; }
.sheet.open .sheet-scrim { opacity: 1; }
.sheet-panel { position: absolute; top: 0; right: 0; bottom: 0; width: var(--sheet-w, 420px); max-width: 92vw; background: var(--surface);
  display: grid; grid-template-rows: auto minmax(0, 1fr) auto; box-shadow: -8px 0 24px rgba(0, 0, 0, .18);
  transform: translateX(100%); transition: transform .2s ease; min-width: 0; }
.sheet.open .sheet-panel { transform: none; }
.sheet-panel:focus { outline: none; }
/* Шапка, тело и низ — прямые дети панели или (форма и подгруженная оболочка стоят с display: contents) формы внутри неё */
:is(.sheet-panel, .sheet-panel > form, .sheet-slot, .sheet-slot > form) > header { display: flex; justify-content: space-between; align-items: center; gap: 10px; padding: 12px 18px; border-bottom: 1px solid var(--border); }
:is(.sheet-panel, .sheet-panel > form, .sheet-slot, .sheet-slot > form) > header h2 { font-size: 15px; text-transform: none; }
:is(.sheet-panel, .sheet-panel > form, .sheet-slot, .sheet-slot > form) > section { overflow: auto; padding: 14px 18px; display: grid; gap: 12px; align-content: start; min-width: 0; overflow-wrap: anywhere; }
:is(.sheet-panel, .sheet-panel > form, .sheet-slot, .sheet-slot > form) > footer { padding: 12px 18px; border-top: 1px solid var(--border); display: flex; justify-content: flex-end; gap: 8px; }
.sheet-panel > form, .sheet-slot, .sheet-slot > form { display: contents; }   /* форма и её подгруженная оболочка не ломают три строки шторки */
/* Панель слова шаги 3–4 — шторка по макету (shag34.css, UX-14): слово, поля, фильтр и список фраз, последствия и кнопки решения */
#word-panel.htmx-request { cursor: progress; }
@media (prefers-reduced-motion: reduce) { .sheet, .sheet-scrim, .sheet-panel { transition: none; } }

/* Угол экрана (макет v2.3, `.corner`): «Обратная связь» всегда, «Отменить действие» только в задаче — одной строкой внизу справа поверх
   страницы. Резерва справа у рабочей области нет. Чтобы угол ничего не закрывал при прокрутке до низа (UI_ПРАВИЛА.md п.16): у страницы
   внизу отступ 64 px (`.main`, app.css), у липкого низа справа 280 px (`.pick-bar`, `.nm-footer`), у колонки-панели шире 1440 и карточки
   «Правил» внизу 60 px. */
.corner { position: fixed; right: 16px; bottom: 14px; z-index: 60; display: flex; gap: 6px; }
.corner form { display: flex; }
.corner .btn { background: var(--surface); white-space: nowrap; }
.corner .btn[aria-busy="true"] { cursor: progress; opacity: .6; }

/* Карточка «Правил» любой длины: колонка прокручивается сама. Без max-content строка сетки сжималась до высоты колонки, а у
   карточки Basecoat overflow: hidden — низ («Проверки», «Время», «Правила нет / предложить») обрезался без прокрутки (круг 2) */
.pravila-card { grid-auto-rows: max-content; }
.pravila-card > .card { overflow: visible; }

.task-head-row { display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; }

/* Сведения о задаче: одна карточка «ключ — значение» в три колонки */
.kv { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px 24px; margin: 0; }
.kv > div { display: grid; gap: 2px; min-width: 0; align-content: start; }
.kv dt, .kv .kv-key { color: var(--ink-2); font-size: 12px; margin: 0; }
.kv dd { margin: 0; overflow-wrap: anywhere; }
/* Карточка обращения: текст, комментарии, журнал и значения снимка пишет человек — слово без пробелов переносится, а не
   обрезается краем карточки (у .card overflow: hidden). UI_ПРАВИЛА №16. */
#appeal-text p, #appeal-comments li, #appeal-log li, main:has(#appeal-text) .task-meta dd { overflow-wrap: anywhere; }
.kv-opts { display: flex; gap: 14px; align-items: center; min-height: 36px; }
.kv-actions { display: flex; justify-content: flex-end; margin-top: 4px; }
.kv.kv--one { grid-template-columns: minmax(0, 1fr); }   /* та же карточка в одну колонку — в шторке */
@media (max-width: 900px) { .kv { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* Разбор аудита (AU-13): кнопки решения под текстом замечания, выбранное правило в списке, строка-заголовок варианта */
.row-actions { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
#razbor-card > section { display: grid; gap: 12px; align-content: start; }
#razbor-card .tools form { display: contents; }
.list2 a[aria-current="true"] { font-weight: 700; color: var(--ink); text-decoration: none; }
tr.variant-row { background: var(--surface-2); }
tr.variant-row td { padding-block: 6px; }
#variant-more > div { display: grid; gap: 6px; }
#variant-more-list { display: flex; flex-wrap: wrap; gap: 6px; }
#variant-more-list a[hidden] { display: none; }

/* ---- Полоса шагов «стрелки» (UX-13, макет v2.3; UX-8, §3). Один компонент для всех сервисов (`steps_strip` в _shell.html): сегменты — любое
   число, номер, название и статус словом приходят данными, шагов очистки здесь нет. Готово — бледно-зелёный с галочкой, текущий — тёмный с
   жёлтым номером, есть непроверенное — бледно-жёлтый с «!», будущий — серый и не ссылка. Цвет сегмента берётся из вида статуса
   (`data-kind` у `.strip-status`), поэтому внеполосная замена одного статуса перекрашивает весь сегмент; текст не переносится. ---- */
.strip { container: strip / inline-size; }
.strip ol { list-style: none; margin: 0; padding: 0; display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 3px; }
.strip li { min-width: 0; display: grid; }
.st { --c: 14px; display: grid; grid-template-columns: 22px minmax(0, 1fr); column-gap: 10px; align-items: center; min-width: 0; line-height: 1.25;
  padding: 9px calc(var(--c) + 8px) 9px calc(var(--c) + 12px); text-decoration: none; background: var(--soft);
  clip-path: polygon(0 0, calc(100% - var(--c)) 0, 100% 50%, calc(100% - var(--c)) 100%, 0 100%, var(--c) 50%); }
.strip .st { color: var(--ink-2); }   /* перебивает синий цвет ссылок */
.strip li:first-child > .st { clip-path: polygon(0 0, calc(100% - var(--c)) 0, 100% 50%, calc(100% - var(--c)) 100%, 0 100%); padding-left: 12px; border-radius: var(--r-sm) 0 0 var(--r-sm); }
/* Плотные значения полосы (срез 10 px, зазор 6, отступы 12/8) — единственное отступление от значений макета (п.43 UI_ПРАВИЛА); включаются в двух случаях:
   полоса уже 1150 px (окно 1280 при развёрнутой панели: 997 px) либо сервер пометил её `data-dense` (в подписи статуса число от 1000, макрос steps_strip).
   Иначе — значения макета (14/10/26/22): на 1440 полоса 1172 px, а при вертикальной прокрутке 1157. Цифры в подписи равной ширины (`.num`), поэтому любое
   четырёхзначное число занимает одно место и помещается без обрезки в плотной полосе; пятизначное — с «…» и полным текстом в подсказке. */
.strip[data-dense] .st { --c: 10px; column-gap: 6px; padding: 9px 8px 9px calc(var(--c) + 2px); }
@container strip (max-width: 1150px) { .st { --c: 10px; column-gap: 6px; padding: 9px 8px 9px calc(var(--c) + 2px); } .strip li:first-child > .st { padding-left: 12px; } }
.strip .num { font-variant-numeric: tabular-nums; }
.strip-title { display: contents; }
.strip-n { grid-row: 1 / span 2; width: 22px; height: 22px; border-radius: 50%; display: grid; place-items: center; font-size: 12px; font-weight: 600;
  background: var(--bg); color: var(--ink-3); border: 1px solid var(--line); }
.strip-name { grid-column: 2; font-size: 13.5px; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.strip-status, .strip .badge { display: block; grid-column: 2; justify-self: start; max-width: 100%; height: auto; padding: 0; border: 0; border-radius: 0; background: none;
  font: 400 12px/1.25 var(--sans); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.st:has([data-kind="done"]) { --k: var(--ok); --kb: var(--ok-bg); --kt: var(--ok); }
.st:has([data-kind="flag"]) { --k: var(--amber); --kb: var(--warn-bg); --kt: var(--warn); }
.st:has([data-kind="error"]) { --k: var(--danger); --kb: var(--danger-bg); --kt: var(--danger); }
.st:has([data-kind="done"], [data-kind="flag"], [data-kind="error"]) { background: var(--kb); color: var(--ink); }
.st:has([data-kind="done"], [data-kind="flag"], [data-kind="error"]) .strip-n { background: var(--k); border-color: var(--k); color: #fff; font-size: 0; }   /* вместо номера — ✓ или «!» */
.st:has([data-kind="done"], [data-kind="flag"], [data-kind="error"]) :is(.strip-status, .badge) { color: var(--kt); }
.st:has([data-kind="done"]) .strip-n::after { content: "✓"; }
.st:has([data-kind="flag"], [data-kind="error"]) .strip-n::after { content: "!"; }
.st .strip-n::after { font-size: 12px; }
.strip .st[aria-disabled] { background: var(--soft); cursor: default; }                  /* будущий шаг: серый, не ссылка */
.strip .st[aria-disabled] .strip-name, .strip .st[aria-disabled] .strip-status { color: var(--ink-3); }
.strip .st[aria-current] { background: var(--panel); color: #fff; cursor: default; }     /* текущий: тёмный, номер жёлтый */
.strip .st[aria-current] .strip-n { background: var(--mark); border-color: var(--mark); color: var(--panel); }
.strip .st[aria-current] .strip-status, .strip .st[aria-current] .badge { color: #e4e4e7; }
.strip .st[aria-disabled] .strip-n, .strip .st[aria-current] .strip-n { font-size: 12px; }
.strip .st[aria-disabled] .strip-n::after, .strip .st[aria-current] .strip-n::after { content: none; }
.strip .st[aria-disabled] .strip-n { background: var(--bg); border-color: var(--line); color: var(--ink-3); }
.strip a.st:hover .strip-name, .strip a.st:focus-visible .strip-name { text-decoration: underline; text-underline-offset: 3px; }
.strip a.st:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }   /* срез стрелки обрезает обводку справа; сверху, снизу и слева она видна, название подчёркнуто */
.strip a.st[aria-current]:focus-visible { outline-color: #fff; }
.task-context { font-size: 13px; color: var(--ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* «Закреплённое» (UX-10, §7): личные ссылки «Бренд › Категория» под основным меню. Название обрезается многоточием (полное — в подсказке);
   в свёрнутой панели остаётся значок. Много закреплённого — список прокручивается сам, подвал панели («Выйти») остаётся на месте. */
.nav-pins { display: flex; flex-direction: column; gap: 2px; min-height: 0; overflow-y: auto; }
.nav-links a, .nav-pins a { align-items: center; justify-content: flex-start; gap: 10px; }
.nav-pins .nav-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Поиск и числа у пунктов меню (UX-12, §7). Поле — вверху панели; в свёрнутой панели вместо поля значок (по щелчку панель разворачивается
   с фокусом в поле). Число — серая цифра справа от названия, в свёрнутой панели маленький кружок на углу значка: ширина панели не растёт. */
.nav-search { margin: 0 2px 10px; }
.nav-search input[type="search"] { width: 100%; height: auto; padding: 7px 10px; font: 13px var(--sans); color: var(--panel-ink); background: none;
  border: 1px solid var(--panel-line); border-radius: var(--r-sm); }
.nav-search input[type="search"]::placeholder { color: var(--panel-ink-2); }
.nav-search input[type="search"]:focus-visible { outline: 2px solid var(--panel-ink); outline-offset: 1px; }
.nav-search .btn { display: none; width: 100%; }
html[data-nav="collapsed"] .nav-search { margin: 0 0 6px; }
html[data-nav="collapsed"] .nav-search input[type="search"] { display: none; }
html[data-nav="collapsed"] .nav-search .btn { display: inline-flex; justify-content: center; }
.nav-count { margin-left: auto; font-size: 12px; color: var(--panel-ink-2); font-variant-numeric: tabular-nums; }
html[data-nav="collapsed"] .nav-links a { position: relative; }
html[data-nav="collapsed"] .nav-count { position: absolute; top: 0; right: 0; margin: 0; min-width: 16px; padding: 0 4px; border-radius: 8px; background: var(--panel-active);
  border: 1px solid var(--panel-line); color: var(--panel-ink); font-size: 10px; line-height: 14px; text-align: center; }

/* «Что нового» (W-14, §10.1): точка у пункта меню (в свёрнутой панели — на углу значка) и список записей */
.nav-dot { flex: none; margin-left: auto; width: 8px; height: 8px; border-radius: 50%; background: var(--panel-ink); }
html[data-nav="collapsed"] .nav-dot { position: absolute; top: 4px; right: 8px; margin: 0; }
.news-list { display: grid; gap: 12px; max-width: 760px; }
.news-item > header { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.news-item h2 { margin: 0; text-transform: none; }   /* заголовок записи — фраза, а не метка раздела: заглавными его не набираем */
.news-item time { font-size: 12px; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.news-body p { margin: 0 0 8px; max-width: 70ch; overflow-wrap: anywhere; }
.news-edit > summary { cursor: pointer; color: var(--ink-2); font-size: 13px; }
.news-edit form { margin-top: 12px; }

/* «Моя работа» (UX-10, UX-16) — moya_rabota.css, подключается из home.html */
[data-sub="above"] .sub { margin: 0 0 2px; }

/* Подсказки одной строкой: «Подсказки (N)», свёрнуты по умолчанию; «Подробнее» — служебное под раскрытием */
details.hints, details.more { color: var(--ink-2); }
details.hints > summary, details.more > summary { cursor: pointer; font-size: 13px; color: var(--ink-2); list-style: none; }
details.hints > summary::-webkit-details-marker, details.more > summary::-webkit-details-marker { display: none; }
details.hints > summary::before, details.more > summary::before { content: "▸"; display: inline-block; width: 1.1em; }
details.hints[open] > summary::before, details.more[open] > summary::before { content: "▾"; }
details.hints > summary:focus-visible, details.more > summary:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
details.hints > ul { margin: 6px 0 0; padding-left: 1.4em; display: grid; gap: 4px; }
details.more > div { margin-top: 4px; font-size: 12px; color: var(--ink-2); }

/* ---- Очереди шагов 3–4 (UX-4, §4; вид списка, строк и шторки по макету v2.3 — shag34.css, UX-14): общие куски, нужные и шагу 5 ---- */
/* Шаг 5: `sticky` держит строку «Выбрано N» внутри родителя. Пока родителем был #step5-list, строка не могла подняться выше его верха, а после
   полосы шагов UX-8 список начинается ниже низа окна (867 px при окне 900): на верху страницы строка висела на 21 px ниже окна. Список без
   своей коробки — родитель строки вся карточка шага, она начинается выше любого окна. Промежутки между блоками списка даёт `gap` карточки. */
#step5-list { display: contents; }
#step5-list .pager { margin: 0; }
.queue-note { margin: 0; font-size: 13px; color: var(--ink-2); }
.queue-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; min-height: 28px; font-size: 12px; }
.queue-meta .badge .btn { height: 18px; width: 18px; padding: 0; font-size: 10px; }
.col-pick { width: 32px; padding-right: 0; }
.act-row { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; }
.act-row .btn { padding-inline: 8px; white-space: nowrap; }
.badge[data-dot="warn"]::before { background: var(--amber); }
.scale { display: inline-flex; gap: 2px; margin-left: 8px; vertical-align: middle; }
.scale i { width: 5px; height: 12px; background: var(--line); }
.scale i[data-on] { background: var(--blue); }
tr[data-cursor] { outline: 2px solid var(--blue); outline-offset: -2px; }
.row-more { position: relative; }
.row-more > summary { list-style: none; cursor: pointer; }
.row-more > summary::-webkit-details-marker { display: none; }
.row-more > div { position: absolute; right: 0; top: 100%; z-index: 20; display: grid; gap: 4px; min-width: 150px; padding: 6px;
  background: var(--surface); border: 1px solid var(--line); box-shadow: 0 4px 12px rgba(0, 0, 0, .12); }
#queue-done .alert { border-left-color: var(--b-core); }
.empty[data-empty="search"] { display: grid; justify-items: start; }
.skel { height: 14px; margin: 8px 0; background: linear-gradient(90deg, var(--surface-2), var(--line), var(--surface-2)); background-size: 200% 100%; animation: skel 1.2s linear infinite; }
.skel--short { width: 40%; }
@keyframes skel { to { background-position: -200% 0; } }
@media (prefers-reduced-motion: reduce) { .skel { animation: none; } }
/* ---- Шаг 5 (UX-9, §5): слова слева, фразы справа, сводка карточками, квадрат слоя, уведомление ---- */
.step5-split { display: grid; grid-template-columns: 200px minmax(0, 1fr); gap: 16px; align-items: start; }
.step5-split[data-single] { grid-template-columns: minmax(0, 1fr); }
.step5-main { display: grid; gap: 12px; min-width: 0; align-content: start; }
.step5-groups { position: sticky; top: 16px; max-height: calc(100vh - 32px); overflow-y: auto; display: grid; gap: 6px; align-content: start; }
.g-order { display: flex; gap: 12px; font-size: 12px; }
.g-order a { color: var(--ink-2); text-decoration: none; }
.g-order a[aria-current="true"] { color: var(--ink); font-weight: 700; }
.step5-groups .list2 a { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 0 8px; padding-left: 8px; border-left: 2px solid transparent; color: var(--ink); text-decoration: none; }
.step5-groups .list2 a:hover { background: var(--surface-2); }
.step5-groups .list2 a[aria-current="true"] { border-left-color: var(--blue); }
.step5-groups .list2 a:focus-visible { outline: 2px solid var(--blue); outline-offset: -2px; }
.g-name { overflow-wrap: anywhere; }
.g-n { text-align: right; }
.step5-groups .sub { grid-column: 1 / -1; margin-top: 0; }
.col-sq { width: 56px; text-align: center; }
#step5-table td.cell-act { width: 1%; }
.act-row[data-nowrap] { flex-wrap: nowrap; }
/* Квадрат слоя: одного нейтрального цвета, смысл несёт цифра; подсказка с полной причиной — по наведению и по фокусу с клавиатуры */
.badge[data-sq] { position: relative; overflow: visible; width: 24px; height: 24px; padding: 0; border-radius: 2px; justify-content: center; font: 600 12px var(--sans);
  cursor: help; }
.badge[data-sq]:not([data-flag]) { background: var(--surface-2); color: var(--ink); border-color: var(--line-2); }   /* жёлтая «!» непроверенного — из app.css */
.badge[data-sq]::first-letter { color: inherit; }
.badge[data-sq][data-layer="0"] { border-style: dashed; color: var(--ink-2); }
.badge[data-sq]:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.badge[data-sq] .tip { display: none; position: absolute; z-index: 40; right: calc(100% + 8px); top: 50%; transform: translateY(-50%); width: max-content; max-width: 260px;
  padding: 8px 10px; background: var(--ink); color: #fff; font: 400 12px/1.35 var(--sans); text-align: left; white-space: normal; text-transform: none; letter-spacing: 0; box-shadow: 0 4px 12px rgba(0, 0, 0, .25); }
.badge[data-sq]:hover .tip, .badge[data-sq]:focus .tip { display: grid; gap: 4px; }
.badge[data-sq] .tip b { font-weight: 600; }
.badge[data-count] { margin-left: 2px; font: 500 11px var(--sans); }
/* Сводка «Что вырезано»: карточка на слой, до пяти самых частотных фраз, «Все N» (образец — пин № 381) */
.cuts-summary > summary { display: flex; align-items: center; min-height: 32px; cursor: pointer; list-style: none; font-weight: 600; }
.cuts-summary > summary::-webkit-details-marker { display: none; }
.cuts-summary > summary::before { content: "▸"; display: inline-block; width: 1.1em; }
.cuts-summary[open] > summary::before { content: "▾"; }
.cuts-summary > summary:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.main .cut-cards { list-style: none; margin: 10px 0 0; padding: 0; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; }
@media (max-width: 1100px) { .main .cut-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.cut-card { display: grid; align-content: start; gap: 4px; min-width: 0; padding: 10px 12px; border: 1px solid var(--line); background: var(--surface); }
.cut-card[data-empty] { color: var(--ink-2); }
.cut-card header { display: flex; align-items: center; gap: 8px; }
.cut-card h3 { font: 600 14px/1.2 var(--sans); }
.cut-card .sub { margin-top: 0; }
.cut-total { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 6px; }
.cut-total b { font-size: 22px; font-weight: 500; }
.cut-total .sub { display: inline; }
.main .cut-top { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: minmax(0, 1fr); }
.cut-top li { display: flex; justify-content: space-between; gap: 8px; border-top: 1px solid var(--border); font-size: 12px; line-height: 22px; }
.cut-top li > span:first-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cut-body { min-height: 110px; }                       /* пять строк по 22 px: пустой или неполный список не меняет высоту карточки */
.cut-card footer { display: flex; flex-wrap: wrap; align-content: flex-start; gap: 6px; min-height: 32px; }
.bulk-bar { row-gap: 4px; }
.bulk-bar .bulk-note { flex-basis: 100%; margin: 0; min-height: 20px; font-size: 13px; line-height: 20px; color: var(--ink-2); }   /* строка стоит всегда: подпись разницы чисел не двигает таблицу */
.state-slot { min-height: 41px; display: grid; align-content: center; }   /* состояние результата («актуален» / «устарел») занимает одно и то же место: смена не двигает таблицу */
.state-ok { color: var(--ink-2); font-size: 13px; }
.strip-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; min-height: 32px; }
/* Уведомление о результате действия: у нижнего края окна над строкой выбора, таблицу не сдвигает; успех гаснет сам */
.toast { position: fixed; z-index: 65; left: 50%; bottom: 76px; transform: translateX(-50%); margin: 0; max-width: min(640px, calc(100vw - 48px)); box-shadow: 0 4px 16px rgba(0, 0, 0, .18); }
.toast[data-fade] { animation: toast-out .4s ease 9s forwards; }
@keyframes toast-out { to { opacity: 0; visibility: hidden; } }
@media (prefers-reduced-motion: reduce) { .toast[data-fade] { animation-duration: 0s; } }

/* ---- Шаг 1, файлы (UX-11, §9): зона перетаскивания и под ней строки с состоянием (образцы — пины № 441, 418, 471). Состояние читается
   по значку и словам, цвет только дополняет (п.5); размер файла не показываем ---- */
.dropzone { display: grid; gap: 4px; padding: 12px 16px; border: 1px dashed var(--line-2); background: var(--surface-2); }
.dropzone[data-over] { border: 1px solid var(--blue); background: color-mix(in srgb, var(--blue) 6%, var(--surface)); }
.dropzone:focus-within { outline: 2px solid var(--blue); outline-offset: 2px; }
.main .file-list { list-style: none; margin: 0; padding: 0; display: grid; }
.file-row { display: grid; align-content: center; gap: 2px; min-height: 44px; padding: 8px 0; border-bottom: 1px solid var(--border); }
.file-row:last-child { border-bottom: 0; }
.file-main { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; }
.file-name { font-weight: 600; overflow-wrap: anywhere; }
.file-state { display: inline-flex; align-items: baseline; gap: 6px; }
.file-state[data-kind="error"] { color: var(--danger); }
.file-state .mark { flex: none; width: 1.1em; text-align: center; font-weight: 700; }
.file-state .mark--spin { align-self: center; width: 10px; height: 10px; border: 2px solid var(--line-2); border-top-color: var(--blue); border-radius: 50%; animation: spin .8s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .file-state .mark--spin { animation: none; } }
.file-replace { display: flex; align-items: center; gap: 8px; }
.file-replace[data-js] input[type="file"] { display: none; }   /* со скриптом кнопка сама открывает выбор файла */
.file-row [data-reading] b { font-weight: 600; font-variant-numeric: tabular-nums; color: var(--ink-2); }
.file-actions { display: grid; gap: 8px; margin-top: 6px; }
.file-actions .form { flex-direction: row; flex-wrap: wrap; align-items: center; gap: 8px; }

/* ---- Банк файлов (W-13, §10.2): десять колонок в рабочей области на 1280 — ячейки плотнее, «Задача» не уже 112 px, «Тип» переносится по словам ---- */
#bank-filters label { white-space: nowrap; }
#bank-table th, #bank-table td { padding-inline: 6px; }
#bank-table td:nth-child(2), #bank-table td:nth-child(3) { min-width: 82px; overflow-wrap: break-word; }   /* слово не режется по буквам */
/* Имя файла переносится в местах, расставленных в шаблоне (после «_», «.», «-»); посреди слова — только когда места нет совсем.
   `anywhere` здесь нельзя: он сводит минимальную ширину колонки к одной букве, и браузер рвёт имя при свободном месте справа. */
#bank-table time { white-space: nowrap; }                                         /* дата не рвётся по дефису */
#bank-table th:nth-child(9), #bank-table td:nth-child(9) { min-width: 100px; }
#bank-table td:last-child { width: 1%; padding-inline-end: 0; }

/* Блок «Последнее подтверждённое ядро» категории, таблицы бренда и шага 6, строка ядра на шаге 1 (UX-19, макет `.sec-h`, `.list`, `.coreline`).
   Без карточки: у `.card` отступ 18 px сдвигал текст и таблицу от края заголовка и полосы шагов, общий `.card` не трогаем. Рамка `.list-frame` —
   как `.list` «Моей работы»: 1 px, скругление 8 px, шапка 36 px на --soft-2, строка от 48 px, текст 13,5 px, отступ ячейки 16 px. */
.flat-block { display: grid; gap: 8px; min-width: 0; }
.flat-block > header { display: flex; align-items: baseline; gap: 12px; padding: 0; }
.flat-block > header h2 { font-size: 15px; letter-spacing: normal; }
.flat-block > header .group-title { margin: 0; font: 400 12px/1.45 var(--sans); }   /* бренд: серая подпись «Категории» 12 px (макет `.gt`), не заголовок */
.flat-block > header a { font-size: 13px; }
.list-frame { border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; min-width: 0; }
.list-frame .table { width: 100%; margin: 0; font-size: 13.5px; border-collapse: collapse; }
.list-frame .table thead { background: var(--soft-2); }
.list-frame .table th { height: 36px; padding: 0 0 0 16px; font-weight: 400; border-bottom: 1px solid var(--line); }
.list-frame .table td { padding: 0 0 0 16px; }
.list-frame .table tbody tr { height: 48px; border-bottom: 1px solid var(--line); }
.list-frame .table tbody tr:last-child { border-bottom: 0; }
.list-frame .table tbody tr:hover { background: var(--soft-2); }
.list-frame .table :is(th, td):last-child { padding-right: 16px; }
.list-frame .table .col-act { text-align: right; white-space: nowrap; }
.list-frame .table td .sub { margin-top: 0; font-size: 12px; }
#category-latest-core .table, #categories .table { table-layout: fixed; }
#category-latest-core th:nth-child(1) { width: 136px; }                                   /* макет: колонки 120 · 70 · 200 · остальное · 100 при зазоре 16: ширина ячейки = колонка + отступ слева 16 */
#category-latest-core th:nth-child(2) { width: 86px; }
#category-latest-core th:nth-child(3) { width: 216px; }
#category-latest-core th:nth-child(5) { width: 116px; }
#categories th:nth-child(2) { width: 96px; }                                              /* макет бренда: остальное · 80 · 200 · 100, так же с отступом ячейки */
#categories th:nth-child(3) { width: 216px; }
#categories th:nth-child(4) { width: 132px; }
.core-line { margin: 0; font-size: 13.5px; }                                              /* на одной линии со строкой контекста над ней (макет `.coreline`) */