/*
 * review.css — единственная таблица стилей операторского экрана.
 *
 * Октябрь 2026: редизайн. Палитра больше не заморожена списком hex-значений
 * (D-02 снят решением оператора) -- вместо этого ВСЕ цвета живут токенами в
 * :root ниже, а правила и шаблоны ссылаются на них через var(--...). Новый
 * цвет = новый токен здесь, не литерал в правиле (тест
 * test_review_css_colors_live_only_in_root_tokens это держит).
 *
 * Основа -- спокойный светлый рабочий интерфейс (ориентир Airtable из
 * awesome-design-md): белые поверхности на мягком сером холсте, тёмные
 * чернила, тонкие линии вместо теней, один акцентный синий. Цвета состояний
 * (успех/внимание/ошибка/выбыло) сохраняют прежние смыслы.
 */
:root {
  --canvas:#f4f5f7; --surface:#ffffff; --surface-soft:#f8f9fb; --surface-sunken:#eceef2;
  --hairline:#e2e5ea; --hairline-strong:#c6cbd3;
  --ink:#171b22; --ink-muted:#4b5260; --ink-subtle:#6f7682;
  --accent:#2457d6; --accent-hover:#1c46b0; --accent-soft:#eaf0fd;
  --violet:#6a46c2; --violet-hover:#5636a6; --violet-soft:#f1ecfb;
  --success:#1b7f49; --success-hover:#156a3c; --success-soft:#e8f5ed;
  --warning:#b25d07; --warning-soft:#fdf2e3;
  --danger:#c4352b; --danger-ink:#a52a21; --danger-soft:#fcecea;
  --neutral:#687180;
  --note-soft:#fdf6e1; --note-line:#ecc561; --note-ink:#5e4505; --field-auto:#fff8d6;
  --shadow-pop:0 12px 32px rgba(23,27,34,.16), 0 2px 6px rgba(23,27,34,.08);
  --radius:10px; --radius-sm:6px;
  --font:"Onest","Segoe UI",system-ui,-apple-system,Roboto,Arial,sans-serif;
  --mono:"JetBrains Mono",Consolas,"Courier New",monospace;
  --sidebar-w:240px;
}
* { box-sizing: border-box; }
html { -webkit-text-size-adjust:100%; }
body { margin:0; font-family:var(--font); font-size:14px; line-height:1.5; color:var(--ink);
       background:var(--canvas); -webkit-font-smoothing:antialiased; }
::selection { background:var(--accent-soft); color:var(--ink); }
a { color:var(--accent); text-underline-offset:2px; }
a:hover { color:var(--accent-hover); }
h1 { font-size:22px; font-weight:650; letter-spacing:-.02em; line-height:1.25; margin:0 0 4px; }
h2 { font-size:16px; font-weight:650; letter-spacing:-.01em; line-height:1.3; }
button, input, select, textarea { font-family:inherit; }
td, th, .eligible-count, .bridge-count, .funnel-count, .tab-count { font-variant-numeric:tabular-nums; }
:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
* { scrollbar-width:thin; scrollbar-color:var(--hairline-strong) transparent; }

/* ── Каркас: боковое меню + рабочая область ───────────────────────────── */
.app { display:grid; grid-template-columns:var(--sidebar-w) minmax(0,1fr); min-height:100vh; }
.sidebar { position:sticky; top:0; height:100vh; overflow-y:auto; background:var(--surface);
           border-right:1px solid var(--hairline); display:flex; flex-direction:column;
           padding:18px 12px 14px; z-index:200; }
.brand { display:flex; align-items:center; gap:10px; padding:2px 10px 20px; color:var(--ink);
         text-decoration:none; font-weight:700; font-size:16px; letter-spacing:-.02em; }
.brand:hover { color:var(--ink); }
.brand img { width:28px; height:28px; border-radius:7px; }
.nav-group { margin-bottom:20px; }
.nav-group-title { font-size:12px; font-weight:600; color:var(--ink-subtle); padding:0 10px 6px; }
.nav-link { display:flex; align-items:center; gap:10px; padding:7px 10px; border-radius:var(--radius-sm);
            color:var(--ink-muted); text-decoration:none; font-size:14px; font-weight:500;
            transition:background-color .15s ease, color .15s ease; }
.nav-link:hover { background:var(--surface-soft); color:var(--ink); }
.nav-link.is-active { background:var(--accent-soft); color:var(--accent); font-weight:600; }
.nav-link svg, .logout-button svg { width:18px; height:18px; flex:none; stroke:currentColor; fill:none;
            stroke-width:1.75; stroke-linecap:round; stroke-linejoin:round; }
.step-num { width:20px; height:20px; flex:none; border-radius:50%; display:inline-grid; place-items:center;
            font-size:11px; font-weight:700; border:1.5px solid var(--hairline-strong); color:var(--ink-subtle);
            background:var(--surface); position:relative; }
.nav-link.is-active .step-num { background:var(--accent); border-color:var(--accent); color:var(--surface); }
/* Шаги связаны вертикальной линией -- видно, что это последовательность. */
.nav-steps { position:relative; }
.nav-steps::before { content:""; position:absolute; left:19px; top:18px; bottom:18px; width:1.5px;
                     background:var(--hairline); }
.sidebar-foot { margin-top:auto; padding-top:12px; border-top:1px solid var(--hairline); }
.logout-form { margin:0 }
.logout-button { width:100%; display:flex; align-items:center; gap:10px; background:transparent;
                 color:var(--ink-muted); border:none; border-radius:var(--radius-sm); padding:7px 10px;
                 font-size:14px; font-weight:500; cursor:pointer; text-align:left; }
.logout-button:hover { background:var(--surface-soft); color:var(--ink); }
.main { min-width:0; display:flex; flex-direction:column; }
.dev-banner { background:var(--note-soft); border-bottom:1px solid var(--note-line); color:var(--note-ink);
              padding:8px 24px; font-size:13px; }
.dev-banner a { color:var(--note-ink); }
.dev-banner-sub { font-size:12px; }

/* Шапка шага: где я, что здесь делать, куда дальше. */
.stepbar { background:var(--surface); border-bottom:1px solid var(--hairline); padding:16px 24px 18px; }
.stepbar-track { display:flex; align-items:center; gap:4px; flex-wrap:wrap; margin:0 0 12px;
                 padding:0; list-style:none; font-size:13px; color:var(--ink-subtle); }
.stepbar-track a { color:var(--ink-subtle); text-decoration:none; padding:3px 10px; border-radius:999px; }
.stepbar-track a:hover { background:var(--surface-soft); color:var(--ink); }
.stepbar-track a.is-current { background:var(--accent-soft); color:var(--accent); font-weight:600; }
.stepbar-track .sep { color:var(--hairline-strong); }
.stepbar-row { display:flex; align-items:flex-end; justify-content:space-between; gap:16px; flex-wrap:wrap; }
.stepbar-title { margin:0; }
.stepbar-hint { margin:4px 0 0; color:var(--ink-muted); font-size:14px; max-width:72ch; }
.btn-next { display:inline-flex; align-items:center; gap:8px; background:var(--surface); color:var(--ink);
            border:1px solid var(--hairline-strong); border-radius:var(--radius-sm); padding:8px 14px;
            font-size:14px; font-weight:600; text-decoration:none; white-space:nowrap;
            transition:border-color .15s ease, background-color .15s ease; }
.btn-next:hover { border-color:var(--ink-subtle); background:var(--surface-soft); color:var(--ink); }
.btn-next svg { width:16px; height:16px; stroke:currentColor; fill:none; stroke-width:2;
                stroke-linecap:round; stroke-linejoin:round; transition:transform .25s cubic-bezier(.16,1,.3,1); }
.btn-next:hover svg { transform:translateX(3px); }
.content { padding:0 0 40px; }

@media (max-width: 900px) {
  .app { grid-template-columns:1fr; }
  .sidebar { height:auto; flex-direction:row; align-items:center; gap:4px; padding:8px 12px;
             border-right:none; border-bottom:1px solid var(--hairline); overflow-x:auto; overflow-y:hidden; }
  .brand { padding:0 6px 0 0; }
  .brand span, .nav-group-title, .nav-steps::before, .logout-button span { display:none; }
  .sidebar nav { display:flex; gap:4px; }
  .nav-group, .nav-steps { display:flex; gap:2px; margin:0; }
  .companies-tabs, .extraction-tabs, .lwe-tabs { overflow-x:auto; white-space:nowrap; }
  .companies-header-right { flex-wrap:wrap; }
  .nav-link { white-space:nowrap; padding:6px 8px; }
  .sidebar-foot { margin:0 0 0 auto; padding:0; border:none; }
  .stepbar, .dev-banner, .legend, .note { padding-left:16px; padding-right:16px; }
}

.legend { background:var(--surface);border-bottom:1px solid var(--hairline);padding:10px 24px;font-size:13px;color:var(--ink-muted);display:flex;flex-wrap:wrap;gap:8px 20px;align-items:center }
.legend-swatch { display:inline-block; width:12px; height:12px; border-radius:3px; border:2px solid; vertical-align:-1px; margin-right:6px; }
.legend-swatch.status-verified { border-color:var(--success); background:var(--success-soft) }
.legend-swatch.status-auto     { border-color:var(--warning); background:var(--field-auto) }
.legend-swatch.status-empty    { border-color:var(--danger); background:var(--danger-soft) }
.note { background:var(--note-soft);border-bottom:1px solid var(--note-line);padding:10px 24px;font-size:13px;color:var(--note-ink);margin:0 }
.ati-section { margin:16px 24px }
.ati-label { background:var(--surface);color:var(--ink);padding:12px 18px;border:1px solid var(--hairline);border-bottom:none;border-radius:var(--radius) var(--radius) 0 0;font-size:15px;font-weight:650 }
.doc-block { background:var(--surface);border:1px solid var(--hairline);border-radius:0 0 var(--radius) var(--radius);
             overflow:hidden;margin-bottom:4px }
.doc-name { background:var(--surface-soft);padding:6px 18px;font-size:12px;color:var(--ink-muted);border-bottom:1px solid var(--hairline) }

/* Пропорции по фидбеку пользователя 2026-07-13 (чекпоинт 08-05): левая колонка
   узкая (в неё только копируют данные), средняя — доминирует (заявка должна
   читаться), правая — фиксированная читаемая ширина с переносом OCR-текста. */
.split { display:grid;grid-template-columns:300px minmax(0,1fr) 400px }
.left-col { padding:14px;background:var(--surface-soft);border-right:2px solid var(--hairline) }
.mid-col { padding:14px;overflow-y:auto;max-height:1100px;background:var(--hairline);border-right:2px solid var(--hairline) }
.right-col { padding:14px;overflow-y:auto;max-height:1100px }
.ocr-text { white-space:pre-wrap;word-break:break-word;overflow-wrap:anywhere;
            margin:0;font-family:Consolas,'Courier New',monospace;font-size:13px;
            line-height:1.5;user-select:text }
.tag-load   { background:var(--accent);color:var(--surface);padding:3px 12px;border-radius:4px;font-size:13px;font-weight:bold }
.tag-unload { background:var(--violet);color:var(--surface);padding:3px 12px;border-radius:4px;font-size:13px;font-weight:bold }

/* ── Phase 8 badges (08-UI-SPEC.md) ──────────────────────────────────────── */
/* Shared pill shape — matches .tag-load/.tag-unload exactly */
.badge-pill { display:inline-block;padding:3px 12px;border-radius:4px;font-size:12px;font-weight:bold;color:var(--surface) }

/* Origin badge system (D-14) */
.badge-origin-curated  { background:var(--neutral) }
.badge-origin-provider { background:var(--accent) }
.badge-origin-agent    { background:var(--violet) }
.badge-origin-manual   { background:var(--success) }

/* Status badge system (carried over verbatim from the legend semantics) */
.badge-status-ok      { background:var(--success) }
.badge-status-partial { background:var(--warning) }
.badge-status-failed  { background:var(--danger) }
/* Живая находка приёмки 24-08: третье состояние «проверка недоступна с
   этого узла» -- НЕ ложная красная тревога и не зелёное «работает».
   Серый переиспользован из .badge-origin-curated (новый hex не заводится). */
.badge-status-unknown { background:var(--neutral) }

/* Company flag badges (STATE.md 2026-07-09 lead-quality rules) */
.badge-flag-liquidated { background:var(--neutral);color:var(--surface) }
.badge-flag-x5-magnit  { background:var(--note-line);color:var(--note-ink) }
/* Phase 15.1 (D-03): manually-edited-but-not-yet-approved rows -- reuses
   the existing blue from badge-origin-provider/badge-lead-neutral above
   (no new hex), kept distinct from badge-lead-done's green (#27ae60) so
   "правлено" never reads as "шаг завершён". */
.badge-flag-manual { background:var(--accent);color:var(--surface) }
/* Phase 15.1 Plan 07 (D-13): legacy rows with no owning document -- same
   grey as .badge-flag-liquidated above, both semantically mean "выбывает
   из работы", no new hex introduced. */
.badge-flag-orphan { background:var(--neutral);color:var(--surface) }

/* ── Approval #1 field-status inputs + save CTA (08-05) ──────────────────── */
/* Field border colours mirror the frozen legend above (green/orange/red) —
   ported from build_review_approval_html.py's inp()/point_block() inline-
   style logic, promoted to CSS classes since this screen renders many
   inputs per row via Jinja rather than string-building HTML in Python. */
.field-row { margin-bottom: 9px; }
.field-label { display:block; font-size:11px; color:var(--ink-muted); font-weight:bold; margin-bottom:2px }
.field-input { display:block; width:100%; padding:7px 10px; border-radius:5px; font-size:13px;
                box-sizing:border-box; border:1.5px solid var(--hairline-strong); background:var(--surface-soft) }
.field-input.status-verified { border-color:var(--success); background:var(--success-soft) }
.field-input.status-auto     { border-color:var(--warning); background:var(--field-auto) }
.field-input.status-empty    { border-color:var(--danger); background:var(--danger-soft) }
.point-block { border:1px solid var(--hairline); border-radius:8px; padding:10px; margin-bottom:12px; background:var(--surface) }
.point-head { margin-bottom:8px }
.btn-save-extraction { background:var(--success); color:var(--surface); border:none; padding:8px 22px;
                        border-radius:6px; font-size:14px; font-weight:bold; cursor:pointer }
.btn-save-extraction:hover { background:var(--success-hover) }

/* ── Phase 13 status panel (13-02, D-13a partial contract for Phase 17) ──── */
/* Class names are a contract for the /status partial built in plan 13-04 --
   do not rename here. Colors reuse the existing badge palette above
   (.badge-status-ok/.badge-status-failed), never a new green/red. */
.status-panel { background:var(--surface); border-radius:8px; padding:14px; border:1px solid var(--hairline) }
.status-row { display:flex; align-items:center; gap:10px; padding:8px 12px; border-bottom:1px solid var(--hairline) }
.status-name { font-weight:bold; min-width:190px }
.status-detail { font-size:12px; color:var(--ink-muted); word-break:break-word }
/* Общий вердикт над списком. Добавлено после живой приёмки 13-06-T2: полоски
   в 4px слева оператору не хватило, он не увидел, что система здорова.
   Цвета -- те же из палитры выше, новых зелёного/красного не заводим. */
.status-verdict { padding:12px 14px; border-radius:6px; font-size:16px;
                  font-weight:bold; color:var(--surface); margin-bottom:12px }
.status-verdict.ok   { background:var(--success) }
.status-verdict.fail { background:var(--danger) }
/* Экран остановки (13-06-T3, доработка по требованию оператора). Панель
   состояния при остановке не рисуется вообще -- вместо неё этот экран,
   который сам переходит в «остановлено», когда вебапп перестаёт отвечать. */
.stop-screen { border-radius:8px; padding:22px; margin-bottom:14px; color:var(--surface) }
.stop-screen.stop-waiting { background:var(--warning) }
.stop-screen.stop-done    { background:var(--success) }
.stop-screen.stop-failed  { background:var(--danger) }
.stop-headline { margin:0 0 6px; font-size:20px; font-weight:bold }
.stop-detail   { margin:0; font-size:14px; line-height:1.5 }
.status-actions { padding:12px; border-top:1px solid var(--hairline) }
.btn-stop-all { background:var(--danger); color:var(--surface); border:none; padding:8px 22px;
                border-radius:5px; cursor:pointer }
.btn-stop-all:hover { background:var(--danger-ink) }
/* Приёмка 22-07, дефект №3 (класс DLV-05, feedback_markup_presence_is_not_
   visibility): disabled в разметке уже был верен на обеих ветках рендера
   (status_panel.html), но без этих двух правил задизейбленная кнопка
   красилась в тот же активный красный -- оператор на /status не видел
   недоступность глазами. #6c757d -- тот же серый "недоступно/выбыло",
   что .badge-flag-liquidated/.badge-flag-orphan/.badge-lead-rejected/
   .channel-dot-paused выше в этом же файле; zero new hex (test_review_
   css_introduces_zero_new_hex_values не трогается). Правило :disabled:hover
   идёт ПОСЛЕ :hover и держит тот же серый, чтобы наведение мышью не
   перекрашивало кнопку обратно в активный вид. */
.btn-stop-all:disabled { background:var(--neutral); cursor:not-allowed }
.btn-stop-all:disabled:hover { background:var(--neutral) }
.status-log-link { font-size:12px; color:var(--accent) }
.status-hint { font-size:11px; color:var(--ink-subtle) }
/* Дефект живой приёмки 23.1-08, пункт Ж (доработка): первая версия
   подсказки (<small>, серый 11px, унаследованный от .status-hint выше)
   оператор глазами счёл незаметной и попросил "сделай заметнее". Красный и
   полужирный -- тот же #e74c3c, что .status-row.fail/.status-verdict.fail/
   .badge-status-failed выше в этом файле (новый hex не заводится, тест
   test_review_css_introduces_zero_new_hex_values его уже знает), подложка
   -- тот же #fff5f5, что .field-input.status-empty (тоже не новый hex).
   Специфичность двух классов (.status-hint.ocr-node-hint) сама перебивает
   базовое правило выше без !important. */
.status-hint.ocr-node-hint {
  display:block; font-size:13px; font-weight:bold; color:var(--danger);
  background:var(--danger-soft); padding:6px 10px;
  margin-top:4px;
}

/* ── Phase 15 lead-step badge (15-06, D-13a partial contract for Phase 17) ──
   Five states colored by STATE, not by step number (D-14) -- every hex below
   reuses one of the five colors already used elsewhere above
   (badge-origin-provider / job-status active-orange / badge-status-ok green /
   badge-status-failed red / badge-origin-curated grey) -- no new hex
   introduced for the state palette itself. */
.badge-lead-neutral  { background:var(--accent) }
.badge-lead-active   { background:var(--warning) }
.badge-lead-done     { background:var(--success) }
.badge-lead-error    { background:var(--danger) }
.badge-lead-rejected { background:var(--neutral) }

.lead-step { display:inline-flex; align-items:center; flex-wrap:wrap; gap:8px }
.lead-step-error { color:var(--danger-ink); font-size:12px }
.lead-step-attempts { font-size:11px; color:var(--ink-subtle) }
.lead-step-details { font-size:11px }
.lead-step-details pre { white-space:pre-wrap; word-break:break-word; overflow-wrap:anywhere;
                          margin:4px 0 0; font-family:Consolas,'Courier New',monospace }
.lead-step-next { display:inline-flex; align-items:center }
/* No :hover darken variant -- every other hex in this block is one of the
   five state colors above or an already-established value cited by name in
   PLAN.md (#a94442); a hover-only darker blue would be a genuinely new hex
   with no existing precedent to borrow from, so it is left out rather than
   invented (verification: review.css introduces no hex beyond the five). */
.btn-lead-retry, .btn-lead-next { display:inline-block; background:var(--accent); color:var(--surface);
                                   border:none; border-radius:4px; padding:4px 10px;
                                   font-size:12px; cursor:pointer; text-decoration:none }

/* D-27: row highlight on cross-page anchor navigation ("#lead-row-...",
   base.html's own script below) -- 2s fade from the existing banner yellow
   (.note's own #fff3cd above) to transparent, no new hex. */
.lead-row-flash { animation: lead-row-flash 2s ease-out; }
@keyframes lead-row-flash {
  from { background-color: var(--note-soft); }
  to   { background-color: transparent; }
}

/* ── Phase 17 CRM screen (17-UI-SPEC.md) ──────────────────────────────────
   /companies table + stage chip. Every hex below reuses a color already
   present elsewhere in this file (see palette table in 17-UI-SPEC.md §
   Color) -- zero new hex values introduced (test_review_css_introduces_
   zero_new_hex_values pins this down). Component classes only -- page-
   specific layout (header row, tabs row, search bar) lives in companies.html's
   own inline <style> block, same convention as review_queue.html/
   extraction_review.html. */

/* Stage chip (STAGE-01/02, D-06/D-07) -- deliberately visually distinct
   from .badge-pill (the static lead-step badge, D-06): bigger radius, a
   1px border, a trailing caret, cursor:pointer (the lead-step badge is
   never clickable). Uses the xs spacing token (4px 12px), NOT .badge-pill's
   3px 12px -- the second of the two visual differentiators. */
.stage-chip { display:inline-flex; align-items:center; gap:4px; padding:4px 12px;
              border-radius:6px; font-size:12px; font-weight:700; color:var(--surface);
              border:1px solid rgba(0,0,0,.15); cursor:pointer; }
.stage-chip::after { content:'▾'; }
.stage-chip-menu { display:inline-block; }
.stage-chip-menu summary { list-style:none; cursor:pointer; }
.stage-chip-menu summary::-webkit-details-marker { display:none; }
.stage-chip-options { display:flex; flex-direction:column; gap:8px; margin-top:8px;
                       padding:8px; background:var(--surface); border:1px solid var(--hairline); border-radius:6px; }
.stage-chip-hint { font-size:12px; color:var(--accent); }
.btn-stage-back { display:inline-block; background:var(--canvas); color:var(--ink-muted); border:none;
                  border-radius:4px; padding:4px 10px; font-size:12px; cursor:pointer; }

/* Stage colors -- by STATE, not step number (same philosophy as
   .badge-lead-* above); replied/negotiation deliberately share one hue
   (both mean "a human conversation is happening", distinguished only by
   the chip's label text, never by color). */
.badge-stage-new         { background:var(--neutral) }
.badge-stage-approved    { background:var(--accent) }
.badge-stage-outreach    { background:var(--warning) }
.badge-stage-replied     { background:var(--violet) }
.badge-stage-negotiation { background:var(--violet) }
.badge-stage-contract    { background:var(--success) }
.badge-stage-rejected    { background:var(--danger) }

/* Delivery-status badges (D-20, JRNL contract) -- .badge-status-ok/
   .badge-status-failed already exist above (Phase 8) and are reused as-is
   for "отправлено"/"ошибка"; these two are new, same existing hexes. */
.badge-status-cancelled { background:var(--neutral) }
.badge-status-planned   { background:var(--accent) }

.pause-icon { font-size:12px; margin-left:4px; }

/* Tab bar (CRM-06, D-21) */
.tab-count { background:var(--canvas); color:var(--ink-muted); font-size:12px; border-radius:10px;
             padding:0 8px; line-height:16px; margin-left:4px; }
.tab-active { color:var(--accent); font-weight:700; border-bottom:2px solid var(--accent); }

/* Row states */
.row-check { cursor:pointer; }
.row-selected { background: rgba(41,128,185,.08); }
.row-open { background: var(--accent-soft); }

/* Table surface (first true <table> in this app, CRM-03) */
.companies-table { width:100%; border-collapse:collapse; background:var(--surface); }
.companies-table th { text-align:left; font-size:16px; font-weight:700; padding:8px 16px;
                       border-bottom:1px solid var(--hairline); }
.companies-table td { padding:8px 16px; font-size:13px; border-bottom:1px solid var(--hairline); }
.companies-table tbody tr:hover { background:var(--surface-soft); cursor:pointer; }

/* Plan 17-09 (JRNL-03/D-19/D-26): health-strip container + bridge-hint
   plaque -- the only two new classes this plan needs. health_strip.html's
   own verdict text reuses .status-verdict/.status-log-link/.status-hint
   verbatim (D-26, no forked health logic); .bridge-hint mirrors the exact
   palette companies.html's own .flash uses (fff3cd/f9a825/555) -- zero new
   hex (test_review_css_introduces_zero_new_hex_values pins this down). */
.health-strip { padding:8px 16px; background:var(--surface); border-bottom:1px solid var(--hairline);
                font-size:12px; display:flex; align-items:center; gap:8px; }

/* Plan 17-10 (STAGE-05/D-09/D-15): .row-plaque -- positions the honest
   per-row plaque <tr> (mr_failed/write_failed_after_mr/stage_conflict/
   partial-restore) directly under the affected company row, full table
   width. Colors come from .flash/.flash-error (companies.html's own
   <style> block, D-19 precedent) -- this rule adds zero new hex
   (test_review_css_introduces_zero_new_hex_values pins this down). */
.row-plaque td { padding:0 16px 8px; border-bottom:1px solid var(--hairline); }

/* Plan 17-11 (CRM-04/08, D-22/D-26/D-28/D-29/D-32): the right-hand drawer +
   unified timeline. Every hex below is already declared above in this same
   block (test_review_css_introduces_zero_new_hex_values pins the whole
   file's set down) -- stage-change timeline entries reuse the seven
   .badge-stage-* hexes via discrete .timeline-entry.type-stage.to-*
   modifiers instead of a CSS custom property (no var()/--custom-property
   machinery exists anywhere else in this file, so none is introduced here
   either). */
.drawer-backdrop { position:fixed; top:0; left:0; right:420px; bottom:0;
                    background:rgba(0,0,0,.3); z-index:250; }
.company-drawer { position:fixed; top:0; right:0; height:100vh; width:420px;
                   background:var(--surface); box-shadow:-2px 0 12px rgba(0,0,0,.15);
                   overflow-y:auto; padding:24px; z-index:300; }
.drawer-section { margin-bottom:24px; }
.drawer-header { display:flex; align-items:center; justify-content:space-between;
                  padding-bottom:16px; border-bottom:1px solid var(--hairline); margin-bottom:16px; }
.drawer-header h2 { font-size:16px; font-weight:700; margin:0; }
.drawer-close { color:var(--accent); font-size:13px; text-decoration:none; }
.drawer-section h3 { font-size:16px; font-weight:700; margin:0 0 8px; }
.drawer-address-row { display:flex; flex-direction:column; gap:8px; margin-bottom:8px; }
.drawer-address-text { font-size:13px; }

.next-touch-callout { background:var(--surface-soft); border-radius:6px; padding:8px 12px;
                       margin-bottom:16px; font-size:13px; }

.timeline-entry { display:flex; gap:8px; padding:8px 0; border-left:2px solid transparent;
                   padding-left:12px; font-size:13px; }
.timeline-entry.type-touch      { border-left-color:var(--accent); }
.timeline-entry.type-touch-skip { border-left-color:var(--neutral); opacity:.7; color:var(--ink-subtle); font-style:italic; }
.timeline-entry.type-note       { border-left-color:var(--hairline); background:var(--surface-soft); border-radius:4px;
                                   padding:8px 12px; white-space:pre-wrap; }
/* Phase 26 Plan 09 (OBS-03, T-26-09-04): a recorded reply's own entry --
   reuses #8e44ad (already declared two lines below for .to-replied/
   .to-negotiation, zero new hex) and the same white-space:pre-wrap +
   padded/background treatment .type-note already uses so a long reply
   body wraps instead of breaking the drawer's layout. */
.timeline-entry.type-reply      { border-left-color:var(--violet); background:var(--surface-soft); border-radius:4px;
                                   padding:8px 12px; white-space:pre-wrap; }
.timeline-entry.type-stage.to-new         { border-left-color:var(--neutral); }
.timeline-entry.type-stage.to-approved    { border-left-color:var(--accent); }
.timeline-entry.type-stage.to-outreach    { border-left-color:var(--warning); }
.timeline-entry.type-stage.to-replied     { border-left-color:var(--violet); }
.timeline-entry.type-stage.to-negotiation { border-left-color:var(--violet); }
.timeline-entry.type-stage.to-contract    { border-left-color:var(--success); }
.timeline-entry.type-stage.to-rejected    { border-left-color:var(--danger); }
.timeline-meta { font-size:12px; color:var(--ink-subtle); }

.contact-card { margin-bottom:16px; font-size:13px; }
.contact-channel-row { display:flex; align-items:center; gap:8px; padding:4px 0; flex-wrap:wrap; }
/* Phase 19: the Selectel fix hint is prose, not a chip -- it gets a line of its
   own under the channel instead of running off the drawer's right edge. */
.delivery-fix-hint { flex-basis:100%; }
.channel-dot { width:8px; height:8px; border-radius:50%; display:inline-block; background:var(--neutral); }
.channel-dot-enabled     { background:var(--success); }
.channel-dot-opt_out     { background:var(--danger); }
.channel-dot-needs_human { background:var(--warning); }
/* review IN-03: gray for "paused" is a DELIBERATE choice, pinned explicitly
   (same #6c757d the bare .channel-dot fallback uses -- zero new hex,
   test_review_css_introduces_zero_new_hex_values). All four channel states
   now have a declared rule; only a genuinely unknown state falls through
   to the undeclared base dot. */
.channel-dot-paused      { background:var(--neutral); }

.note-entry { font-size:13px; white-space:pre-wrap; background:var(--surface-soft); border:1px solid var(--hairline);
              border-radius:4px; padding:8px 12px; margin-bottom:8px; }

/* Plan 17-13 (CRM-07, D-17/D-18): mass-action bar -- hidden by default
   (companies.html's own inline script toggles `.active` on ≥1 row-check),
   zero new hex (test_review_css_introduces_zero_new_hex_values pins this
   down): #fff is the table's own surface color, the same value
   `.stage-chip-options`/`.company-drawer` already use above. */
.mass-action-bar { display:none; max-width:1280px; margin:0 auto 8px; padding:8px 16px;
                    background:var(--surface); border-radius:6px; align-items:center; gap:16px; }
.mass-action-bar.active { display:flex; }
.bulk-report { font-size:12px; font-weight:400; color:var(--ink-muted); }

/* ── Phase 19 Selectel delivery status ── */
/* Exactly four rules, zero new hex (test_review_css_introduces_zero_new_hex_values):
   .badge-status-spam reuses the #f9a825/#5c4400 pair already declared for
   .badge-flag-x5-magnit above (19-UI-SPEC.md § Color, D-02/D-04/D-06's spam
   complaint needs to be categorically distinct from a plain bounce). The
   other three rules reuse #e67e22 (badge-status-partial's own hex, already
   used for "in progress/needs attention") -- .selectel-poll-stale is
   consumed by a later plan's sync-status line (D-07), the two
   .timeline-entry rules by the D-04/D-06 auto-action trace entries (plans
   19-04/19-06) -- declared here so this file is touched exactly once for
   the whole phase. */
.badge-status-spam { background:var(--note-line); color:var(--note-ink); }
.selectel-poll-stale { color:var(--warning); }
.timeline-entry.type-channel-off   { border-left-color:var(--warning); }
.timeline-entry.type-spam-suppress { border-left-color:var(--note-line); }

/* ── Редизайн 2026-10: общие компоненты ───────────────────────────────────
   Раньше каждый экран нёс свою копию .btn-accent/.flash/.card/.empty-state
   в собственном <style> с разными отступами; теперь они живут здесь одни
   на всех, а копии из шаблонов убраны. */
.screen { max-width:960px; margin:24px auto; padding:0 24px; }
.card, .export-panel, .queue-card, .lead-noemail-card, .db-status-group, .db-status-migration-card {
  background:var(--surface); border:1px solid var(--hairline); border-radius:var(--radius);
  padding:20px; margin-bottom:16px; }
.card h2, .export-panel h2 { margin:0 0 14px; font-size:16px; }

.btn-accent, .btn-danger, .btn-mr, .btn-save-extraction, .btn-stop-all {
  display:inline-flex; align-items:center; justify-content:center; gap:6px; border:1px solid transparent;
  border-radius:var(--radius-sm); padding:8px 16px; font-size:14px; font-weight:600; line-height:1.3;
  cursor:pointer; text-decoration:none; color:var(--surface);
  transition:background-color .15s ease, box-shadow .15s ease; }
.btn-accent, .btn-save-extraction { background:var(--accent); }
.btn-accent:hover, .btn-save-extraction:hover { background:var(--accent-hover); }
.btn-danger, .btn-stop-all { background:var(--danger); }
.btn-danger:hover, .btn-stop-all:hover { background:var(--danger-ink); }
.btn-mr { background:var(--violet); }
.btn-mr:hover { background:var(--violet-hover); }
.btn-accent:disabled, .btn-danger:disabled, .btn-mr:disabled { background:var(--surface-sunken); color:var(--ink-subtle); cursor:not-allowed; }
.btn-stop-all:disabled, .btn-stop-all:disabled:hover { background:var(--neutral); cursor:not-allowed; }
.btn-lead-retry, .btn-lead-next { background:var(--accent-soft); color:var(--accent); font-weight:600;
  border-radius:var(--radius-sm); padding:5px 10px; font-size:13px; }
.btn-lead-retry:hover, .btn-lead-next:hover { background:var(--accent); color:var(--surface); }
.btn-stage-back, .btn-lead-close, .btn-close-extraction {
  display:inline-flex; align-items:center; background:var(--surface); color:var(--ink-muted);
  border:1px solid var(--hairline-strong); border-radius:var(--radius-sm); padding:5px 10px;
  font-size:13px; font-weight:500; cursor:pointer; }
.btn-stage-back:hover, .btn-lead-close:hover, .btn-close-extraction:hover { border-color:var(--ink-subtle); color:var(--ink); }

.badge-pill, .tag-load, .tag-unload { border-radius:999px; padding:2px 10px; font-size:12px; font-weight:600;
  letter-spacing:.01em; line-height:18px; }
.stage-chip { border-radius:999px; padding:3px 10px 3px 12px; font-weight:600; border-color:transparent; }
.stage-chip-menu { position:relative; }
.stage-chip-options { box-shadow:var(--shadow-pop); border-color:var(--hairline); border-radius:var(--radius);
  position:absolute; z-index:20; min-width:180px; }

.flash, .banner, .bridge-hint { background:var(--note-soft); border:1px solid var(--note-line);
  color:var(--note-ink); border-radius:var(--radius-sm); padding:10px 14px; font-size:13px; margin:12px 0; }
.flash-error { background:var(--danger-soft); border:1px solid var(--danger); color:var(--danger-ink);
  border-radius:var(--radius-sm); padding:10px 14px; font-size:13px; margin:12px 0; }
.banner code { background:var(--surface); padding:1px 6px; border-radius:4px; font-family:var(--mono); font-size:12px; }

.empty-state { text-align:center; padding:56px 16px; color:var(--ink-muted); }
.empty-state h2 { margin:0 0 6px; color:var(--ink); }
.empty-state p { color:var(--ink-muted); font-size:14px; margin:0 auto 16px; max-width:52ch; }

input[type=text], input[type=search], input[type=email], input[type=password], input[type=number],
input:not([type]), select, textarea {
  font-size:14px; color:var(--ink); background:var(--surface); border:1px solid var(--hairline-strong);
  border-radius:var(--radius-sm); padding:7px 10px; transition:border-color .15s ease, box-shadow .15s ease; }
input:focus, select:focus, textarea:focus { outline:none; border-color:var(--accent)!important;
  box-shadow:0 0 0 3px var(--accent-soft); }
input::placeholder, textarea::placeholder { color:var(--ink-subtle); }
.field-input { font-size:14px; border-radius:var(--radius-sm); }

/* Шапки экранов без шага (Компании, Лиды без почты, Состояние...). */
.companies-header, .lwe-header, .db-status-header { padding:0 24px!important; margin:24px auto 0!important; }
.companies-header h1, .lwe-header h1, .db-status-header h1 { font-size:22px; font-weight:650; }
.content > h1 { margin:24px 24px 16px; }

.companies-table { border:1px solid var(--hairline); border-radius:var(--radius); overflow:hidden;
  border-collapse:separate; border-spacing:0; }
.companies-table th { font-size:12px; font-weight:600; color:var(--ink-subtle); background:var(--surface-soft);
  padding:10px 16px; border-bottom:1px solid var(--hairline); }
.companies-table td { font-size:14px; padding:10px 16px; border-bottom:1px solid var(--hairline); }
.companies-table tbody tr:last-child td { border-bottom:none; }
.companies-table tbody tr:hover { background:var(--surface-soft); }
.tab-active { color:var(--accent)!important; font-weight:600!important; border-bottom:2px solid var(--accent); }
.tab-count { background:var(--surface-sunken); color:var(--ink-muted); padding:1px 7px; }

.status-panel { border-radius:var(--radius); border-color:var(--hairline); padding:0; overflow:hidden; }
.status-row { padding:10px 16px; border-bottom:1px solid var(--hairline); }
.status-row.ok .status-name::before, .status-row.fail .status-name::before {
  content:""; display:inline-block; width:8px; height:8px; border-radius:50%; margin-right:8px; vertical-align:1px; }
.status-row.ok .status-name::before { background:var(--success); }
.status-row.fail .status-name::before { background:var(--danger); }
.status-verdict { border-radius:var(--radius); font-size:15px; padding:12px 16px; }
.status-hint.ocr-node-hint { border:1px solid var(--danger); border-radius:var(--radius-sm); }
.stop-screen { border-radius:var(--radius); }
.health-strip { padding:8px 24px; }
.mass-action-bar { border:1px solid var(--hairline); box-shadow:var(--shadow-pop); border-radius:var(--radius); }
.company-drawer { box-shadow:var(--shadow-pop); }
.drawer-backdrop { background:rgba(23,27,34,.32); }
.point-block { border-radius:var(--radius); border-color:var(--hairline); }
.left-col { border-right:1px solid var(--hairline); }
.mid-col { background:var(--surface-sunken); border-right:1px solid var(--hairline); }
.ocr-text { font-family:var(--mono); font-size:12.5px; }

/* Содержимое экранов выровнено по левому краю вместе с шапкой шага --
   раньше каждый экран центрировал свою колонку своей ширины, и края
   прыгали от страницы к странице. */
.screen, .lwe-header, .lwe-flash-wrap, .lwe-tabs, .lwe-list, .lwe-empty, .lwe-csv-bar,
.companies-header, .companies-tabs, .vertical-switch, .companies-search, .companies-table-wrap,
.extraction-tabs, .extraction-search, .pagination-bar, .ocr-error-intake-link,
.db-status-header, .db-status-groups, .db-status-migration {
  margin-left:0!important; margin-right:0!important; padding-left:24px!important; padding-right:24px!important; }
.screen { max-width:1008px; }
.lwe-header, .lwe-flash-wrap, .lwe-tabs, .lwe-list, .lwe-empty, .lwe-csv-bar { max-width:1008px; }
.pagination-bar { justify-content:flex-start; }
@media (max-width: 900px) {
  .screen, .lwe-header, .lwe-flash-wrap, .lwe-tabs, .lwe-list, .lwe-empty, .lwe-csv-bar,
  .companies-header, .companies-tabs, .vertical-switch, .companies-search, .companies-table-wrap,
  .extraction-tabs, .extraction-search, .pagination-bar, .ocr-error-intake-link,
  .db-status-header, .db-status-groups, .db-status-migration { padding-left:16px!important; padding-right:16px!important; }
  .companies-header { flex-wrap:wrap; }
  .companies-table-wrap { overflow-x:auto; }
  .split { grid-template-columns:1fr; }
}

/* Строка таблицы компаний на живых данных (2026-10-12): название сверху,
   шаг лида строкой под ним; стадия, доставка и дата не переносятся. */
.cell-company strong { display:block; margin-bottom:4px; }
.cell-company .lead-step { gap:6px; }
.cell-nowrap { white-space:nowrap; }
.stage-chip, .badge-pill { white-space:nowrap; }
.pause-icon { display:inline-block; margin-left:6px; padding:1px 7px; border-radius:999px; font-size:11px;
  font-weight:600; color:var(--ink-muted); background:var(--surface-sunken); vertical-align:middle; }
.lead-step-attempts { color:var(--ink-subtle); font-size:12px; }
.companies-table time { color:var(--ink-muted); }

/* Вторичные кнопки: обводка вместо заливки, чтобы рядом с главным
   действием не стояло четыре одинаково громких кнопки. */
.btn-ghost, .btn-danger-ghost {
  display:inline-flex; align-items:center; gap:6px; background:var(--surface); color:var(--ink);
  border:1px solid var(--hairline-strong); border-radius:var(--radius-sm); padding:7px 14px;
  font-size:14px; font-weight:500; line-height:1.3; cursor:pointer; user-select:none;
  transition:background-color .15s ease, border-color .15s ease; }
.btn-ghost:hover { background:var(--surface-soft); border-color:var(--ink-subtle); }
.btn-danger-ghost { color:var(--danger-ink); }
.btn-danger-ghost:hover { background:var(--danger-soft); border-color:var(--danger); }
/* Метки «откуда поле» и «откуда данные» -- справка, а не тревога: тихие. */
.field-source-badge, .qc-tags .badge-pill[class*="badge-origin-"], .candidate-flags .badge-lead-neutral {
  background:var(--surface-sunken)!important; color:var(--ink-muted)!important; font-weight:500; }
.field-source-badge { font-size:11px; padding:1px 8px; vertical-align:1px; }

/* Экран «Извлечение»: метки точек -- подпись цветом, а не заливная таблетка. */
.tag-load, .tag-unload { background:none!important; padding:0; border-radius:0; font-size:12px; font-weight:700; letter-spacing:.06em; }
.tag-load { color:var(--accent); }
.tag-unload { color:var(--violet); }
.point-block { background:var(--surface); padding:14px; }
.left-col { background:var(--surface-soft); padding:18px; }
.mid-col, .right-col { padding:18px; }
.field-label { font-size:12px; font-weight:500; color:var(--ink-subtle); margin-bottom:4px; }
.field-input { border-width:1px; }
.field-input.status-verified { background:var(--surface); }
.field-input.status-empty { background:var(--surface); }
