/* Панель управления агентом WEICH.
   Две темы: тёмная (по умолчанию) и светлая. Выбор — атрибут `data-theme` на
   <html>; ставит его инлайн-скрипт в <head> (web/templates/_theme_head.html)
   ДО загрузки этого файла, иначе страница мигает чужой темой.
   Никаких зависимостей — один файл, читается сверху вниз.

   ЦВЕТА — ТОЛЬКО ЧЕРЕЗ ПЕРЕМЕННЫЕ. Хозяин цвета — блоки `:root` ниже; прямой
   hex в правиле — это «дыра», которая в другой теме останется прежней (так
   светлая карточка с тёмной подложкой и появляется). Сторож —
   tests/test_ui_theme.py: hex вне `:root*` и `@font-face` роняет тест. */

/* ── Шрифты ───────────────────────────────────────────────────────────────
   IBM Plex (OFL, fonts/OFL.txt) лежит у нас, а не на Google Fonts: панель
   открывают из РФ, и шрифт с внешнего CDN может не прийти. Только латиница и
   кириллица — остальные подмножества панели не нужны. */
@font-face { font-family: "IBM Plex Sans"; font-style: normal; font-weight: 400; font-display: swap;
  src: url(fonts/ibm-plex-sans-cyrillic-400.woff2) format("woff2"); unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; }
@font-face { font-family: "IBM Plex Sans"; font-style: normal; font-weight: 400; font-display: swap;
  src: url(fonts/ibm-plex-sans-latin-400.woff2) format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "IBM Plex Sans"; font-style: normal; font-weight: 500; font-display: swap;
  src: url(fonts/ibm-plex-sans-cyrillic-500.woff2) format("woff2"); unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; }
@font-face { font-family: "IBM Plex Sans"; font-style: normal; font-weight: 500; font-display: swap;
  src: url(fonts/ibm-plex-sans-latin-500.woff2) format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "IBM Plex Sans"; font-style: normal; font-weight: 600; font-display: swap;
  src: url(fonts/ibm-plex-sans-cyrillic-600.woff2) format("woff2"); unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; }
@font-face { font-family: "IBM Plex Sans"; font-style: normal; font-weight: 600; font-display: swap;
  src: url(fonts/ibm-plex-sans-latin-600.woff2) format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "IBM Plex Mono"; font-style: normal; font-weight: 400; font-display: swap;
  src: url(fonts/ibm-plex-mono-cyrillic-400.woff2) format("woff2"); unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; }
@font-face { font-family: "IBM Plex Mono"; font-style: normal; font-weight: 400; font-display: swap;
  src: url(fonts/ibm-plex-mono-latin-400.woff2) format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "IBM Plex Mono"; font-style: normal; font-weight: 500; font-display: swap;
  src: url(fonts/ibm-plex-mono-cyrillic-500.woff2) format("woff2"); unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; }
@font-face { font-family: "IBM Plex Mono"; font-style: normal; font-weight: 500; font-display: swap;
  src: url(fonts/ibm-plex-mono-latin-500.woff2) format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }

/* ── Токены темы ──────────────────────────────────────────────────────────
   Таблица — docs/UI_REDESIGN_SPEC.md §2.1. Отступление одно: `--text-faint`
   темнее/светлее, чем в таблице. Значения из спеки давали контраст подписей
   3.6:1 (тёмная, на карточке) и 2.9:1 (светлая, на фоне) — ниже 4.5:1 для
   мелкого текста, а подписи у нас как раз мелкие.

   Сверх таблицы — производные, без которых правила снова тянули бы hex:
   `--accent-dim` (подложка «своего» и активного), `--accent-soft` (заливка
   выделенного), `--bg-subtle` (плашка внутри панели: в светлой теме
   `--bg-raised` совпадает с панелью, и заливка без рамки пропадала), `--scrim` (затемнение под окном), `--shadow`. */
:root {
  color-scheme: dark;           /* родные контролы: календарь, полосы прокрутки */
  --bg: #0b0d12;
  --bg-panel: #0f121a;
  --bg-raised: #161b26;
  --bg-hover: #1b2130;
  --line: #1c2130;
  --line-strong: #2a3040;
  --text: #e4e7ee;
  --text-dim: #8b93a7;
  --text-faint: #7e8699;
  --accent: #8ab4ff;
  --accent-ink: #0b0d12;
  --accent-dim: #22345a;
  --accent-soft: #141d30;
  --bg-subtle: #161b26;         /* заливка второго уровня внутри панели */
  --ok: #4ade80;
  --warn: #f7c948;
  --err: #ff6b6b;
  --draft: #b48cff;
  --ok-bg: #14301f;
  --warn-bg: #3a2f10;
  --err-bg: #3a1a1a;
  --draft-bg: #24193a;
  --scrim: rgba(0, 0, 0, .6);
  --shadow: 0 12px 40px rgba(0, 0, 0, .45);
  /* Цвет оси метки (agent/labels.AXIS_ORDER) — по нему видно, ЧТО за метка:
     модель, ткань, повод клиента. Классы `.ax-<ось>` ниже. */
  --ax-flag: #ff6b6b;
  --ax-model: #8ab4ff;
  --ax-trigger: #ffa94d;
  --ax-config: #38d9a9;
  --ax-style: #f783ac;
  --ax-fabric: #8ce99a;
  --ax-size: #66d9e8;
  --ax-form: #b197fc;
  --ax-moment: #ffd43b;
  --ax-topic: #a5b4c8;
  --ax-other: #8b93a7;
  /* Значок ▶ поверх миниатюры видео — светлый на любом кадре, в любой теме. */
  --on-media: #ffffff;
  --on-media-shadow: rgba(0, 0, 0, .8);

  --radius: 6px;
  --font: "IBM Plex Sans", -apple-system, "Segoe UI", sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, Menlo, monospace;

  /* Высота прилипшей шапки (вкладки + заголовок страницы). Меряет её
     `syncHeadHeight()` в app.js по живому элементу: вкладки переносятся,
     заголовок бывает в две строки, и зашитое число врало. Значение здесь —
     только до первого замера. */
  --head-h: 110px;
  /* Сколько по вертикали занимает всё, что НЕ прокручивается над колонками
     карточки: шапка плюс отступ содержимого сверху и зазор снизу. По ней
     считается высота колонок — иначе «Сохранить» и «Отправить» не видны
     разом. */
  --top: calc(var(--head-h) + 40px);
}

:root[data-theme="light"] {
  color-scheme: light;
  --bg: #f4f5f7;
  --bg-panel: #ffffff;
  --bg-raised: #ffffff;
  --bg-hover: #eef1f5;
  --line: #dfe3ea;
  --line-strong: #c9cfd8;
  --text: #15181d;
  --text-dim: #5b6270;
  --text-faint: #666d7c;
  --accent: #1f5fbf;
  --accent-ink: #ffffff;
  --accent-dim: #d3e1f7;
  --accent-soft: #eaf1fc;
  --bg-subtle: #f0f2f5;
  --ok: #1e6b34;
  --warn: #7a4b00;
  --err: #9b1c1c;
  --draft: #5b21b6;
  --ok-bg: #e3f1e6;
  --warn-bg: #fdf4d6;
  --err-bg: #fdeaea;
  --draft-bg: #f1eafd;
  --scrim: rgba(21, 24, 29, .35);
  --shadow: 0 12px 32px rgba(21, 24, 29, .14);
  --ax-flag: #c92a2a;
  --ax-model: #1f5fbf;
  --ax-trigger: #d9480f;
  --ax-config: #0b7a5c;
  --ax-style: #c2255c;
  --ax-fabric: #2b8a3e;
  --ax-size: #0b7285;
  --ax-form: #6741d9;
  --ax-moment: #a87400;
  --ax-topic: #495768;
  --ax-other: #5b6270;
  --on-media: #ffffff;
  --on-media-shadow: rgba(0, 0, 0, .8);
}

* { box-sizing: border-box; }

/* Атрибут `hidden` должен ПОБЕЖДАТЬ любое наше правило отображения.
   Без этого панель массовых действий висела на экране всегда: JS честно ставил
   `hidden`, а `.select-bar { display: flex }` был сильнее — и «Объединить»,
   «Перевести», «В архив» предлагались, когда не выбрано ни одной карточки.
   Правило общее, потому что ошибка общая: любой блок, который мы прячем
   атрибутом, рискует иметь свой `display`. */
[hidden] { display: none !important; }

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

a { color: var(--accent); text-decoration: none; }
h1, h2, h3 { margin: 0; font-weight: 600; letter-spacing: -0.01em; }
/* Моно — для чисел, сумм, возраста и кода: цифры встают столбиком. */
code, .mono { font-family: var(--mono); font-size: 12px; font-variant-numeric: tabular-nums; }
/* Длинное слово без пробелов (ссылка, код, ник) не должно распирать блок. */
p, li, dd, .card-note, .cell-sub { overflow-wrap: break-word; }

/* ── Каркас ───────────────────────────────────────────────────────────────── */

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

.sidebar {
  width: 232px; flex: 0 0 232px;
  background: var(--bg-panel);
  border-right: 1px solid var(--line);
  display: flex; flex-direction: column;
  position: sticky; top: 0; height: 100vh;
  overflow-y: auto;
}

.brand { display: flex; align-items: center; gap: 12px; padding: 16px 16px 16px; }
.brand-mark {
  width: 28px; height: 28px; border-radius: var(--radius);
  background: var(--accent);
  color: var(--accent-ink); font-weight: 700; font-size: 15px;
  display: grid; place-items: center;
}
.brand-text { display: flex; flex-direction: column; font-weight: 600; line-height: 1.2; letter-spacing: .04em; }
.brand-text em { font-style: normal; font-size: 11px; color: var(--text-faint); font-weight: 400; letter-spacing: 0; }

nav { display: flex; flex-direction: column; gap: 2px; padding: 0 8px; flex: 1; }
.nav-item {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 8px; border-radius: var(--radius);
  color: var(--text-dim); font-size: 14px;
}
.nav-item:hover { background: var(--bg-hover); color: var(--text); }
.nav-item.is-active { background: var(--accent-dim); color: var(--text); font-weight: 500; }
.nav-icon { width: 18px; text-align: center; opacity: 0.8; font-size: 13px; }

.sidebar-foot {
  padding: 12px 16px; border-top: 1px solid var(--line);
  display: flex; align-items: center; justify-content: space-between;
  font-size: 13px; color: var(--text-faint);
}

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

/* ШАПКА ПРИЛИПАЕТ — вся, вкладки вместе с заголовком. В карточке
   «Сохранить изменения» живёт здесь, а «Отправить» — внизу переписки: пока
   шапка уезжала со страницей, видно было либо одну кнопку, либо другую.
   Раньше прилипал только заголовок, а вкладки уезжали, и `--top` (зашитые
   122px) считал их высоту, которой на экране уже не было. Фон обязателен —
   без него сквозь прилипшую шапку просвечивает содержимое. */
.page-head {
  position: sticky; top: 0; z-index: 20;
  background: var(--bg);
}
.head-row {
  display: flex; align-items: stretch; gap: 8px;
  padding: 0 16px 0 24px; border-bottom: 1px solid var(--line);
}
.head-row .tabbar { flex: 1; min-width: 0; padding: 0; border-bottom: none; }
.head-tools { display: flex; align-items: center; gap: 4px; margin-left: auto; }
.topbar {
  display: flex; align-items: center;
  gap: 16px; padding: 12px 24px; border-bottom: 1px solid var(--line);
  background: var(--bg);
}
/* Заголовок прижат к «назад» слева, действия уходят вправо сами. */
/* Длинное имя клиента не переносится по слогам в столбик, а обрезается
   многоточием: действия справа важнее второй строки заголовка. */
.topbar h1 {
  font-size: 19px; margin-right: auto; min-width: min(14em, 40%); flex: 1 1 auto;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.topbar-actions {
  display: flex; gap: 8px; align-items: center; flex-wrap: wrap;
  justify-content: flex-end; flex: 0 1 auto;
}

/* Кнопки-иконки в шапке: тема и (на узком экране) меню. */
.icon-toggle {
  display: inline-grid; place-items: center;
  width: 32px; height: 32px; padding: 0;
  background: none; border: 1px solid transparent; color: var(--text-dim);
}
.icon-toggle:hover { color: var(--text); background: var(--bg-hover); border-color: var(--line); }
.icon-toggle svg { width: 16px; height: 16px; display: block; }
/* Показываем то, ВО ЧТО переключим: в тёмной — солнце, в светлой — луну. */
.theme-toggle .i-moon { display: none; }
:root[data-theme="light"] .theme-toggle .i-sun { display: none; }
:root[data-theme="light"] .theme-toggle .i-moon { display: block; }
.menu-toggle { display: none; font-size: 18px; line-height: 1; }

/* ВО ВСЮ ШИРИНУ ЭКРАНА (владелец 06.10, большой монитор: «канбан
   обрезается на половине экрана, оптимизировать все формы»). Раньше было
   1460px на всё — на 2560 треть экрана пустовала. Теперь ширину держат не
   страницы, а то, что плохо читается широким: пояснения (`.card-note`,
   `.page-lead`) и одиночные поля ввода — правила в конце файла,
   «Большие экраны». */
.content { padding: 24px 24px 64px; max-width: none; }

/* ── Блоки ────────────────────────────────────────────────────────────────── */

.card {
  background: var(--bg-panel); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 16px; margin-bottom: 16px;
}
.card-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px; margin-bottom: 16px; flex-wrap: wrap;
}
.card-head h2 { font-size: 15px; }
.card-note { color: var(--text-dim); font-size: 13px; margin: 0 0 16px; }

.scan-result { border-color: var(--accent-dim); }
.scan-block { margin-top: 12px; color: var(--text-dim); }
.scan-block b { color: var(--text); font-size: 13px; }
.scan-block ul { margin: 8px 0 0; padding-left: 24px; }
.scan-block li { margin: 4px 0; }
.scan-error { color: var(--err); margin: 0 0 8px; }

.grid { display: grid; gap: 16px; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }

.metric { background: var(--bg-raised); border: 1px solid var(--line); border-radius: var(--radius); padding: 16px; }
.metric-value { font-family: var(--mono); font-size: 26px; font-weight: 500; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.metric-label { color: var(--text-dim); font-size: 13px; margin-top: 4px; }

.pill {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 2px 8px; border-radius: 999px; font-size: 12px;
  background: var(--bg-subtle); color: var(--text-dim);
  border: 1px solid var(--line);
}
.dot { width: 7px; height: 7px; border-radius: 50%; background: var(--text-faint); }
.dot.ok { background: var(--ok); }
.dot.warn { background: var(--warn); }
.dot.err { background: var(--err); }

/* Плашка состояния — ОДИН компонент на всю панель: подложка из `*-bg`,
   текст — цветом состояния. Раньше таких было три (ai-badge, nav-badge,
   test-result), каждая со своим rgba, и в светлой теме они темнели. */
.badge {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 1px 8px; border-radius: 999px;
  font-size: 12px; font-weight: 500; line-height: 18px; white-space: nowrap;
  background: var(--bg-subtle); color: var(--text-dim);
}
.badge.ok { background: var(--ok-bg); color: var(--ok); }
.badge.warn { background: var(--warn-bg); color: var(--warn); }
.badge.err { background: var(--err-bg); color: var(--err); }
.badge.draft { background: var(--draft-bg); color: var(--draft); }
.badge.accent { background: var(--accent-dim); color: var(--text); }

/* ── Формы ────────────────────────────────────────────────────────────────── */

.field { margin-bottom: 16px; }
.field label { display: block; font-size: 13px; margin-bottom: 4px; font-weight: 500; color: var(--text-dim); }
.field .help { color: var(--text-faint); font-size: 13px; margin-top: 4px; }
.field .unit { color: var(--text-faint); font-size: 12px; margin-left: 8px; }

/* ПЕРЕЧИСЛЯТЬ ТИПЫ ПОИМЁННО — ошибка. `input[type=search]` в этом списке не
   было, и поле поиска на канбане оставалось без `color`: браузер брал свой
   тёмный по умолчанию, и на тёмном фоне текст был не виден вовсе. Поэтому
   правило теперь обратное — «любое поле ввода, КРОМЕ тех, у которых своя
   природа»: новый тип поля получает вид сам собой, а не ждёт, пока про него
   вспомнят.

   Через `:where()` — у него НУЛЕВАЯ специфичность, и селектор весит как одно
   `input`. Перечисление через `:not(...)` весило бы как семь атрибутов и
   перебило бы стили по классам: `.board-search` потеряла бы свой фон.

   ВЫСОТА 32px у поля и у кнопки — одна: 5 + 20 + 5 + рамка 2. Поля и кнопки
   стоят в одной строке постоянно, и разнобой в два-три пикселя был виден. */
input:where(:not([type=checkbox], [type=radio], [type=range], [type=file],
                 [type=submit], [type=button], [type=color], [type=hidden])),
select, textarea {
  width: 100%; padding: 5px 10px;
  background: var(--bg-raised); color: var(--text);
  border: 1px solid var(--line-strong); border-radius: var(--radius);
  font: inherit; font-size: 14px; line-height: 20px;
}
select { min-height: 32px; }
textarea { line-height: 1.5; }
input::placeholder, textarea::placeholder { color: var(--text-faint); opacity: 1; }
/* Свой крестик у поиска уже есть в разметке — родной убираем, чтобы их не
   было два. */
input[type=search]::-webkit-search-decoration,
input[type=search]::-webkit-search-cancel-button { -webkit-appearance: none; }
/* Фокус — кольцо акцентом 2px, одинаковое у полей и кнопок. У кнопок только
   с клавиатуры (`:focus-visible`): после щелчка мышью кольцо — шум. */
input:focus, select:focus, textarea:focus {
  outline: 2px solid var(--accent); outline-offset: -1px; border-color: var(--accent);
}
button:focus-visible, .btn:focus-visible, a:focus-visible, summary:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px;
}
input[type=checkbox], input[type=radio] { width: 16px; height: 16px; accent-color: var(--accent); }
/* Кнопка выбора файла — родная, серая и другого размера; приводим к обычной. */
input[type=file] { font: inherit; font-size: 13px; color: var(--text-dim); }
input[type=file]::file-selector-button {
  font: inherit; font-size: 14px; line-height: 20px; margin-right: 8px;
  padding: 5px 12px; border-radius: var(--radius); cursor: pointer;
  border: 1px solid var(--line-strong); background: var(--bg-raised); color: var(--text);
}
input[type=file]::file-selector-button:hover { background: var(--bg-hover); }
.check { display: flex; align-items: center; gap: 8px; }

/* Кнопки трёх видов: основная (акцент), обычная (обводка), тихая (`.ghost` —
   только текст, обводка появляется на наведении). Опасная (`.danger`) —
   отдельно: цвет ошибки, чтобы «В архив» не стояло вровень с «Сохранить». */
button, .btn {
  display: inline-block; vertical-align: middle;
  padding: 5px 12px; border-radius: var(--radius);
  border: 1px solid var(--line-strong);
  background: var(--bg-raised); color: var(--text);
  font: inherit; font-size: 14px; line-height: 20px; cursor: pointer;
  text-align: center;
}
/* Ссылка-кнопка центрирует подпись так же, как <button>: блочная ссылка
   держит текст у верхнего края, и на телефоне (высота 44px) «Выгрузить CSV»
   в шапке стояла не по центру. */
a.btn { display: inline-flex; align-items: center; justify-content: center; gap: 4px; white-space: nowrap; }
button:hover, .btn:hover { border-color: var(--text-faint); background: var(--bg-hover); }
button.primary, .btn.primary {
  background: var(--accent); border-color: var(--accent); color: var(--accent-ink); font-weight: 600;
}
button.primary:hover, .btn.primary:hover { background: var(--accent); filter: brightness(1.08); }
button.ghost, .btn.ghost {
  background: transparent; border-color: transparent; color: var(--text-dim);
}
button.ghost:hover, .btn.ghost:hover { color: var(--text); background: var(--bg-hover); border-color: var(--line); }
button.danger, .btn.danger {
  background: transparent; border-color: var(--line-strong); color: var(--err);
}
button.danger:hover, .btn.danger:hover { background: var(--err-bg); border-color: var(--err); }
button.link { background: none; border: none; color: var(--text-faint); padding: 0; font-size: 13px; }
button.link:hover { color: var(--accent); background: none; }
button:disabled, .btn:disabled { opacity: .55; cursor: default; }
button:disabled:hover { border-color: var(--line-strong); background: var(--bg-raised); }
button.primary:disabled:hover { background: var(--accent); filter: none; }

.source-tag { font-size: 11px; color: var(--text-faint); margin-left: 8px; }

/* ── Интеграции ───────────────────────────────────────────────────────────── */

.steps { margin: 0 0 16px; padding-left: 16px; color: var(--text-dim); font-size: 14px; }
.steps li { margin-bottom: 4px; }
.test-result { margin-top: 12px; padding: 8px 12px; border-radius: var(--radius); font-size: 14px; display: none; border: 1px solid transparent; }
.test-result.ok { display: block; background: var(--ok-bg); border-color: var(--ok); }
.test-result.err { display: block; background: var(--err-bg); border-color: var(--err); }
.test-result.warn { display: block; background: var(--warn-bg); border-color: var(--warn); }
.test-result .hint { color: var(--text-dim); margin-top: 4px; font-size: 13px; }

/* ── Вход ─────────────────────────────────────────────────────────────────── */

.auth-page { display: grid; place-items: center; min-height: 100vh; padding: 24px; }
.auth-card { width: 100%; max-width: 380px; background: var(--bg-panel);
  border: 1px solid var(--line); border-radius: var(--radius); padding: 24px; }
.auth-card h1 { font-size: 20px; margin-bottom: 8px; }
.auth-card .sub { color: var(--text-dim); font-size: 14px; margin-bottom: 24px; }
.auth-card button { width: 100%; margin-top: 8px; }
.auth-error { color: var(--err); font-size: 13px; margin-top: 12px; min-height: 18px; }

/* ── Заглушка раздела ─────────────────────────────────────────────────────── */

/* Пустое состояние: заголовок «почему пусто», одна фраза и действие. Не
   пустая рамка — по ней не понять, сломалось или просто ещё нечего. */
.planned, .empty-state { text-align: center; padding: 48px 24px; color: var(--text-dim); }
.planned h2, .empty-state h2 { font-size: 16px; color: var(--text); margin-bottom: 8px; }
.planned p, .empty-state p { max-width: 460px; margin: 0 auto 16px; font-size: 14px; }
.planned p:last-child, .empty-state p:last-child { margin-bottom: 0; }

/* ── Тост ─────────────────────────────────────────────────────────────────── */

.toast {
  position: fixed; bottom: 22px; left: 50%; transform: translateX(-50%) translateY(20px);
  background: var(--bg-raised); border: 1px solid var(--line);
  padding: 12px 16px; border-radius: 999px; font-size: 14px;
  opacity: 0; pointer-events: none; transition: opacity .18s, transform .18s;
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
.toast.err { border-color: var(--err); color: var(--err); }

/* ── Фильтры и таблицы ────────────────────────────────────────────────────── */

.filters { display: flex; gap: 8px; margin-bottom: 16px; flex-wrap: wrap; align-items: center; }
.filters input[type=text] { max-width: 320px; }
.filters select { max-width: 200px; }

.table { width: 100%; border-collapse: collapse; font-size: 14px; }
.table th {
  text-align: left; padding: 8px 12px; font-size: 12px; font-weight: 500;
  color: var(--text-faint); text-transform: uppercase; letter-spacing: .04em;
  border-bottom: 1px solid var(--line); background: var(--bg-subtle);
}
.table td { padding: 8px 12px; border-bottom: 1px solid var(--line); vertical-align: top; }
/* Числа — моноширинным и вправо: суммы и счётчики сравнивают столбиком,
   и разряды должны стоять друг под другом. */
.table th.num, .table td.num, .num {
  text-align: right; font-family: var(--mono); font-size: 13px;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.table tbody tr:last-child td { border-bottom: none; }
.table tbody tr[onclick] { cursor: pointer; }
.table tbody tr:hover { background: var(--bg-hover); }
.cell-title { font-weight: 500; }
.cell-sub { color: var(--text-faint); font-size: 13px; margin-top: 2px; }
.flags { display: flex; gap: 8px; flex-wrap: wrap; }
/* В таблице `.flags` — это <td>. С `display: flex` ячейка переставала быть
   ячейкой: пустая схлопывалась, и у строк без черновика обрывалась нижняя
   граница (список клиентов). Ячейка остаётся ячейкой, зазор — отступом. */
.table td.flags { display: table-cell; }
.table td.flags > * + * { margin-left: 8px; }
.nowrap { white-space: nowrap; color: var(--text-dim); }
.payload { color: var(--text-dim); font-size: 13px; max-width: 460px; }
.payload-key { color: var(--text-faint); }
.payload div { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ── Карточка клиента ─────────────────────────────────────────────────────── */

/* Слева поля, справа переписка — как в Bitrix. Колонки почти равны: поля
   читаются в один столбец, переписка требует ширины. */
.client-grid {
  display: grid; grid-template-columns: minmax(0, .95fr) minmax(360px, 1.05fr);
  gap: 16px; align-items: start;
}
.col-fields, .col-feed { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
/* Зазор между блоками даёт `gap` колонки; собственный `margin-bottom` у
   `.card` удваивал его до 32px. */
.col-fields > .card, .col-feed > .card { margin-bottom: 0; }
/* Прокручиваются ТОЛЬКО колонки, а не страница целиком: иначе кнопки
   «Сохранить» и «Отправить» никогда не видны одновременно. Высота — экран
   минус шапка; `--top` считает шапку с отступом контента. (Широкий экран —
   ниже, «Прокрутка карточки».) */
.col-fields {
  max-height: calc(100vh - var(--top)); overflow-y: auto;
  padding-right: 8px;
  /* Полоса прокрутки не появляется-исчезает при раскрытии блока («состав ▾»,
     «ещё 3», «Подобрать комплект») — от этого колонка прыгала по ширине. */
  scrollbar-gutter: stable;
}
.col-feed { position: sticky; top: calc(var(--head-h) + 16px); }
@media (max-width: 1000px) { .client-grid { grid-template-columns: 1fr; } }

/* Переписка ЦЕЛИКОМ укладывается в экран, а прокручивается только лента.
   Иначе форма ответа уезжала под сгиб: чтобы нажать «Отправить», приходилось
   пролистать всю карточку до раздела КП. Поэтому карточка ограничена высотой
   экрана и сама является колонкой: лента растягивается и скроллится внутри,
   форма прижата снизу и видна всегда. */
.feed-card {
  position: sticky; top: calc(var(--head-h) + 16px);
  max-height: calc(100vh - var(--top));
  display: flex; flex-direction: column;
}
/* `min-height: 0` обязателен: без него flex-элемент не даёт себя сжать ниже
   содержимого, и внутренняя прокрутка не включается. */
.feed {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  display: flex; flex-direction: column; gap: 4px; padding: 8px 6px 8px 2px;
}
/* ЛЕНТА КАК В МЕССЕНДЖЕРЕ (владелец 06.10: «сейчас пахнет 2000 годом»).
   Свои справа акцентной подложкой, клиент слева нейтральной; время внутри
   пузыря; подряд идущие сообщения одной стороны — плотнее; дни —
   разделителями (`feedDecorate` в card.js). */
.msg {
  position: relative; max-width: min(78%, 640px); padding: 7px 12px 6px;
  border-radius: 16px; font-size: 14px; line-height: 1.45;
  background: var(--bg-raised); border: 1px solid var(--line);
  overflow-wrap: anywhere; margin-top: 6px;
}
.msg + .msg.in, .msg.in + .msg.in, .msg.out + .msg.out { margin-top: 0; }
.msg.in { align-self: flex-start; border-bottom-left-radius: 6px; }
.msg.out {
  align-self: flex-end; background: var(--accent-soft);
  border-color: var(--accent-dim); border-bottom-right-radius: 6px;
}
/* Черновик в переписке: жёлтая рамка, чтобы его нельзя было принять за
   отправленное сообщение (владелец просил именно рамку, а не только подпись). */
.msg.is-draft {
  border: 2px solid var(--warn); background: var(--warn-bg);
}
.msg-text { white-space: pre-wrap; overflow-wrap: anywhere; }
/* Черновик, который уйдёт несколькими сообщениями: части — разделённые
   штрихом, как будущие пузыри (agent/pacing.py). */
.msg-part + .msg-part { margin-top: 6px; padding-top: 6px; border-top: 1px dashed var(--warn); }
.msg-script { margin-top: 6px; font-size: 13px; color: var(--text-dim); }
.msg-meta { margin-top: 2px; font-size: 11px; color: var(--text-faint);
  display: flex; gap: 6px; align-items: center; justify-content: flex-end; flex-wrap: wrap; }
.msg.out .msg-meta { color: var(--text-dim); }
.msg-meta time { font-variant-numeric: tabular-nums; }
.msg-by { opacity: .8; }
/* Цитата сообщения, на которое ответили: полоса слева, кто и что. */
.msg-quote { display: flex; flex-direction: column; align-items: flex-start; gap: 1px; width: 100%;
  margin: 0 0 4px; padding: 4px 8px; border: 0; border-left: 3px solid var(--accent);
  border-radius: 6px; background: var(--bg-hover); color: var(--text-dim); font: inherit;
  font-size: 12.5px; text-align: left; cursor: pointer; }
.msg-quote b { color: var(--accent); font-size: 12px; }
.msg-quote span { overflow: hidden; text-overflow: ellipsis; display: -webkit-box;
  -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
/* Действия у пузыря — по наведению, не загромождая ленту. */
.msg-actions { position: absolute; top: -12px; display: none; gap: 2px; padding: 2px;
  background: var(--bg-panel); border: 1px solid var(--line-strong); border-radius: 10px;
  box-shadow: var(--shadow); z-index: 2; }
.msg.in .msg-actions { right: -8px; }
.msg.out .msg-actions { left: -8px; }
.msg:hover .msg-actions, .msg:focus-within .msg-actions { display: flex; }
.msg-actions button { border: 0; background: none; padding: 2px 7px; border-radius: 8px;
  color: var(--text-dim); cursor: pointer; font-size: 13px; line-height: 1.4; }
.msg-actions button:hover { background: var(--bg-hover); color: var(--text); }
.msg.is-flash { animation: msg-flash 1.4s ease-out; }
@keyframes msg-flash { 0%, 40% { box-shadow: 0 0 0 3px var(--accent); } 100% { box-shadow: none; } }
.msg-file { display: inline-flex; gap: 6px; align-items: center; padding: 6px 10px;
  border-radius: 10px; background: var(--bg-hover); color: var(--text); text-decoration: none; }
/* Разделитель дня — по центру, мелко. */
.feed-day { align-self: center; margin: 10px 0 4px; }
.feed-day span { display: inline-block; padding: 2px 10px; border-radius: 10px;
  background: var(--bg-panel); border: 1px solid var(--line); font-size: 11.5px;
  color: var(--text-dim); }

.facts { display: grid; grid-template-columns: 1fr 1fr; gap: 0 12px; }
.sub-block { margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--line); }
.sub-title { font-size: 13px; color: var(--text-faint); margin-bottom: 8px; }
.sub-block .pill { margin: 0 4px 4px 0; }

.props { display: grid; grid-template-columns: minmax(120px, auto) 1fr; gap: 8px 16px; margin: 0 0 12px; font-size: 14px; }
.props dt { color: var(--text-faint); }
.props dd { margin: 0; word-break: break-word; }

/* ── Черновики ────────────────────────────────────────────────────────────── */

.draft textarea { font-size: 14px; line-height: 1.5; }
.draft-script { margin-top: 12px; font-size: 13px; color: var(--text-dim); }
.draft-hint { margin-top: 6px; }
.draft-script-lines { margin: 4px 0 0 18px; padding: 0; }
.draft-actions { display: flex; gap: 8px; margin-top: 12px; align-items: center; }
/* Черновик в ленте и хвост по элементам (владелец 11.10). */
.draft-box { margin-top: 8px; padding-top: 8px; border-top: 1px dashed var(--line); }
.draft-tail { display: grid; gap: 2px; margin: 6px 0; font-size: 13px; }
.draft-tail-item { display: flex; justify-content: space-between; gap: 8px;
  align-items: baseline; }
.draft-tail-item.is-blocked > span:first-child { color: var(--text-dim);
  text-decoration: line-through; }
.draft-tail-item .link { flex: none; }
.draft-buttons { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.draft-editor { margin-top: 8px; display: grid; gap: 6px; }
.draft-editor textarea { width: 100%; box-sizing: border-box; font: inherit; }
.draft.done { opacity: .45; }
.draft-failed {
  margin-bottom: 12px; padding: 8px 12px; border-radius: var(--radius); font-size: 13px;
  background: var(--err-bg); border: 1px solid var(--err);
}

a.metric { display: block; color: inherit; }
a.metric:hover { background: var(--bg-hover); border-color: var(--line-strong); }

/* ── Редакторы контента ───────────────────────────────────────────────────── */

.doc, .block { border: 1px solid var(--line); border-radius: var(--radius); margin-bottom: 12px; }
.doc summary, .block summary {
  padding: 12px 16px; cursor: pointer; display: flex; gap: 12px;
  align-items: baseline; justify-content: space-between; font-size: 14px;
}
.doc summary::-webkit-details-marker, .block summary::-webkit-details-marker { display: none; }
.doc[open] summary, .block[open] summary { border-bottom: 1px solid var(--line); }
.doc-title { font-weight: 500; }
.doc-meta { color: var(--text-faint); font-size: 13px; }
.doc form { padding: 16px; }
.doc textarea { line-height: 1.5; }
.doc-controls { display: flex; gap: 12px; align-items: center; margin-top: 12px; flex-wrap: wrap; }
.stages-input { max-width: 320px; }

.prompt-text {
  margin: 0; padding: 16px; white-space: pre-wrap; word-break: break-word;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 13px;
  line-height: 1.55; color: var(--text-dim); max-height: 420px; overflow-y: auto;
}

.versions { padding: 0 16px 16px; }
.version {
  display: flex; gap: 12px; align-items: center; justify-content: space-between;
  padding: 12px 0; border-top: 1px solid var(--line);
}
.version-preview { color: var(--text-faint); font-size: 13px; margin-top: 3px;
  max-width: 640px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.actions-row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin: 16px 0 8px; }
.actions-row input { max-width: 260px; }

/* ── Медиатека и сценарии ─────────────────────────────────────────────────── */

.media-grid { display: grid; gap: 12px; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
.media-card { border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; background: var(--bg-raised); }
.media-card img { width: 100%; height: 120px; object-fit: cover; display: block; }
.media-placeholder { height: 120px; display: grid; place-items: center; font-size: 26px; color: var(--text-faint); }
.media-info { padding: 8px 12px; }
.media-name { font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.set-grid { display: grid; gap: 12px; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); }
.set-card { display: block; padding: 12px 16px; border: 1px solid var(--line);
  border-radius: var(--radius); background: var(--bg-raised); color: var(--text); }
.set-card:hover { border-color: var(--accent); }
.set-title { font-weight: 500; font-size: 14px; margin-bottom: 3px; }

/* ── Чертежи ─────────────────────────────────────────────────────────────── */

.drawing-upload { border-color: var(--accent-dim); }
.drawing-form input { max-width: 180px; }
.drawing-filters { padding-bottom: 12px; }
.size-filter input { max-width: 110px; }
.drawing-grid {
  display: grid; gap: 16px;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
}
.drawing-card {
  border: 1px solid var(--line); border-radius: var(--radius);
  overflow: hidden; background: var(--bg-panel);
  display: flex; flex-direction: column; min-width: 0;
}
.drawing-preview {
  display: block; height: 170px; background: var(--bg-subtle);
  border-bottom: 1px solid var(--line);
}
.drawing-preview img {
  width: 100%; height: 100%; object-fit: cover; display: block;
}
.drawing-preview .media-placeholder { height: 100%; }
.drawing-info { padding: 12px 16px 16px; min-width: 0; }
.drawing-title {
  font-weight: 600; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap;
}
.drawing-dims { margin-top: 4px; color: var(--text); font-size: 14px; }
.drawing-actions { margin-top: 12px; }
.drawing-list { display: flex; flex-direction: column; gap: 8px; }
.drawing-row {
  display: grid; grid-template-columns: 58px minmax(0, 1fr) auto;
  gap: 12px; align-items: center;
  padding: 8px; border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--bg-raised);
}
.drawing-row .sort-thumb {
  width: 52px; height: 40px; border-radius: 5px; overflow: hidden;
  display: block; background: var(--bg);
}
.drawing-row .sort-thumb img {
  width: 100%; height: 100%; object-fit: cover; display: block;
}
.client-pick-list {
  display: flex; flex-direction: column; gap: 8px;
  margin-top: 12px; max-height: 50vh; overflow-y: auto;
}

.sortable { display: flex; flex-direction: column; gap: 8px; }
.sort-row { display: flex; align-items: center; gap: 12px; padding: 8px 12px;
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--bg-raised); cursor: grab; }
.sort-row.dragging { opacity: .4; }
.drag-handle { color: var(--text-faint); }
.sort-thumb { width: 52px; height: 40px; object-fit: cover; border-radius: 5px; flex: 0 0 auto; }
.sort-thumb.media-placeholder { height: 40px; font-size: 16px; background: var(--bg); }
.sort-title { flex: 1; font-size: 14px; }

.flow { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 12px 0 8px; }
.flow-node { padding: 4px 12px; border-radius: 999px; background: var(--accent-dim); font-size: 13px; }
.flow-arrow { color: var(--text-faint); }
.media-step { padding: 12px 0; }
.media-strip { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 8px; }
.media-thumb { padding: 4px 8px; border-radius: 6px; background: var(--bg-subtle);
  font-size: 12px; color: var(--text-dim); font-family: ui-monospace, monospace; }
.transition { display: flex; align-items: center; gap: 12px; padding: 8px 0;
  border-bottom: 1px solid var(--line); font-size: 14px; }
.transition:last-of-type { border-bottom: none; }
.preview-row { display: flex; gap: 12px; align-items: flex-start; padding: 12px 0;
  border-bottom: 1px solid var(--line); font-size: 14px; }

/* ── Дашборд ──────────────────────────────────────────────────────────────── */

.attention { display: flex; flex-direction: column; gap: 1px; }
.attention-row { display: flex; align-items: center; gap: 12px; padding: 8px 12px;
  border-radius: var(--radius); color: var(--text); font-size: 14px; background: var(--bg-subtle); }
.attention-row:hover { background: var(--bg-hover); }

.recent { display: flex; flex-direction: column; }
.recent-row { display: flex; align-items: center; gap: 12px; padding: 8px 0;
  border-bottom: 1px solid var(--line); font-size: 14px; }
.recent-row:last-child { border-bottom: none; }

.sparkline { display: flex; align-items: flex-end; gap: 8px; height: 90px;
  margin-top: 16px; padding-top: 12px; }
.spark-col { flex: 1; display: flex; flex-direction: column; justify-content: flex-end;
  align-items: center; height: 100%; }
.spark-bar { width: 100%; background: var(--accent-dim); border-radius: 3px 3px 0 0;
  min-height: 2px; }
.spark-col:hover .spark-bar { background: var(--accent); }
.spark-label { font-size: 11px; color: var(--text-faint); margin-top: 4px; }

/* ── Пометки «составлено ассистентом» ─────────────────────────────────────── */

.ai-badge { background: var(--warn-bg); color: var(--warn); border-color: transparent; }
.ai-item { padding: 12px 0; border-bottom: 1px solid var(--line); }
.ai-item:last-child { border-bottom: none; }
.ai-item-head { display: flex; gap: 12px; align-items: baseline; flex-wrap: wrap; }
.ai-preview { color: var(--text-dim); font-size: 13px; margin: 8px 0 12px;
  max-height: 60px; overflow: hidden; }
.ai-actions { display: flex; gap: 8px; align-items: center; }
.nav-badge { margin-left: auto; background: var(--warn-bg); color: var(--warn);
  border-radius: 999px; padding: 1px 8px; font-size: 11px; }
.bulk-bar { display: none; gap: 12px; align-items: center; margin-bottom: 16px;
  padding: 12px 16px; border-radius: var(--radius); background: var(--bg-raised);
  border: 1px solid var(--line); flex-wrap: wrap; }
.bulk-bar.visible { display: flex; }
.bulk-bar input { max-width: 220px; }
.media-card { position: relative; }
.media-pick { position: absolute; top: 6px; left: 6px; z-index: 2;
  background: var(--bg-panel); border: 1px solid var(--line); border-radius: 4px; padding: 3px 4px; }
.tag-row { display: flex; gap: 4px; flex-wrap: wrap; margin-top: 4px; }
.tag { display: inline-block; padding: 2px 8px; border-radius: 999px;
  background: var(--bg-subtle); color: var(--text-dim); font-size: 12px;
  margin: 0 4px 4px 0; }
.tag-stage { background: var(--accent-dim); color: var(--text); }
/* Карта выключена — черновик не ведёт клиентов, это должно бросаться в глаза. */
.tag-warn { background: var(--warn-bg); color: var(--warn); }
a.tag:hover { background: var(--accent); color: var(--accent-ink); }

/* ── Исправления ──────────────────────────────────────────────────────────── */

/* «Исправлено» у ответа, который человек поправил: версия агента всплывает
   по наведению или фокусу. Всплывашка привязана к ПУЗЫРЮ (а не к метке) и
   растёт вверх от его низа — так она не обрезается краем ленты у свежих
   сообщений внизу и не сдвигает соседей. */
.msg-edited {
  color: var(--warn); cursor: help; border-bottom: 1px dotted currentColor;
  outline: none;
}
.msg-edited:focus-visible { box-shadow: 0 0 0 2px var(--accent); border-radius: 2px; }
.msg-original {
  display: none; position: absolute; left: 0; right: 0; bottom: 0; z-index: 5;
  padding: 8px 12px; border-radius: var(--radius);
  background: var(--bg-raised); color: var(--text); border: 1px solid var(--line-strong);
  box-shadow: var(--shadow); font-size: 13px; white-space: pre-wrap;
  max-height: 60vh; overflow: auto;
}
.msg-edited:hover .msg-original, .msg-edited:focus .msg-original { display: block; }
.msg-original-label { display: block; font-size: 11px; text-transform: uppercase;
  letter-spacing: .04em; color: var(--text-faint); margin-bottom: 4px; }
.correction { border: 1px solid var(--line); border-radius: var(--radius); padding: 16px;
  margin-bottom: 12px; }
.correction-versions { display: grid; gap: 12px; grid-template-columns: 1fr 1fr; }
@media (max-width: 900px) { .correction-versions { grid-template-columns: 1fr; } }
.version-box { background: var(--bg-subtle); border-radius: var(--radius); padding: 12px 12px;
  font-size: 14px; white-space: pre-wrap; }
.version-box.was { opacity: .6; }
.version-label { font-size: 11px; text-transform: uppercase; letter-spacing: .04em;
  color: var(--text-faint); margin-bottom: 4px; }
.insight { margin-top: 12px; padding: 12px; border-radius: var(--radius);
  background: var(--accent-soft); border: 1px solid var(--accent-dim); }
.insight-summary { font-weight: 500; margin-bottom: 8px; }
.suggestion { display: flex; gap: 12px; align-items: flex-start; padding: 8px 0;
  border-top: 1px solid var(--line); font-size: 14px; }
.chain-arrow { color: var(--text-faint); text-align: center; margin: 4px 0; }

/* ── Доска карты сценариев ────────────────────────────────────────────────── */

.board-card { padding: 0; overflow: hidden; }
/* Доска — окно в бесконечное полотно (canvas.js): масштаб и сдвиг держит
   viewBox, а не прокрутка страницы. Сетка — внутри SVG, едет вместе с картой. */
.board-wrap { overflow: hidden; height: calc(100vh - 290px); min-height: 440px; }
.board-wrap > svg.board { width: 100%; height: 100%; }
.board { display: block; user-select: none; touch-action: none; }
.board .board-grid { pointer-events: none; }
.board .grid-dot { fill: var(--line); }
.board.is-space, .board.is-space * { cursor: grab; }
.board.is-panning, .board.is-panning * { cursor: grabbing !important; }
.zoom-group { display: inline-flex; gap: 2px; }
.zoom-group button { min-width: 32px; }
.board .node rect { fill: var(--bg-panel); stroke: var(--line); stroke-width: 1.4; }
.board .node.is-start rect { stroke: var(--accent); stroke-width: 2; }
.board .node:hover rect { stroke: var(--text-faint); }
.board .node { cursor: grab; }
.board .node-kind { fill: var(--text-faint); font-size: 11px;
  text-transform: uppercase; letter-spacing: .04em; }
.board .node-title { fill: var(--text); font-size: 14px; }
.board .kind-touch rect { fill: color-mix(in srgb, var(--accent) 12%, var(--bg-panel)); }
.board .kind-script rect { fill: color-mix(in srgb, var(--ok) 12%, var(--bg-panel)); }
.board .kind-media_set rect { fill: color-mix(in srgb, var(--draft) 12%, var(--bg-panel)); }
.board .kind-phrase rect { fill: color-mix(in srgb, var(--warn) 12%, var(--bg-panel)); }
.board .kind-knowledge rect { fill: color-mix(in srgb, var(--text-dim) 12%, var(--bg-panel)); }
.board .node-plus circle, .board .node-remove circle { fill: var(--bg-raised);
  stroke: var(--line); }
.board .node-plus text, .board .node-remove text { fill: var(--text-dim);
  font-size: 12px; }
.board .node-plus:hover circle { fill: var(--accent); }
.board .node-remove:hover circle { fill: var(--err); }
.board .edge { cursor: pointer; }
/* Цвета стрелок board.js пишет атрибутами SVG (fill/stroke = hex). Атрибут
   слабее любого CSS-правила, поэтому тема перебивает их здесь, не трогая JS. */
.board .edge path { stroke: var(--text-faint); }
.board #arrow path { fill: var(--text-faint); }
.board .rubber { stroke: var(--accent); }
.board .edge:hover path { stroke: var(--accent); }
.board .edge-label { fill: var(--text-dim); font-size: 11px; }
/* Конец стрелки — ручка: тянется на другую карточку. */
.board .edge-end { fill: var(--bg-raised); stroke: var(--text-faint);
  stroke-width: 1.4; cursor: grab; opacity: .6; }
.board .edge-end:hover { fill: var(--accent); stroke: var(--accent); opacity: 1; }
.board .edge.is-rewiring path { opacity: .25; }
/* Невидимая широкая линия — попасть по стрелке мышью легко. */
.board .edge .edge-hit { stroke: transparent; stroke-width: 12; pointer-events: stroke; }
.board .edge-handles { cursor: grab; }
/* Овал по типу условия: словами — акцент, правило кода — фиолетовый,
   подпись — нейтральный, только пауза — пунктир. */
.board .chip-words rect { stroke: var(--accent); }
.board .chip-rule rect { stroke: var(--draft); }
.board .chip-label rect { stroke: var(--line-strong); }
.board .chip-pause rect { stroke: var(--line-strong); stroke-dasharray: 3 2; }
.board.has-hl .edge-handles:not(.is-hl) { opacity: .2; }
/* Фокус на стрелке, пока открыта её панель: линия и две карточки. */
.board.has-focus .edge:not(.is-focus),
.board.has-focus .edge-handles:not(.is-focus) { opacity: .12; }
.board.has-focus .node:not(.is-focus) { opacity: .3; }
.board.has-focus .container { opacity: .4; }
.board .edge.is-focus path:not(.edge-hit) { stroke: var(--accent); stroke-width: 2.6; }
.board .edge-handles.is-focus .trigger rect { fill: var(--bg-panel); stroke: var(--accent); stroke-width: 1.6; }
.board .edge-handles.is-focus .edge-end { fill: var(--accent); stroke: var(--accent); opacity: 1; }
.board .node.is-focus > rect { stroke: var(--accent); stroke-width: 2.5; }
.board .node.is-drop > rect { stroke: var(--accent); stroke-width: 2.5; }

/* ── Конструктор блоков касания ─────────────────────────────────────────── */

.step-editor { margin-top: 8px; }

.step-list { display: flex; flex-direction: column; gap: 8px; }

.step-row {
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 12px 12px;
}

.step-head {
  display: flex; align-items: center; gap: 12px;
  margin-bottom: 8px;
}

.step-num {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; flex: 0 0 22px;
  background: var(--accent-dim); color: var(--text);
  border-radius: 50%; font-size: 12px; font-weight: 600;
}

.step-type { color: var(--text-dim); font-size: 13px; }
.step-move { margin-left: auto; display: flex; gap: 4px; }
.step-move button { padding: 2px 8px; font-size: 13px; line-height: 1.4; }

.step-body textarea, .step-body input[type=text] { width: 100%; }
.step-body .inline { display: inline-flex; align-items: center; gap: 8px; }
.step-body .inline input { width: 90px; }

.step-media { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }

.chip {
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--bg-panel); border: 1px solid var(--line);
  border-radius: 999px; padding: 3px 8px 3px 4px; font-size: 13px;
  max-width: 240px;
}
.chip img { width: 24px; height: 24px; object-fit: cover; border-radius: 50%; }
.chip button { padding: 0 4px; background: none; border: none; color: var(--text-faint); }
.chip button:hover { color: var(--err); }
.chip-missing { border-color: var(--err); color: var(--err); }

.step-add { margin-top: 12px; flex-wrap: wrap; }

/* ── Выбор файлов из медиатеки ──────────────────────────────────────────── */

.modal {
  display: none; position: fixed; inset: 0; z-index: 50;
  background: var(--scrim); padding: 4vh 16px;
  overflow-y: auto;
}
.modal.open { display: block; }

.modal-box {
  max-width: 820px; margin: 0 auto;
  background: var(--bg-panel); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 16px;
}

.picker-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
  gap: 8px; margin: 12px 0; max-height: 55vh; overflow-y: auto;
}

.picker-item {
  position: relative; cursor: pointer;
  border: 2px solid transparent; border-radius: var(--radius);
  padding: 4px; background: var(--bg-subtle);
}
.picker-item img { width: 100%; height: 80px; object-fit: cover; border-radius: 5px; }
.picker-icon {
  height: 80px; display: flex; align-items: center; justify-content: center;
  font-size: 26px; color: var(--text-faint);
}
.picker-title {
  font-size: 12px; color: var(--text-dim); margin-top: 4px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.picker-item.chosen { border-color: var(--accent); }
/* Номер выбора — порядок, в котором файлы уйдут клиенту. */
.picker-item.chosen::after {
  content: attr(data-pos);
  position: absolute; top: 6px; right: 6px;
  width: 20px; height: 20px; border-radius: 50%;
  background: var(--accent); color: var(--accent-ink);
  font-size: 12px; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
}

/* ── Канбан стадий ───────────────────────────────────────────────────────── */

.kanban {
  display: flex; gap: 12px; overflow-x: auto;
  padding-bottom: 8px; margin: 12px 0;
}

.kan-col {
  flex: 0 0 210px;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  cursor: grab;
}
.kan-col.dragging { opacity: 0.45; }
.kan-cap { height: 3px; }
.kan-cap-inline {
  display: inline-block; width: 3px; height: 16px;
  border-radius: 2px; vertical-align: middle; margin-right: 8px;
}

.kan-head {
  display: flex; align-items: center; gap: 8px;
  padding: 12px 12px 8px;
}
.kan-title { font-weight: 600; font-size: 14px; flex: 1; }
.kan-count {
  font-size: 12px; color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}
.kan-meta {
  padding: 0 12px 12px; display: flex; flex-wrap: wrap;
  gap: 8px; align-items: center; font-size: 12px;
}
.kan-actions {
  border-top: 1px solid var(--line);
  padding: 8px 12px; display: flex; flex-direction: column; gap: 8px;
}
.kan-actions button { font-size: 12px; padding: 3px 8px; }

.swatches { display: flex; flex-wrap: wrap; gap: 4px; }
.swatch {
  width: 14px; height: 14px; padding: 0;
  border: 1px solid var(--line); border-radius: 50%;
  cursor: pointer;
}
.swatch.on { outline: 2px solid var(--text); outline-offset: 1px; }

/* Окно стадии на доске («+» и ✎): название, цвет кружком, превью шапки. */
.stage-box { width: min(420px, 100%); gap: 12px; }
.stage-box-field {
  display: flex; flex-direction: column; gap: 6px;
  font-size: 12px; color: var(--text-dim);
}
.stage-box-field input { font-size: 14px; }
.stage-colors { display: flex; flex-wrap: wrap; gap: 8px; }
.stage-color {
  width: 26px; height: 26px; padding: 0; border-radius: 50%;
  border: 1px solid var(--line-strong); cursor: pointer;
}
.stage-color.on { outline: 2px solid var(--text); outline-offset: 2px; }
.stage-color-none {
  background: repeating-linear-gradient(45deg, var(--bg-raised) 0 4px,
                                        var(--line) 4px 8px);
}
.stage-preview {
  border: 1px solid var(--line); border-radius: var(--radius);
  overflow: hidden; background: var(--bg-panel);
}
.stage-preview .board-title { display: block; padding: 8px 12px; }

/* Метка привязки к стадии: называет стадию, а не уровень — в базе знаний
   читатель не знает контекста. */
.pill-stage {
  background: var(--accent-dim);
  color: var(--text);
}

/* ── Полоски стадии ──────────────────────────────────────────────────────── */

.strips {
  border-top: 1px solid var(--line);
  padding: 8px; display: flex; flex-direction: column; gap: 2px;
}
.strip {
  display: flex; justify-content: space-between; align-items: center;
  gap: 8px; width: 100%;
  background: var(--bg-panel); border: 1px solid transparent;
  border-radius: 4px; padding: 4px 8px;
  font-size: 12px; color: var(--text-dim); text-align: left;
  cursor: pointer;
}
.strip:hover { border-color: var(--line); color: var(--text); }
.strip.on { border-color: var(--accent-dim); color: var(--text); }
.strip-count {
  font-variant-numeric: tabular-nums; color: var(--text-faint);
  font-size: 12px;
}
.strip-body:not(:empty) {
  padding: 8px; margin-top: 4px;
  background: var(--bg-panel); border-radius: 4px;
  font-size: 13px;
}
.strip-row {
  display: flex; justify-content: space-between; align-items: center;
  gap: 8px; padding: 4px 0;
}
.strip-row .btn { font-size: 11px; padding: 2px 8px; }
.strip-group { margin: 8px 0 2px; font-weight: 600; }
.strip-body textarea { width: 100%; font-size: 13px; }

.kan-delays {
  padding: 0 12px 8px; display: flex; flex-direction: column; gap: 4px;
  font-size: 12px; color: var(--text-faint);
}
.kan-delays .inline { display: flex; align-items: center; gap: 4px; }
.kan-delays input { width: 62px; padding: 2px 4px; font-size: 12px; }

/* ── Канбан клиентов ─────────────────────────────────────────────────────── */

.client-col { cursor: default; }
.card-drop {
  padding: 8px; display: flex; flex-direction: column; gap: 8px;
  min-height: 60px;
}
.card-drop.over { background: var(--accent-soft, var(--bg-panel)); }

.client-card {
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 8px 12px;
  cursor: grab;
  font-size: 13px;
}
.client-card a { font-weight: 600; }
.client-card.dragging { opacity: 0.45; }
.client-card.moving { opacity: 0.6; }
.client-card.overdue { border-left: 3px solid var(--warn); }
.cell-sub.alert { color: var(--warn); }

/* ── Статистика стадий на дашборде ───────────────────────────────────────── */

.stat-rows { padding: 8px 12px 12px; display: flex; flex-direction: column; gap: 3px; }
.stat-row {
  display: flex; justify-content: space-between; gap: 8px;
  font-size: 12px; color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}
.stat-row.alert span:last-child { color: var(--warn); font-weight: 600; }
.kan-col.stalled { border-color: var(--warn); }

/* ── Проверка «что уйдёт клиенту» ────────────────────────────────────────── */

.dry-form { display: flex; flex-direction: column; gap: 8px; margin: 8px 0; }
.dry-form input[type=text] { width: 100%; }
.dry-form input[type=number] { width: 60px; }
.dry-note {
  background: var(--bg-subtle); border-left: 2px solid var(--accent);
  padding: 8px 8px; margin: 8px 0; font-size: 12px; color: var(--text-dim);
}
.dry-msg {
  background: var(--bg-subtle); border-radius: 6px; padding: 8px 8px;
  white-space: pre-wrap; font-size: 12px; margin: 3px 0;
}
.dry-step { display: flex; gap: 8px; align-items: flex-start; margin: 4px 0; }
.dry-num {
  flex: 0 0 18px; height: 18px; border-radius: 50%;
  background: var(--accent-dim); color: var(--text);
  font-size: 11px; display: flex; align-items: center; justify-content: center;
}

/* ── Мини-панель на стрелке карты ────────────────────────────────────────── */

/* Окно у места щелчка (board.js → floatPanel), перетаскивается за заголовок. */
.edge-panel {
  position: fixed; top: 96px; left: 50%;
  z-index: 60; width: 300px; max-height: calc(100vh - 16px); overflow-y: auto;
  background: var(--bg-panel); border: 1px solid var(--line);
  border-radius: 10px; padding: 0 12px 12px;
  display: flex; flex-direction: column; gap: 7px;
  box-shadow: var(--shadow); font-size: 13px;
}
.edge-panel.is-moving { opacity: .92; }
.edge-panel-head {
  display: flex; align-items: center; gap: 6px; cursor: move; user-select: none;
  margin: 0 -12px; padding: 9px 8px 9px 12px; border-bottom: 1px solid var(--line);
  border-radius: 10px 10px 0 0; background: var(--bg-subtle);
}
.edge-panel-head b { flex: 1; }
.edge-panel-head button { padding: 2px 7px; }
.ep-route { flex: 1; display: inline-flex; align-items: center; gap: 6px; min-width: 0; }
.ep-route b {
  flex: 0 1 auto; padding: 1px 8px; border-radius: 999px; font-size: 12px;
  background: var(--accent-soft); color: var(--accent); border: 1px solid var(--accent-dim);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ep-route span { color: var(--text-faint); }
.ep-names { color: var(--text-faint); font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.edge-panel label { display: flex; flex-direction: column; gap: 3px; font-size: 12px; color: var(--text-dim); }
.edge-panel label.check { flex-direction: row; align-items: center; gap: 6px; }
.edge-panel input[type=text] { width: 100%; box-sizing: border-box; }
.edge-panel input[type=number] { width: 52px; }
.edge-panel select { width: auto; min-width: 0; padding: 3px 4px; }
.ep-row { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-dim); }
.ep-row > span { width: 64px; }
.ep-help { font-size: 12px; color: var(--text-faint); }
.ep-help summary { cursor: pointer; color: var(--text-dim); }
.ep-help p { margin: 4px 0 0; line-height: 1.4; }
.edge-hint { font-size: 12px; color: var(--text-faint); }
.rubber { pointer-events: none; }

/* ── Триггеры-овалы на стрелках карты ────────────────────────────────────── */

.trigger { cursor: pointer; }
.trigger rect {
  fill: var(--bg-raised); stroke: var(--line); stroke-width: 1;
}
.trigger text { font-size: 11px; fill: var(--text-dim); }
.trigger:hover rect { stroke: var(--accent); }
.trigger:hover text { fill: var(--text); }
.trigger-open rect { fill: var(--bg-panel); stroke: var(--accent); }

.edge-twin {
  background: var(--accent-dim); color: var(--text);
  border-radius: 4px; padding: 8px 8px; font-size: 12px;
}

/* ── Контейнеры-стадии на карте ──────────────────────────────────────────── */

.container rect {
  fill: var(--accent); fill-opacity: .05;
  stroke: var(--line); stroke-width: 1.5; stroke-dasharray: 6 4;
}
.container:hover rect { stroke: var(--accent-dim); }
.container-title { font-size: 13px; font-weight: 600; fill: var(--text-dim); }
.container-stage { font-size: 11px; fill: var(--text-faint); }
.container-grip rect { fill: var(--line); stroke: none; cursor: nwse-resize; }
.container-grip:hover rect { fill: var(--accent); }

/* ── Развёрнутое касание на карте ────────────────────────────────────────── */

.composition rect {
  fill: var(--accent); fill-opacity: .07;
  stroke: var(--line); stroke-width: 1;
}
.composition-title { font-size: 11px; fill: var(--text-faint); }
.composition-step { font-size: 11px; fill: var(--text-dim); }
.insert-point { cursor: pointer; }
.insert-point circle { fill: var(--bg-panel); stroke: var(--line); }
.insert-point text { font-size: 11px; fill: var(--text-faint); }
.insert-point:hover circle { fill: var(--accent); stroke: var(--accent); }
.insert-point:hover text { fill: var(--accent-ink); }
.node-expand circle { fill: var(--bg-panel); stroke: var(--line); }
.node-expand text { font-size: 11px; fill: var(--text-dim); }
.node-expand:hover circle { stroke: var(--accent); }
.composition-step.inserted { fill: var(--accent); }

/* ── Метки: chip-редактор ─────────────────────────────────────────────────── */
.label-chips { display: flex; align-items: center; gap: 4px; flex-wrap: wrap;
  margin-top: 8px; }
.label-chips-title { font-size: 11px; color: var(--text-faint); }
.tag-label { display: inline-flex; align-items: center; gap: 4px; }
.tag-signal { background: var(--accent-dim); color: var(--text); }
.tag-label { cursor: pointer; }
/* «Тоже видно»: метка не тема единицы, а то, что попало в кадр. */
.tag-secondary { background: none; border: 1px dashed var(--line);
  color: var(--text-dim); }
.label-chip-del { padding: 0 2px; background: none; border: none; line-height: 1;
  color: var(--text-faint); cursor: pointer; }
.label-chip-del:hover { color: var(--err); }
/* ✎ — переименовать метку везде; виден на наведении, как инструменты колонки. */
.label-chip-ren { padding: 0 2px; background: none; border: none; line-height: 1;
  color: var(--text-faint); cursor: pointer; font-size: 11px; opacity: 0; }
.tag-label:hover .label-chip-ren, .label-chip-ren:focus-visible { opacity: 1; }
.label-chip-ren:hover { color: var(--accent); }
.label-chip-edit { font-size: 11px; padding: 0 4px; min-width: 6em;
  border-radius: 999px; }
@media (hover: none) { .label-chip-ren { opacity: 1; } }
.label-chip-input { width: 110px; padding: 2px 8px; font-size: 11px;
  border-radius: 999px; }
/* Строка материала: превью единицы слева, пояснения под ним, действия —
   отдельной колонкой справа, разными цветами (владелец 03.10: «кнопки
   отделить, сделать разных цветов, отодвинуть в бок»). */
.material-row { display: grid; grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas: "unit actions" "meta actions"; column-gap: 16px; row-gap: 2px;
  padding: 10px 0; border-top: 1px solid var(--line); align-items: start; }
.material-row:first-of-type { border-top: 0; }
.material-unit { grid-area: unit; min-width: 0; }
.material-meta { grid-area: meta; display: flex; flex-wrap: wrap; gap: 8px; }
.material-meta:empty { display: none; }
.material-actions { grid-area: actions; display: flex; flex-direction: column;
  gap: 6px; align-items: stretch; min-width: 128px; }
.material-row.is-overdue .material-title { color: var(--err); }
.material-title { font-weight: 500; }
.materials-interest b { color: var(--text); }
.btn.small, button.small { padding: 4px 10px; font-size: 12.5px; }
.mat-plan { border-color: var(--accent); color: var(--accent); background: transparent; }
.mat-plan:hover { background: var(--accent-soft); }
.mat-promise { border-color: var(--warn); color: var(--warn); background: var(--warn-bg); }
.mat-promise:hover { filter: brightness(1.08); background: var(--warn-bg); }
.mat-sent { border-color: var(--ok); color: var(--ok); background: var(--ok-bg); }
.mat-sent:hover { filter: brightness(1.08); background: var(--ok-bg); }
.mat-drop { color: var(--text-faint); }
@media (max-width: 640px) {
  .material-row { grid-template-columns: 1fr; grid-template-areas: "unit" "meta" "actions"; }
  .material-actions { flex-direction: row; flex-wrap: wrap; }
}
.phrase-form { display: flex; flex-direction: column; gap: 8px; }
.phrase-form textarea { width: 100%; }
.step-mode { margin-top: 6px; font-size: 12px; color: var(--text-dim); }
.step-phrase-text { white-space: pre-wrap; margin-top: 4px; }
.media-size { margin-top: 4px; }
.media-size input { width: 72px; padding: 2px 6px; font-size: 11px; }
.doc-off > summary { opacity: .55; }

/* Поиск клиента в расчёте: результаты под полем. Список всех клиентов
   бесполезен — их сотни, поэтому здесь именно поиск по подстроке. */
.hits {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  margin-top: 8px;
  max-height: 230px;
  overflow-y: auto;
  background: var(--bg-panel);
}
.hits button {
  display: block;
  width: 100%;
  text-align: left;
  border: none;
  border-bottom: 1px solid var(--line);
  border-radius: 0;
  background: none;
  padding: 8px 12px;
  font-size: 14px;
}
.hits button:last-child { border-bottom: none; }
.hits button:hover { background: var(--bg-hover); }
.hits .hit-sub { color: var(--text-faint); font-size: 12px; }
.field-note { color: var(--text-dim); font-size: 13px; margin-top: 8px; }
.row-actions { white-space: nowrap; }

/* Шапка страницы: «назад» слева, заголовок по центру потока, действия справа.
   Раньше возврат стоял среди действий в правом углу — искать его там неудобно. */
.topbar-back { display: flex; align-items: center; }
.topbar-back:empty { display: none; }
.topbar-back .btn { padding: 4px 12px; font-size: 13px; white-space: nowrap; }

/* ── Карточка клиента: шапка, поля слева, переписка справа ─────────────────
   Раскладка повторяет Bitrix (media/client crm.jpg): раньше переписка была
   слева, а поля прятались в форме «Память агента» — и правились только все
   разом. */
.client-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 16px 24px; flex-wrap: wrap;
}
/* ПРОКРУТКА КАРТОЧКИ НА ШИРОКОМ ЭКРАНЕ. Страница не прокручивается вовсе:
   содержимое — ровно экран под шапкой, колонной. Шапка карточки (имя,
   стадия, ссылки) стоит на месте, а поля и переписка прокручиваются каждая
   сама и занимают всё, что осталось. Прежде прокручивалась ещё и страница:
   шапка карточки уезжала, а прилипшие колонки при прокрутке страницы
   заезжали под шапку (им не хватало места «прилипнуть» внутри сетки). Так
   высоту не нужно ни зашивать, ни мерить скриптом — её раздаёт flex. */
@media (min-width: 1001px) {
  .content:has(> .client-grid) {
    height: calc(100vh - var(--head-h)); padding-bottom: 16px;
    display: flex; flex-direction: column; overflow: hidden;
  }
  .content:has(> .client-grid) > .card { flex: none; }
  /* Разбор переписки бывает длинным — он не должен съесть колонки. */
  .content:has(> .client-grid) > .scan-result { max-height: 35vh; overflow-y: auto; }
  .content > .client-grid {
    flex: 1 1 auto; min-height: 0;
    grid-template-rows: minmax(0, 1fr); align-items: stretch;
  }
  .content > .client-grid > .col-fields { max-height: none; min-height: 0; }
  .content > .client-grid > .col-feed { position: static; min-height: 0; }
  .content > .client-grid .feed-card {
    position: static; max-height: none; flex: 1 1 auto; min-height: 0;
  }
}
.head-main { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
/* Ссылки «Профиль · Чат · CRM» — та же строка, что в уведомлениях. */
.head-links { font-size: 13px; color: var(--text-faint); }
.head-links a { color: var(--accent); }
.head-links .sep { color: var(--text-faint); }
.editable-name {
  font-size: 20px; font-weight: 600; cursor: pointer;
  border-bottom: 1px dashed transparent;
}
.editable-name:hover { border-bottom-color: var(--line); }
.head-channels { display: flex; gap: 8px; flex-wrap: wrap; }
.chan-chip {
  font-size: 12px; padding: 2px 8px; border-radius: 20px;
  border: 1px solid var(--line); color: var(--text-dim);
}
.head-side { display: flex; align-items: flex-end; gap: 16px; flex-wrap: wrap; }
.head-field { display: flex; flex-direction: column; gap: 4px; font-size: 13px; }
.head-field > span { color: var(--text-faint); font-size: 12px; }
/* Закреплённые поля шапки: ID, квалификация, след. касание (владелец 04.10). */
.head-pinned b { font-weight: 600; }
.head-pinned small { color: var(--text-faint); font-weight: 400; }
.head-pinned b.is-empty { color: var(--text-faint); font-weight: 400; }
button.head-jump { background: none; border: 0; padding: 0; text-align: left;
  cursor: pointer; color: inherit; font: inherit; }
button.head-jump:hover b { color: var(--accent); }
.field-row.is-jumped { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 6px; }
/* Режим агента в шапке — цветом режима, как в «Пульте агента» (.mode-*). */
.head-agent b { color: var(--mode, var(--text)); display: inline-flex; align-items: center; gap: 6px; }
.head-agent b::before { content: ""; width: 8px; height: 8px; border-radius: 50%;
  background: currentColor; flex: 0 0 auto; }

/* ШАПКА КАРТОЧКИ ОДНОЙ СТРОКОЙ (владелец 07.10: шапка с кнопками, второй
   заголовок и имя дважды занимали 40% экрана, переписке — меньше четверти).
   Имя — в заголовке страницы, редкие действия — в меню «⋯», здесь — каналы,
   ссылки и закреплённые поля в одну строку (на узком — переносятся). */
.client-head { padding: 8px 16px; align-items: center; gap: 6px 20px; margin-bottom: 12px; }
.client-head .head-main { flex-direction: row; align-items: center; flex-wrap: wrap; gap: 6px 12px; }
.client-head .head-side { align-items: center; gap: 6px 18px; }
.client-head .head-field { gap: 1px; }
.client-head .head-field > span { font-size: 11px; }
/* Стадия — самое длинное в строке. До 1440px — 320px (на 1366 строка
   остаётся одной, замер 07.10), шире — название целиком. Полные названия
   всё равно видны в раскрытом списке. */
.client-head #client-stage { min-height: 0; padding-top: 4px; padding-bottom: 4px; max-width: 320px; }
@media (min-width: 1440px) { .client-head #client-stage { max-width: 380px; } }
.client-head .crm-deals { flex-basis: 100%; margin-top: 0; }
.topbar h1:has(#client-name) { display: flex; align-items: center; gap: 8px; }
.topbar h1 #client-name, .topbar h1 .name-edit {
  font-size: inherit; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.topbar h1 .name-src, .topbar h1 .icon-btn { flex: none; font-size: 12px; font-weight: 400; }
/* Меню «⋯»: закрытие — app.js (щелчок мимо, пункт, Esc). */
.more-menu { position: relative; }
.more-menu > summary { list-style: none; cursor: pointer; }
.more-menu > summary::-webkit-details-marker { display: none; }
.more-menu-list {
  position: absolute; right: 0; top: calc(100% + 4px); z-index: 30; min-width: 220px;
  display: flex; flex-direction: column; align-items: stretch; gap: 2px; padding: 6px;
  background: var(--bg-raised); border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.more-menu-list .btn { justify-content: flex-start; text-align: left; white-space: nowrap; }
/* На телефоне ряд действий прокручивается вбок и обрезал бы выпадающий
   список — там он прикреплён к экрану под шапкой. */
@media (max-width: 640px) {
  .more-menu-list { position: fixed; top: calc(var(--head-h) + 4px); right: 8px; left: auto; }
}
.pill.quiet { color: var(--text-faint); border-color: var(--line); }

/* Поля: подпись — значение — отметка «кто и когда менял». */
.field-rows { display: flex; flex-direction: column; }
.field-row {
  display: grid; grid-template-columns: 190px 1fr; gap: 4px 16px;
  padding: 8px 0; border-bottom: 1px solid var(--line);
}
.field-row:last-child { border-bottom: none; }
.field-label { color: var(--text-faint); font-size: 13px; }
/* Здесь «точка» — символ «•», а не кружок: общее правило `.dot` (кружок 7px
   с заливкой) превращало его в серую каплю поверх текста. */
.field-label .dot {
  color: var(--warn); background: none; width: auto; height: auto;
  border-radius: 0; display: inline;
}
.field-value { font-size: 14px; min-height: 20px; overflow-wrap: anywhere; min-width: 0; }
.field-label { min-width: 0; overflow-wrap: anywhere; }
.field-value.is-editable { cursor: pointer; border-bottom: 1px dashed transparent; }
.field-value.is-editable:hover { border-bottom-color: var(--line); }
.field-value input, .field-value select { width: 100%; }
/* Правка по месту не раздвигает строку: поле 32px вписано в строку значения
   20px отрицательным отступом. Раньше каждая правка сдвигала всё, что ниже,
   на 12px — и обратно после выхода из поля. */
.field-value > input:not([type=checkbox]):not([type=radio]),
.field-value > select:not([multiple]) { margin: -6px 0; }
/* Ссылка под формой блока — отдельной строкой с зазором, а не вплотную к
   кнопке «Сохранить сводку». */
.card-foot-link { display: inline-block; margin-top: 12px; }
/* Подбор комплекта: поля в ряд, выравнены по низу, отступы из шкалы. Было
   инлайном `gap:10px; align-items:flex-end` — без `display:flex` (правила
   `.row` в стилях нет), и поля стояли столбиком. */
.set-picker-row { display: flex; gap: 12px; align-items: flex-end; flex-wrap: wrap; }
.set-picker-row .field { margin: 0; }
.set-picker-row input[type=number] { width: 120px; }
.supply-list { display: flex; flex-direction: column; gap: 4px; }
.supply-line {
  display: grid; grid-template-columns: minmax(0, 1fr) max-content;
  gap: 16px; align-items: baseline;
}
.supply-desc { min-width: 0; }
.supply-size {
  color: var(--text-faint); font-size: 13px; white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.supply-more { margin-top: 8px; }
.field-stamp {
  grid-column: 2; color: var(--text-faint); font-size: 12px;
}

/* Переписка: вкладки по каналам и метка канала у сообщения. */
.feed-tabs { display: flex; gap: 4px; flex-wrap: wrap; }
.feed-tabs .tab {
  font-size: 13px; padding: 4px 12px; border-radius: 16px;
  border: 1px solid var(--line); background: none; color: var(--text-dim);
}
.feed-tabs .tab.is-active { color: var(--text); border-color: var(--text-dim); }
.msg-chan {
  display: inline-block; margin-right: 8px; padding: 0 8px;
  border-radius: 4px; border: 1px solid var(--line);
  font-size: 11px; text-transform: uppercase; letter-spacing: .04em;
}

/* ── Канбан клиентов: колонки-стадии, карточки перетаскиваются ─────────────
   Отдельно от канбана настроек на /funnel: там перетаскивание меняет порядок
   стадий, здесь — двигает клиента. */
.board { display: flex; gap: 12px; overflow-x: auto; padding-bottom: 12px; }
.board-col {
  min-width: 240px; max-width: 240px; background: var(--bg-panel);
  border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden;
  display: flex; flex-direction: column;
}
.board-cap { height: 4px; }
.board-head {
  display: flex; align-items: center; gap: 8px; padding: 12px 12px 4px;
}
.board-title { font-size: 13px; font-weight: 600; }
.board-count {
  margin-left: auto; font-size: 12px; color: var(--text-faint);
}
.board-sum { padding: 0 12px 8px; font-size: 12px; color: var(--text-dim); }
.board-cards {
  display: flex; flex-direction: column; gap: 8px; padding: 8px 8px 12px;
  min-height: 60px;
}
.board-card {
  position: relative;
  border: 1px solid var(--line); border-radius: var(--radius); padding: 8px 12px;
  cursor: grab; background: var(--bg-raised);
}
.board-card:active { cursor: grabbing; }
/* Имя с пилюлей квалификации — одна гибкая обёртка, счётчик — справа.
   Не влезает в строку — пилюля уходит под имя, а имя не рвётся по буквам
   (раньше пилюля отжимала ему половину ширины). */
.board-card-head { display: flex; align-items: center; gap: 8px; min-width: 0; }
.board-card-head a { font-size: 13px; font-weight: 500; }   /* и в «Очереди» */
.board-card-title {
  flex: 1 1 auto; min-width: 0;
  display: flex; flex-wrap: wrap; align-items: center; gap: 2px 8px;
}
.board-card-title a {
  font-size: 13px; font-weight: 500; min-width: 0; overflow-wrap: break-word;
}
.board-card-head .board-unread { flex: none; }
/* «Написать» — значок в шапке карточки (07.10): чат в окошке мессенджера. */
.card-chat { flex: none; width: 24px; height: 24px; padding: 3px; border: 0; border-radius: 6px;
  background: none; color: var(--text-faint); cursor: pointer; display: inline-flex;
  align-items: center; justify-content: center; }
.card-chat svg { width: 16px; height: 16px; }
.card-chat:hover, .card-chat:focus-visible { color: var(--accent); background: var(--bg-hover); }

/* Квалификация — пилюля справа от имени (UI_REDESIGN_SPEC §4). Высокие
   («Наш клиент», «Богатый», «Состоятельный») — акцентная подложка, средний —
   нейтральная, низкий — тихий текст без подложки. */
.q-pill {
  flex: none; max-width: 100%; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; font-size: 11px; font-weight: 500; line-height: 16px;
  padding: 0 8px; border-radius: 9px; border: 1px solid transparent;
}
.q-pill.q-high { background: var(--ok-bg); color: var(--ok); border-color: var(--ok-bg); }
.q-pill.q-mid { background: var(--bg-subtle); color: var(--text-dim); border-color: var(--line); }
.q-pill.q-low { color: var(--text-faint); padding: 0 4px; }
.board-unread {
  margin-left: auto; min-width: 18px; text-align: center;
  border-radius: 9px; background: var(--accent); color: var(--accent-ink);
  font-size: 11px; padding: 1px 4px;
}
.board-card-meta { color: var(--text-faint); font-size: 12px; margin-top: 4px; }
.board-card-field { font-size: 12px; margin-top: 4px; overflow-wrap: anywhere; }
.board-card-field span { color: var(--text-faint); }
.board-more { color: var(--text-faint); font-size: 12px; text-align: center; }
.chips-row { display: flex; flex-wrap: wrap; gap: 12px 16px; }
.check.inline { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; }

/* Мелкие кнопки-иконки: правка имени карточки и полей. Появляются на наведении,
   чтобы не рябить, но существуют всегда — иначе о них не догадаешься. */
.icon-btn {
  border: none; background: none; color: var(--text-faint);
  font-size: 13px; padding: 2px 4px; cursor: pointer; border-radius: 4px;
}
.icon-btn:hover { color: var(--text); background: var(--bg-hover); }
.row-tools { opacity: 0; transition: opacity .12s; white-space: nowrap; }
.field-row:hover .row-tools { opacity: 1; }
.fields-card .card-head { gap: 8px; }
.fields-card .card-head h2 { margin-right: auto; }

/* ── Правка карточки клиента ───────────────────────────────────────────────
   Значение и название поля правятся ПО МЕСТУ, но пишутся не сразу: сначала
   набирается всё, что нужно, потом одна кнопка «Сохранить». Раньше стадия
   менялась «на лету» — точнее, не менялась вовсе: обработчик вызывал функцию,
   которой не существовало, и человек уходил со страницы в уверенности, что
   сохранил. Отсюда и явная кнопка, и предупреждение при уходе. */
.field-value.is-editable { cursor: text; border-radius: 6px; padding: 1px 4px; margin: -1px -4px; }
.field-value.is-editable:hover { background: var(--bg-hover); }
.field-edit { width: 100%; font-size: 14px; padding: 4px 8px; }
/* Многострочная правка: Enter переносит строку, закрывает Ctrl+Enter. Растёт
   под содержимое — полоса прокрутки внутри поля на три строки хуже, чем поле
   на три строки. */
/* Изображение в поле показывается превью: имя файла на экране ничего не
   говорит, а картинка говорит всё. */
.field-image {
  max-width: 100%; max-height: 180px; border-radius: 6px;
  border: 1px solid var(--line); display: block;
}
.field-edit-multi { min-height: 84px; }
/* Действия у значения поля («отложить»): мельче подписи, чтобы не спорить со
   значением, но нажимаемые. */
.field-actions { display: flex; gap: 8px; margin-top: 3px; }
.field-actions .link { font-size: 12px; }
.field-upload { display: flex; flex-direction: column; gap: 4px; }

/* Стрелки порядка блоков. Приглушены и показываются ярче при наведении на
   блок: это настройка вида, а не действие над данными, и бросаться в глаза
   ей незачем. */
.move-block { display: inline-flex; gap: 1px; }
.move-block .icon-btn {
  padding: 0 3px; font-size: 10px; line-height: 1.3;
  color: var(--text-faint);
}
.fields-card:hover .move-block .icon-btn { color: var(--text-dim); }
.move-block .icon-btn:hover { color: var(--text); }

/* Поле, которое переносят в другой блок. */
.field-row.is-dragging { opacity: .45; }
.fields-card.is-drop { outline: 2px dashed var(--accent); outline-offset: 2px; }
.field-row.is-drop-before { box-shadow: inset 0 2px 0 var(--accent); }
.field-row.is-drop-after { box-shadow: inset 0 -2px 0 var(--accent); }
.field-grip {
  cursor: grab; color: var(--text-faint); font-size: 12px;
  padding: 0 4px; user-select: none; opacity: 0;
}
.field-row:hover .field-grip { opacity: 1; }
.field-grip:active { cursor: grabbing; }

/* Значок календаря у полей с датой. Раньше его инвертировали фильтром — на
   тёмной теме родной значок был чёрным. Теперь тему знает сам браузер
   (`color-scheme` в :root), и значок светлеет/темнеет вместе с ней; фильтр в
   светлой теме сделал бы его невидимым. Курсор-указатель: по нему нажимают. */
input[type=date]::-webkit-calendar-picker-indicator,
input[type=datetime-local]::-webkit-calendar-picker-indicator,
input[type=time]::-webkit-calendar-picker-indicator {
  cursor: pointer; opacity: .75;
}
input[type=date]::-webkit-calendar-picker-indicator:hover,
input[type=datetime-local]::-webkit-calendar-picker-indicator:hover,
input[type=time]::-webkit-calendar-picker-indicator:hover { opacity: 1; }

.field-edit-area {
  resize: vertical; min-height: 52px; max-height: 260px;
  line-height: 1.45; font: inherit; font-size: 14px;
}
.field-title-edit { font-size: 13px; padding: 3px 8px; max-width: 190px; }

/* Изменённое, но ещё не сохранённое, помечаем полосой слева: список полей
   длинный, и без метки не видно, что именно уедет по кнопке. */
.field-row.is-dirty { border-left: 2px solid var(--warn); padding-left: 8px; margin-left: -10px; }
.field-row.is-dirty .field-title { color: var(--warn); }

/* Кнопка «Сохранить» живёт в шапке страницы и всегда на виду: она отвечает за
   всю карточку сразу — имя, стадию, значения и названия полей. */
.save-btn { min-width: 118px; }
.save-btn:disabled { opacity: .45; }
.name-edit { font-size: 20px; font-weight: 600; padding: 3px 8px; max-width: 340px; }
.editable-name { cursor: text; border-radius: 6px; padding: 0 4px; margin: 0 -4px; }
.editable-name:hover { background: var(--bg-hover); }

.board-card .pick { margin: 0 2px 0 0; }

/* ── Вкладки верхнего меню ─────────────────────────────────────────────────
   Пункты слева относятся к активной вкладке. До этого все девятнадцать
   пунктов стояли одной колонкой и глазами не просматривались. */
.tabbar {
  display: flex; gap: 2px; padding: 0 24px; align-items: flex-end;
  border-bottom: 1px solid var(--line); overflow-x: auto;
  scrollbar-width: none;           /* прокрутка вкладок — жестом, без полосы */
}
.tabbar::-webkit-scrollbar { display: none; }
.tabbar-item {
  padding: 12px 12px 10px; font-size: 14px; color: var(--text-dim);
  border-bottom: 2px solid transparent; white-space: nowrap;
}
.tabbar-item:hover { color: var(--text); }
.tabbar-item.is-active {
  color: var(--text); border-bottom-color: var(--accent);
}

/* ── Доска: одна верхняя панель ────────────────────────────────────────────
   Панель ОДНА и в одну строку. До этого поиск и переключатель вида были и в
   шапке страницы, и здесь, а панель массовых действий висела отдельной
   карточкой во всю ширину — верх экрана съедал половину страницы, и было
   неясно, какой из двух поисков настоящий.

   Строк по-прежнему две, но они взаимоисключающие: пока ничего не выбрано,
   видна строка поиска; как только выбрана карточка, на её месте появляется
   строка массовых действий. Так работает любая почта, и высота панели не
   меняется. */
.board-bar { padding: 8px 12px; }
.board-bar-row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
/* Кнопки панели доски — одной высоты и по центру строки: «🗄 Архив» (ссылка
   с эмодзи) стоял выше «Стадий» и «⚙ вида» на 3px. */
.board-bar-row > button, .board-bar-row > .btn {
  display: inline-flex; align-items: center; height: 32px;
}

/* Поиск — главный элемент панели, поэтому он один и с лупой внутри поля. */
.search-box { position: relative; flex: 1 1 260px; min-width: 190px; max-width: 460px; }
.search-box::before {
  content: '⌕'; position: absolute; left: 10px; top: 50%;
  transform: translateY(-50%); color: var(--text-faint);
  font-size: 17px; line-height: 1; pointer-events: none;
}
.board-search {
  width: 100%; padding: 8px 24px 8px 29px; border-radius: var(--radius);
  background: var(--bg-raised); color: var(--text);
}
.search-clear {
  position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
  border: none; background: none; color: var(--text-faint);
  font-size: 15px; padding: 2px 8px; cursor: pointer; border-radius: 4px;
}
.search-clear:hover { color: var(--text); }

/* ── Важность полей ───────────────────────────────────────────────────────
   Подсвечивается только ПУСТОЕ важное поле: у заполненного важность уже не
   новость. Цвет берётся у самого поля (`--field-color`) — настраивается в
   «Полях карточки» и действует у всех клиентов сразу. */
.field-row[data-need] { border-left: 2px solid var(--field-color, var(--flag-silent)); padding-left: 8px; }
.field-row[data-need="required"] { --field-color: var(--flag-overdue); }
.field-row[data-need="important"] { --field-color: var(--flag-silent); }
.need {
  font-size: 11px; font-weight: 500; padding: 1px 8px; border-radius: 3px;
  margin-left: 8px; white-space: nowrap;
}
.need-required { color: var(--flag-overdue); border: 1px solid var(--flag-overdue); }
.need-important { color: var(--flag-silent); border: 1px solid var(--flag-silent); }

/* ── Состояние карточки ───────────────────────────────────────────────────
   Полоса слева и одна подпись — не заливка всей карточки: залитая читается
   как «эта карточка другая», а нам надо сказать «на эту смотри первой».

   Цвета РАЗНЫЕ ПО СМЫСЛУ, а не по красоте: красный — просрочено (клиент ждёт
   или просрочен обещанный контакт), фиолетовый — ответ готов и не отправлен,
   сроки ещё не вышли, жёлтый — клиент замолчал. Значения задаются в
   настройках и приходят переменными `--flag-*` из base.html; своих значений
   по умолчанию здесь нет — третья копия умолчаний из config/settings.py
   (вторая — в web/ui.py) была бы лишней. Тема их не перебивает. */
.board-card[data-flag] { border-left: 3px solid var(--line); }
.board-card[data-flag="overdue"] { border-left-color: var(--flag-overdue); }
.board-card[data-flag="draft"] { border-left-color: var(--flag-draft); }
.board-card[data-flag="silent"] { border-left-color: var(--flag-silent); }
.board-card[data-flag="stale"] { border-left-color: var(--flag-stale); }
.board-card[data-flag="good"] { border-left-color: var(--flag-good); }

/* ── Фильтр по цвету в панели доски ───────────────────────────────────────
   Чипы стоят в самой панели, а не в настройках вида: «покажи просроченные» —
   первый вопрос к доске, и ради него не должно приходиться открывать «⚙ вид».
   Невыбранные приглушены: в обычном состоянии панель не должна пестреть. */
.flag-filter { display: inline-flex; gap: 4px; align-items: center; flex-wrap: wrap; }
.flag-chip {
  display: inline-flex; align-items: center; gap: 8px; height: 32px;
  padding: 0 8px; font-size: 13px; border-radius: var(--radius);
  border: 1px solid var(--line); background: none; color: var(--text-dim);
  cursor: pointer; white-space: nowrap;
}
.flag-chip .dot { flex: none; width: 8px; height: 8px; border-radius: 50%; background: currentColor; }
/* Число в чипе — моно, чтобы «4» и «12» стояли одинаково. */
.flag-chip .chip-n {
  font-family: var(--mono); font-size: 12px; color: var(--text-faint);
  min-width: 1.5ch; text-align: right; font-variant-numeric: tabular-nums;
}
.flag-chip.is-on .chip-n { color: var(--text-dim); }
.flag-chip.flag-overdue .dot { background: var(--flag-overdue); }
.flag-chip.flag-draft .dot { background: var(--flag-draft); }
.flag-chip.flag-silent .dot { background: var(--flag-silent); }
.flag-chip.flag-stale .dot { background: var(--flag-stale); }
.flag-chip.flag-good .dot { background: var(--flag-good); }
.flag-chip:hover { color: var(--text); border-color: var(--text-dim); }
.flag-chip.is-on { color: var(--text); border-color: var(--accent); background: var(--accent-soft); }

/* Фильтр словами: что фильтруем — обычным текстом, чем — приглушённым. */
.filter-what { font-weight: 500; }
.filter-how { color: var(--text-dim); }

/* Строка состояния — ПЕРВАЯ строка карточки, цветом состояния. Кнопки
   переноса и паузы стоят в той же строке и переносятся целиком, а не по
   одной под текст. */
.card-flag {
  display: flex; flex-wrap: wrap; align-items: center; gap: 4px;
  font-size: 12px; font-weight: 500; margin-bottom: 4px;
}
/* Кнопки «отложить» в подписи состояния: мелкие и приглушённые — это правка
   срока, а не действие над клиентом. */
.card-flag .postpone {
  font-size: 11px; line-height: 16px; opacity: .75; color: inherit;
  border: 1px solid currentColor; border-radius: 3px; padding: 0 4px;
}
.card-flag .postpone:first-of-type { margin-left: auto; }
.card-flag .postpone:hover { opacity: 1; }
.flag-overdue { color: var(--flag-overdue); }
.flag-draft { color: var(--flag-draft); }
.flag-silent { color: var(--flag-silent); }
.flag-stale { color: var(--flag-stale); }
.flag-good { color: var(--flag-good); }

/* Действия в строке таблицы: одинаковая высота, один зазор, перенос на узком
   экране. Кнопки одного ряда должны выглядеть кнопками одного ряда. */
.row-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.one-line {
  max-width: 340px; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap;
}
.row-actions > .btn, .row-actions > button { white-space: nowrap; }

/* Пока идёт запрос, колонки чуть гаснут: видно, что список ещё не окончательный,
   но читать его уже можно. Подменять содержимое «спиннером» хуже — пропадает
   то, на что человек смотрит. */
#board-live.is-searching { opacity: .55; transition: opacity .12s; }

/* Переключатель вида — сегментами, а не двумя отдельными кнопками: так видно,
   что это одна настройка с двумя положениями, а не два действия. */
.seg { display: inline-flex; border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
.seg a {
  padding: 8px 12px; font-size: 13px; color: var(--text-dim);
  border-right: 1px solid var(--line); white-space: nowrap;
}
.seg a:last-child { border-right: none; }
.seg a:hover { color: var(--text); }
.seg a.is-active { background: var(--accent-dim); color: var(--text); }

.board-summary {
  margin-left: auto; color: var(--text-dim); font-size: 13px;
  white-space: nowrap;
}
#board-setup-btn { padding: 8px 12px; }

/* Массовые действия: та же панель, та же высота, только когда есть выбор. */
.select-bar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.select-bar select { max-width: 190px; }
.select-count { font-weight: 600; white-space: nowrap; }
.select-bar .sep { color: var(--text-faint); }
.select-bar .tail { margin-left: auto; display: flex; gap: 8px; }
#board-setup-btn.is-active { color: var(--text); border-color: var(--text-dim); }
.setup-block { border-top: 1px solid var(--line); padding-top: 12px; margin-top: 8px; }
.setup-block .sub-title { margin-bottom: 8px; }
.filter-row {
  display: flex; align-items: center; gap: 8px; padding: 4px 0;
  font-size: 13px;
}
.filter-row .cell-sub { margin-left: auto; }

/* Галочки на карточках появляются, только когда выбор начат: постоянные
   галочки рябят и мешают читать доску. */
.board-card .pick { display: none; }
.board.is-picking .board-card .pick { display: inline-block; }
.board-card.is-picked { outline: 2px solid var(--accent); }
.board-card-draft { font-size: 13px; margin-top: 4px; }
.draft-tab.is-active { color: var(--warn); border-color: var(--warn); }

/* ── Калькулятор и конструктор прайса ──────────────────────────────────────
   Таблиц здесь много и они узкие (размеры, расход, ставки), поэтому вариант
   таблицы с меньшими отступами: иначе разбивка по блокам не влезает на экран
   и владелец не видит, из чего сложилась цена. */
.table.compact th, .table.compact td { padding: 4px 8px; font-size: 13px; }
.table.compact input[type=number], .table.compact input[type=text] {
  width: 100%; min-width: 64px; padding: 4px 8px; font-size: 13px;
}
.totals-row { display: flex; gap: 8px; flex-wrap: wrap; margin: 12px 0; align-items: center; }
.pill.big { font-size: 15px; font-weight: 600; padding: 8px 12px; }
/* Расчёт и КП: овалы двигаются, строки блоков тянут за номер, сравнение комплектов. */
#calc-pills [draggable="true"] { cursor: grab; }
#calc-blocks td.b-num { cursor: grab; color: var(--text-faint); text-align: center;
  width: 28px; user-select: none; }
#calc-blocks tr.is-dragging { opacity: .45; }
.calc-compare { display: grid; gap: 6px; margin: 0 0 12px; }
.calc-compare-row { display: grid; grid-template-columns: minmax(180px, 1fr) auto 28px;
  gap: 8px; align-items: center; padding: 6px 8px; border: 1px solid var(--line);
  border-radius: 10px; }
.calc-compare-row .totals-row { margin: 0; }
.calc-compare-row.is-now { border-color: var(--line-strong); }
.calc-compare-label { font-size: 13px; color: var(--text-dim); }
@media (max-width: 760px) { .calc-compare-row { grid-template-columns: 1fr 28px; }
  .calc-compare-row .totals-row { grid-column: 1 / -1; grid-row: 2; } }
.family-block { border-top: 1px solid var(--line); padding-top: 12px; margin-top: 12px; }
.family-block .actions-row { margin-bottom: 8px; }
.family-block .field { display: flex; flex-direction: column; font-size: 12px; color: var(--text-dim); }

/* ── Управление стадиями в канбане ─────────────────────────────────────────
   Как в Bitrix: инструменты колонки появляются на наведении. Постоянно
   висящие иконки над двадцатью колонками превращают доску в рябь, а совсем
   спрятанные — в загадку, поэтому они существуют всегда и проявляются, когда
   мышь над колонкой. */
.board-head { position: relative; }
.col-tools {
  position: absolute; right: 0; top: -2px;
  display: flex; align-items: center; gap: 1px;
  opacity: 0; transition: opacity .12s;
  background: var(--bg-panel); padding-left: 4px; border-radius: 6px;
}
.board-col:hover .col-tools { opacity: 1; }
.col-grip {
  cursor: grab; color: var(--text-faint); font-size: 12px;
  padding: 2px 3px; line-height: 1; user-select: none;
}
.col-grip:active { cursor: grabbing; }
.col-grip:hover { color: var(--text); }
.col-tools .icon-btn { padding: 1px 4px; font-size: 13px; }

/* Колонка в переносе и место, куда она встанет. Без подсветки непонятно, что
   произойдёт при отпускании. */
.board-col.is-dragging { opacity: .45; }
.board-col.drop-here { outline: 2px dashed var(--accent); outline-offset: 2px; }

/* Вложения в переписке. Картинку показываем сразу и небольшой: клиент шлёт
   референсы пачками, и полноразмерные фото выдавили бы текст с экрана.
   По клику открывается оригинал. */
.msg-media { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.msg-media img {
  max-width: 180px; max-height: 180px; border-radius: var(--radius); display: block;
  border: 1px solid var(--line);
}
.msg-media img:hover { border-color: var(--text-faint); }

/* Кнопка с включённым отбором: видно из бара, что показаны не все стадии. */
button.ghost.is-on {
  border-color: var(--accent); color: var(--accent);
}
#stage-picker .chips-row { max-height: 168px; overflow-y: auto; padding: 2px 0; }

/* ── Плашка источника имени ────────────────────────────────────────────────
   Стоит сразу за именем, потому что относится к нему, и подсвечена по смыслу:
   «имени нет» — это работа для человека, и она должна бросаться в глаза, а
   «из Bitrix» — сноска, которая мешать не должна. */
.name-src {
  font-size: 11px; padding: 2px 8px; border-radius: 9px;
  border: 1px solid var(--line); color: var(--text-faint);
  white-space: nowrap; vertical-align: middle;
}
.name-src.is-missing {
  color: var(--accent-ink); background: var(--warn); border-color: var(--warn);
  font-weight: 600;
}
.name-src.is-manual { color: var(--accent); border-color: var(--accent-dim); }
.name-src.is-auto { background: var(--bg-raised); }
/* На карточке канбана плашка мельче: там она соседствует с именем-ссылкой. */
.name-src.small { font-size: 10px; padding: 1px 8px; }

/* ── Окно выбора (клиент для КП) ───────────────────────────────────────────
   Отдельным окном, потому что выбор требует прочитать приметы: номер, стадию,
   модель, ткань, комплект. В подсказке под строкой это не помещается, а из
   списка одних имён выбирают наугад. */
.overlay {
  position: fixed; inset: 0; z-index: 50;
  background: var(--scrim);
  display: flex; align-items: flex-start; justify-content: center;
  padding: 8vh 16px 16px;
}
.overlay-box {
  background: var(--bg-panel); border: 1px solid var(--line);
  border-radius: var(--radius); width: min(720px, 100%);
  max-height: 76vh; display: flex; flex-direction: column;
  padding: 16px 16px; box-shadow: var(--shadow);
}
.overlay-head { display: flex; gap: 12px; align-items: center; }
.picker-open {
  text-align: left; width: 100%; max-width: 420px;
}
.picker-rows { overflow-y: auto; margin-top: 8px; }

/* Строками, а не плитками: строки просматриваются сверху вниз быстрее, и в них
   помещается вторая строчка с приметами. */
.picker-row {
  display: block; width: 100%; text-align: left; border: none;
  border-bottom: 1px solid var(--line); background: none;
  padding: 8px 8px; border-radius: 0;
}
.picker-row:hover, .picker-row.is-active { background: var(--bg-hover); }
/* Касание без содержимого выбрать нельзя — и это видно, а не выясняется при
   нажатии «Отправить». */
.picker-row.is-off { opacity: .55; cursor: not-allowed; }

/* ── Выбор касаний ────────────────────────────────────────────────────────
   Сетка крупных карточек, а не список строк: касание узнаётся по
   фотографиям — «Коллекция ткани» и «Категории тканей» на слух одинаковы.
   Три-четыре в ряд и три-четыре в высоту: больше не помещается читаемо,
   меньше — заставляет листать там, где нужно окинуть взглядом. */
.overlay-wide { width: min(1180px, 100%); max-height: 86vh; }

.touch-grid {
  display: grid; gap: 12px; margin-top: 12px;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  overflow-y: auto; padding: 2px;
}
.touch-card {
  position: relative; cursor: pointer;
  background: var(--bg-raised); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 12px 12px;
  display: flex; flex-direction: column; gap: 8px;
  transition: border-color .12s, transform .12s;
}
.touch-card:hover { border-color: var(--text-dim); }
.touch-card.is-chosen {
  border-color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
}
.touch-card.is-off { opacity: .5; cursor: not-allowed; }
.touch-card.is-off:hover { border-color: var(--line); }
.touch-card h3 { font-size: 14.5px; margin: 0; line-height: 1.3; }

/* Номер — это МЕСТО В ОЧЕРЕДИ. Порядок отправки задаётся порядком выбора, и
   он должен быть виден, а не держаться в голове. */
.touch-num {
  position: absolute; top: -7px; left: -7px;
  width: 24px; height: 24px; border-radius: 50%;
  background: var(--accent); color: var(--accent-ink);
  display: grid; place-items: center;
  font-size: 13px; font-weight: 600;
}
.touch-tags { display: flex; gap: 4px; flex-wrap: wrap; }
.touch-text {
  font-size: 13px; color: var(--text-dim); line-height: 1.45;
  margin: 0; overflow: hidden;
  display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical;
}
.touch-text.is-empty { color: var(--text-faint); font-style: italic; }
.touch-shots {
  display: flex; gap: 4px; margin-top: auto; align-items: center;
  flex-wrap: wrap;
}
.touch-shots img {
  width: 48px; height: 48px; object-fit: cover; border-radius: 4px;
  border: 1px solid var(--line);
}
.touch-more { font-size: 12px; color: var(--text-faint); }
.picker-row.is-off:hover { background: none; }
.picker-row.is-active { box-shadow: inset 2px 0 0 var(--accent); }
.picker-line { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.picker-num { color: var(--text-dim); font-size: 13px; }
.picker-sub {
  display: block; color: var(--text-faint); font-size: 12px; margin-top: 3px;
}
.picker-row mark { background: var(--warn-bg); color: var(--warn); border-radius: 3px; }

/* Готовое КП: кнопка «Скачать» рядом с расчётом. Раньше файл был доступен
   только из карточки клиента — приходилось уходить со страницы и искать её. */
.quote-ready {
  border: 1px solid var(--accent-dim); background: var(--bg-raised);
  border-radius: var(--radius); padding: 12px 16px; margin-bottom: 12px;
  display: flex; gap: 12px; align-items: center; flex-wrap: wrap;
}
.quote-ready .draft-failed { flex-basis: 100%; margin: 0; }

/* ── Сворачиваемые блоки конструктора ──────────────────────────────────────
   Конструктор — самая длинная часть страницы: четыре модели, у каждой семьи
   две таблицы. Развёрнутый целиком, он превращает страницу в свиток, и,
   прокручивая ниже, чем собирался, человек оказывается в чужих цифрах.
   Используем `<details>`: он сворачивается и без скриптов, доступен с
   клавиатуры и не требует своей механики. */
.fold-head {
  cursor: pointer; display: flex; align-items: baseline; gap: 12px;
  flex-wrap: wrap; list-style: none; padding: 8px 0;
}
.fold-head::-webkit-details-marker { display: none; }
.fold-head::before {
  content: '▸'; color: var(--text-faint); font-size: 11px;
  transition: transform .12s;
}
details[open] > .fold-head::before { transform: rotate(90deg); }
.fold-head:hover { color: var(--text); }
.fold-head:hover::before { color: var(--text); }
.fold.inner { margin: 8px 0 8px 16px; }
.fold.inner > .fold-head { font-size: 13px; color: var(--text-dim); }
details.card > .card-head { margin-bottom: 0; }
details.card[open] > .card-head { margin-bottom: 16px; }

/* Источник клиента на карточке канбана — это КАНАЛ. Прежняя плашка писала
   «Bitrix» на 517 карточках из 527: это происхождение имени, а не источник
   человека, и читалось оно ровно наоборот. */
/* Форма ответа под лентой. Прижата к низу колонки переписки: писать
   удобнее там, где кончается разговор. */
.composer {
  border-top: 1px solid var(--line); padding: 10px 0 0; margin-top: 8px;
  display: flex; flex-direction: column; gap: 6px;
  flex: none;                     /* лента сжимается, форма — нет */
}
/* Поле ответа одной строкой, как в мессенджере: скрепка, текст, готовое,
   быстрые, «позже» и круглая кнопка отправки. */
.composer-bar { display: flex; align-items: flex-end; gap: 4px; padding: 4px 4px 4px 6px;
  border: 1px solid var(--line-strong); border-radius: 22px; background: var(--bg-raised); }
.composer-bar:focus-within { border-color: var(--accent); }
.composer-bar textarea { flex: 1; min-width: 0; border: 0; background: none; resize: none;
  min-height: 36px; max-height: 30vh; padding: 8px 6px; font: inherit; line-height: 1.4;
  color: var(--text); outline: none; box-shadow: none; }
.cmp-btn { flex: none; width: 36px; height: 36px; border-radius: 50%; border: 0; padding: 0;
  display: inline-flex; align-items: center; justify-content: center; background: none;
  color: var(--text-dim); cursor: pointer; font-size: 15px; }
.cmp-btn:hover { background: var(--bg-hover); color: var(--text); }
.cmp-btn svg { width: 20px; height: 20px; }
.cmp-send { flex: none; width: 38px; height: 38px; border-radius: 50%; border: 0; padding: 0;
  display: inline-flex; align-items: center; justify-content: center; cursor: pointer;
  background: var(--accent); color: var(--accent-ink); }
.cmp-send svg { width: 18px; height: 18px; margin-left: 2px; }
.cmp-send:disabled, .cmp-send.is-sending { opacity: .5; cursor: progress; }
.composer-head, .composer-foot {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.composer-sub { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 0 8px;
  font-size: 12px; }
.composer-sub select { width: auto; padding: 2px 8px; font-size: 12px; border-radius: 12px; }
.composer-hint { margin-left: auto; }
.composer-reply { display: flex; align-items: center; gap: 8px; padding: 4px 8px 4px 10px;
  border-left: 3px solid var(--accent); border-radius: 8px; background: var(--bg-hover);
  font-size: 12.5px; }
.composer-reply-body { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; color: var(--text-dim); }
.composer-reply-body b { color: var(--accent); margin-right: 6px; }

/* Кнопка, выглядящая ссылкой: для мелких действий внутри подсказки, где
   настоящая кнопка перетянула бы на себя внимание. */
.linklike {
  background: none; border: 0; padding: 0; cursor: pointer;
  color: var(--accent); font: inherit; text-decoration: underline;
}
.linklike:hover { opacity: .8; }

/* Отложенное сообщение в ленте: пунктир — «ещё не ушло». Сплошная рамка
   означала бы отправленное, а перепутать тут дорого. */
.msg.is-scheduled {
  border: 1px dashed var(--flag-draft);
  background: transparent;
}
.btn-timer { padding: 8px 8px; line-height: 1; }

/* Кнопка «назад» в шапке: узкая, чтобы не спорить с заголовком. */
.btn-back { padding: 4px 12px; font-size: 15px; line-height: 1; }

.card-src { color: var(--text-dim); font-weight: 500; }

/* Имя из мессенджера на карточке доски. Приглушено и отделено: это подсказка
   «почему карточка нашлась», а не второе название. */
.card-handle {
  color: var(--text-faint); margin-left: 8px;
  overflow-wrap: anywhere;
}
.card-handle::before { content: '· '; }

/* Поле выбора даты для «отложить» с доски: нужно, чтобы открылся родной
   календарь, а само поле на карточке видеть незачем — оно исчезает сразу
   после выбора. Прячем размером, а не `display:none`: скрытому элементу
   браузер календарь не откроет. */
.postpone-picker {
  position: absolute; width: 1px; height: 1px; padding: 0; border: 0;
  opacity: 0; pointer-events: none;
}

/* Вторая сделка в Bitrix. Не ошибка (у человека правда может быть два
   заказа), но и не мелочь: во вторую сделку мы не пишем никогда. Поэтому
   заметно, но без красного. */
.crm-deals { margin-top: 12px; }
.crm-deals-warn {
  border: 1px solid var(--flag-silent); border-radius: var(--radius);
  background: var(--bg-raised); padding: 12px 12px; font-size: 13px;
  line-height: 1.5; color: var(--text);
}
.crm-deals-warn ul { margin: 8px 0 4px; padding-left: 16px; }
.crm-deals-warn li { margin: 2px 0; }

/* Плашка «карточка объединена»: сама карточка после слияния пуста, и без
   объяснения выглядит потерянной. */
.merged-note {
  border-left: 3px solid var(--accent);
  padding: 12px 16px;
  margin-bottom: 12px;
}

/* ── Объединение карточек ───────────────────────────────────────────────────
   Раньше выбор шёл двумя системными confirm(): «ОК — Иван, Отмена — Иван».
   Здесь обе карточки видны рядом, и по каждому блоку сказано, откуда брать. */
.merge-cards { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }

.merge-card {
  display: block; cursor: pointer;
  border: 2px solid var(--line); border-radius: var(--radius);
  padding: 12px 12px;
}
.merge-card:has(input:checked) { border-color: var(--accent); }
.merge-card input { margin-right: 8px; }

.merge-blocks { margin-top: 16px; display: grid; gap: 8px; }

.merge-block {
  display: flex; gap: 12px; align-items: baseline;
  flex-wrap: wrap; justify-content: space-between;
  border-top: 1px solid var(--line); padding-top: 8px;
}
.merge-block-title { display: flex; gap: 8px; align-items: baseline;
                     flex-wrap: wrap; }
.merge-options { display: flex; gap: 12px; flex-wrap: wrap; }
.merge-option { display: flex; gap: 4px; align-items: center; cursor: pointer; }

@media (max-width: 720px) {
  .merge-cards { grid-template-columns: 1fr; }
}

/* ── Расчёт: сводка наверху, цех, доппозиции ────────────────────────────────
   Сводку подняли над блоками: до цены приходилось пролистывать весь список
   модулей, а смотрят на неё чаще всего. */
.totals-top {
  /* Прилипает ПОД шапку страницы: с `top: 0` сводка уезжала под неё. */
  position: sticky; top: var(--head-h); z-index: 2;
  background: var(--bg-panel); padding: 8px 0; margin-bottom: 8px;
  border-bottom: 1px solid var(--line);
}

.shop-panel { margin-bottom: 12px; }

.shop-fields {
  display: grid; gap: 12px;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
}
.shop-field { display: flex; flex-direction: column; gap: 3px; }
.shop-field input { width: 100%; }

.extra-row input[type="text"] { width: 100%; }
.extra-row input[type="number"] { width: 110px; }

/* Сообщение, которое сейчас уходит. Пока канал не ответил, пузырь бледный:
   обещать доставку, которой ещё не было, нельзя. */
.msg.is-pending { opacity: 0.55; }
.msg.is-pending .msg-meta::before { content: "⏳ "; }

/* Шапка КП в редакторе текстов: видно, что уйдёт клиенту на первой странице. */
.hero-box { margin-top: 8px; }
.hero-preview {
  display: block; max-width: 100%; max-height: 220px;
  border: 1px solid var(--line); border-radius: var(--radius);
  margin-bottom: 8px;
}

/* Состав КП в карточке: список позиций как есть, моноширинным не делаем —
   это обычный текст, который уйдёт в договор. */
.quote-body pre {
  white-space: pre-wrap; font: inherit; margin: 8px 0 0;
  color: var(--text-dim);
}

/* Поле сборки комплекта (мм). Сетка фона — шаг модели (размер задаёт
   composerRender); блоки — DOM, тяга — pointer events. */
.composer-grid {
  position: relative;
  background-image: linear-gradient(var(--line) 1px, transparent 1px),
                    linear-gradient(90deg, var(--line) 1px, transparent 1px);
  background-size: 35px 35px;
  background-color: var(--bg-subtle);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  min-height: 220px;
  overflow: hidden;
  margin-top: 8px;
}
.composer-grid > .help { padding: 16px; margin: 0; }
.composer-block {
  position: absolute;
  box-sizing: border-box;
  background: var(--accent-soft);
  border: 1px solid var(--accent);
  border-radius: 4px;
  display: flex; align-items: center; justify-content: center;
  font-size: 11px; line-height: 1.2; color: var(--text);
  cursor: grab; user-select: none; -webkit-user-select: none;
  touch-action: none;
}
/* Слои — как на чертеже (set_layout.LAYER): пол → подлокотник → спинка →
   подушка; выбранный и перетаскиваемый блок — поверх всех. */
.composer-block.is-dragging { cursor: grabbing; opacity: .92; z-index: 6; }
.composer-block.picked { outline: 2px solid var(--accent); outline-offset: 1px; z-index: 5; }
.composer-block.role-back, .composer-block.role-cushion {
  background: var(--bg-raised); border-style: dashed;
}
.composer-block.role-armrest { background: var(--accent-dim); z-index: 1; }
.composer-block.role-back { z-index: 2; }
.composer-block.role-cushion { z-index: 3; }
.composer-block.role-table, .composer-block.role-pouf, .composer-block.role-other {
  background: var(--bg-hover); border-color: var(--line-strong);
}
.composer-block.is-clash {
  background: var(--err-bg); border-color: var(--err); outline-color: var(--err);
}
.cmp-name {
  padding: 2px 4px; text-align: center; overflow: hidden;
  font-variant-numeric: tabular-nums; pointer-events: none;
}
/* Куда смотрит деталь (спинка модуля, подлокотник) — полоса у этой стороны:
   поворот на поле виден так же, как на чертеже. */
.cmp-back { position: absolute; background: var(--accent); opacity: .55; pointer-events: none; }
.cmp-back-top { top: 2px; left: 8%; right: 8%; height: 4px; border-radius: 2px; }
.cmp-back-bottom { bottom: 2px; left: 8%; right: 8%; height: 4px; border-radius: 2px; }
.cmp-back-left { left: 2px; top: 8%; bottom: 8%; width: 4px; border-radius: 2px; }
.cmp-back-right { right: 2px; top: 8%; bottom: 8%; width: 4px; border-radius: 2px; }
/* Ручки растягивания — по серединам сторон выбранного блока. */
.cmp-h {
  position: absolute; width: 14px; height: 14px;
  background: var(--bg-panel); border: 2px solid var(--accent); border-radius: 50%;
  touch-action: none; z-index: 4;
}
.cmp-h-n { top: -8px; left: calc(50% - 7px); cursor: ns-resize; }
.cmp-h-s { bottom: -8px; left: calc(50% - 7px); cursor: ns-resize; }
.cmp-h-e { right: -8px; top: calc(50% - 7px); cursor: ew-resize; }
.cmp-h-w { left: -8px; top: calc(50% - 7px); cursor: ew-resize; }
@media (pointer: coarse) {
  /* Палец: ручки не меньше 24 px. */
  .cmp-h { width: 26px; height: 26px; }
  .cmp-h-n { top: -14px; left: calc(50% - 13px); }
  .cmp-h-s { bottom: -14px; left: calc(50% - 13px); }
  .cmp-h-e { right: -14px; top: calc(50% - 13px); }
  .cmp-h-w { left: -14px; top: calc(50% - 13px); }
}
.cmp-dim {
  position: absolute; transform: translateX(-50%); z-index: 5;
  padding: 2px 8px; border-radius: 999px; font-size: 12px; white-space: nowrap;
  background: var(--text); color: var(--bg); pointer-events: none;
  font-variant-numeric: tabular-nums;
}
/* Панель свойств под полем и то же меню по правому клику. */
.cmp-props, .cmp-menu {
  display: flex; flex-wrap: wrap; gap: 10px 14px; align-items: flex-end;
}
.cmp-props {
  margin-top: 12px; padding: 12px; border: 1px solid var(--line);
  border-radius: var(--radius); background: var(--bg-raised);
}
.cmp-props.is-empty { background: none; border-style: dashed; }
.cmp-props .help { margin: 0; }
.cmp-prop { display: flex; flex-direction: column; gap: 4px; font-size: 12px; color: var(--text-dim); }
.cmp-prop input { width: 110px; }
.cmp-prop select { min-width: 130px; }
.cmp-prop-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.cmp-prop-hint { flex-basis: 100%; margin: 0; }
.cmp-menu {
  position: fixed; z-index: 60; width: 300px; max-width: calc(100vw - 16px);
  padding: 12px; background: var(--bg-panel); border: 1px solid var(--line-strong);
  border-radius: var(--radius); box-shadow: var(--shadow);
}
.cmp-menu[hidden], .cmp-palette[hidden] { display: none; }
.cmp-menu .cmp-prop input, .cmp-menu .cmp-prop select { width: 120px; min-width: 0; }
/* Палитра «+ Добавить элемент». */
.cmp-add { position: relative; }
.cmp-palette {
  position: absolute; left: 0; bottom: calc(100% + 6px); z-index: 50;
  width: min(560px, calc(100vw - 32px)); max-height: 60vh; overflow: auto;
  padding: 12px; background: var(--bg-panel); border: 1px solid var(--line-strong);
  border-radius: var(--radius); box-shadow: var(--shadow);
}
.cmp-pal-group + .cmp-pal-group { margin-top: 12px; }
.cmp-pal-group h3 { margin: 0 0 6px; font-size: 12px; font-weight: 600; color: var(--text-dim); }
.cmp-pal-group .cell-sub { margin: 0; }
.cmp-tile {
  display: inline-flex; flex-direction: column; align-items: flex-start; gap: 2px;
  margin: 0 6px 6px 0; padding: 6px 10px; min-height: 44px; text-align: left;
}
.cmp-tile b { font-weight: 600; font-size: 13px; }
.cmp-tile span { font-size: 12px; color: var(--text-dim); font-variant-numeric: tabular-nums; }
/* Пресеты модели — рядом с типами. */
.cmp-presets { align-items: center; margin-top: 8px; }
.cmp-presets-label { font-size: 12px; color: var(--text-dim); }
.cmp-preset { display: inline-flex; }
.cmp-preset > button:first-child { border-top-right-radius: 0; border-bottom-right-radius: 0; }
.cmp-preset-x {
  border-top-left-radius: 0; border-bottom-left-radius: 0; border-left: none;
  padding: 0 10px; color: var(--text-dim);
}
.cmp-preset.is-on > button { border-color: var(--accent); background: var(--accent-soft); }
.cmp-preset-form { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.cmp-preset-form[hidden] { display: none; }
.cmp-preset-form input { flex: 1 1 260px; }
@media (max-width: 640px) {
  .cmp-palette { position: fixed; left: 16px; right: 16px; bottom: 16px; width: auto; }
  .cmp-prop input, .cmp-prop select { width: 100%; min-width: 0; }
  .cmp-prop { flex: 1 1 40%; }
}
/* Тип, с которого открыт чертёж из истории, — подсвечен. */
#cmp-types button.is-on { border-color: var(--accent); background: var(--accent-soft); }

/* История конструктора: таблица чертежей с сортировкой по столбцам. */
.cmp-history .th-sort {
  background: none; border: none; padding: 0; font: inherit; color: inherit;
  text-transform: inherit; letter-spacing: inherit; cursor: pointer;
}
.cmp-history .th-sort:hover { color: var(--text); background: none; }
.cmp-history .th-sort::after { content: " ↕"; color: var(--text-faint); }
.cmp-history th[aria-sort="ascending"] .th-sort::after { content: " ↑"; color: var(--accent); }
.cmp-history th[aria-sort="descending"] .th-sort::after { content: " ↓"; color: var(--accent); }
.cmp-history td { vertical-align: middle; }
.cmp-history-dims { white-space: nowrap; }
#cmp-history-model { width: auto; max-width: 220px; }
.cmp-history tr.is-current td { background: var(--accent-soft); }
.cmp-history-when { white-space: nowrap; font-variant-numeric: tabular-nums; }
.cmp-history-thumb {
  padding: 0; border: 1px solid var(--line); border-radius: 6px;
  background: var(--bg-subtle); overflow: hidden; line-height: 0;
  width: 112px; height: 70px; cursor: zoom-in;
}
.cmp-history-thumb img { width: 100%; height: 100%; object-fit: cover; }
.cmp-history-thumb:hover { border-color: var(--accent); }
/* Кнопки строки — столбиком: с «Составом» таблица иначе шире экрана
   ноутбука, и «Скачать» уезжал за край. */
.cmp-history-actions { text-align: right; }
.cmp-history-actions > * { display: flex; width: 100%; justify-content: center; }
.cmp-history-actions > * + * { margin-top: 6px; }
.cmp-preview-box { gap: 12px; }
.cmp-preview-box .overlay-head h2 { flex: 1; min-width: 0; margin: 0; font-size: 16px; }
.cmp-preview-box img {
  display: block; max-width: 100%; max-height: 72vh; margin: 0 auto;
  object-fit: contain; border-radius: 6px;
}
/* На телефоне строка таблицы — карточка: шесть столбцов в 390px не влезают. */
@media (max-width: 640px) {
  .cmp-history thead { display: none; }
  .cmp-history, .cmp-history tbody { display: block; }
  .cmp-history tr {
    display: grid; grid-template-columns: 112px 1fr; gap: 4px 12px;
    padding: 12px 0; border-bottom: 1px solid var(--line);
  }
  .cmp-history tbody tr:last-child { border-bottom: none; }
  .table.cmp-history td { display: block; padding: 2px 0; border: none; }
  .cmp-history td[data-label="Превью"] { grid-row: 1 / span 5; grid-column: 1; }
  .cmp-history td:not([data-label="Превью"]) { grid-column: 2; }
  .cmp-history td[data-label="Тип"], .cmp-history td[data-label="Для кого"],
  .cmp-history td[data-label="Дата"] { font-size: 13px; }
  .cmp-history td[colspan] { grid-column: 1 / -1; }
  .cmp-history-actions { grid-column: 1 / -1 !important; text-align: left; white-space: normal; }
  .cmp-history-actions > * { margin-top: 4px; }
}

/* ── Настройки: пять разделов, поиск, одна кнопка «Сохранить» ─────────────
   UI_REDESIGN_SPEC §7. Слева — разделы и поиск (прилипают), справа —
   карточки подразделов; внизу прилипшая полоса сохранения. */
.set-screen {
  display: grid; grid-template-columns: 232px minmax(0, 1fr);
  gap: 24px; align-items: start; max-width: 1180px;
}
.set-nav {
  position: sticky; top: calc(var(--head-h) + 16px);
  display: flex; flex-direction: column; gap: 12px;
}
.set-nav input[type=search] { width: 100%; }
.set-nav-list { display: flex; flex-direction: column; gap: 2px; }
.set-nav-item {
  display: flex; align-items: center; gap: 8px; min-height: 36px;
  padding: 0 12px; border-radius: var(--radius); border-left: 2px solid transparent;
  color: var(--text-dim); text-decoration: none; font-size: 14px;
}
.set-nav-item:hover { background: var(--bg-hover); color: var(--text); }
.set-nav-item.is-active {
  background: var(--accent-soft); color: var(--text); border-left-color: var(--accent);
  font-weight: 500;
}
.set-nav-item.is-empty { opacity: .45; }
.set-nav-title { flex: 1 1 auto; min-width: 0; }
.set-nav-n {
  font-family: var(--mono); font-size: 12px; color: var(--text-faint);
  font-variant-numeric: tabular-nums;
}
/* Несохранённые правки в разделе — точка акцентом справа от названия. */
.set-nav-item.has-changes .set-nav-title::after {
  content: ""; display: inline-block; width: 6px; height: 6px; margin-left: 8px;
  border-radius: 50%; background: var(--accent); vertical-align: middle;
}
.set-section-head { margin-bottom: 16px; }
.set-section-head h2 { font-size: 20px; font-weight: 600; margin: 0 0 4px; }
.set-section-head .card-note { margin: 0; max-width: 680px; }
.set-main.is-searching .set-section-head .card-note { display: none; }
.set-card .card-head { margin-bottom: 8px; align-items: center; }
.set-card h3 { font-size: 15px; font-weight: 600; margin: 0; display: flex; align-items: center; gap: 8px; }
.set-card h4 { font-size: 14px; font-weight: 600; margin: 0; display: flex; align-items: center; gap: 8px; }
.set-card .field { max-width: 560px; }
.set-card textarea { max-width: none; }
.set-card .field:has(textarea), .set-card .field:has(.price-rules) { max-width: none; }
.set-card .is-filtered, .set-card.is-filtered { display: none; }
/* Изменено, но не сохранено — полоска акцентом слева; не сохранилось — ошибкой. */
.set-card .is-changed { box-shadow: inset 2px 0 0 var(--accent); padding-left: 8px; }
.set-card .field.is-error { box-shadow: inset 2px 0 0 var(--err); padding-left: 8px; }
.set-card[data-dirty-area].is-changed { box-shadow: inset 2px 0 0 var(--accent); padding-left: 16px; }
.set-lastcheck { font-size: 12px; color: var(--text-faint); margin: 0 0 0 auto; }
.set-lastcheck.is-err { color: var(--err); }
.set-provider .set-lastcheck { margin: 0 0 12px; }
.set-steps { margin: 0 0 16px; font-size: 13px; color: var(--text-dim); }
.set-steps summary { cursor: pointer; color: var(--accent); margin-bottom: 8px; }
.set-steps .steps { margin-bottom: 0; }
.set-int .test-result:empty { display: none; }
.set-int .test-result { margin: 0 0 16px; }

.with-unit { display: inline-flex; align-items: center; gap: 8px; }
.with-unit input { width: 120px; }
.with-unit .unit, .set-flags .unit { margin: 0; color: var(--text-faint); font-size: 13px; }
.w-num { width: 88px; }
.w-180 { max-width: 180px; }
.w-220 { max-width: 220px; }
.mono { font-family: var(--mono); font-size: 13px; }
input[type=color].swatch {
  width: 44px; height: 32px; padding: 2px; border: 1px solid var(--line);
  border-radius: var(--radius); background: var(--bg-raised); cursor: pointer;
}

/* Ключи поставщиков — карточками в сетке, как подключения. */
.set-providers {
  display: grid; gap: 16px; margin-bottom: 16px;
  grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr));
}
.set-provider {
  border: 1px solid var(--line); border-radius: var(--radius);
  padding: 12px 16px; background: var(--bg-raised); min-width: 0;
}
.set-provider .field { margin-bottom: 12px; }
.set-provider input { width: 100%; min-width: 0; }
.set-tasks td .badge { margin-top: 4px; white-space: normal; }
.set-route { padding: 12px 0; border-top: 1px solid var(--line); }
.set-route:first-of-type { border-top: none; padding-top: 0; }
.set-route-head { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
.set-route .help { margin: 4px 0 0; color: var(--text-faint); font-size: 13px; }
.set-route .actions-row { margin: 8px 0; flex-wrap: nowrap; }
.set-route .route-row select { width: 200px; flex: none; }
.set-route .route-row input { flex: 1 1 auto; max-width: 320px; }
@media (max-width: 640px) {
  .set-route .actions-row { flex-wrap: wrap; }
  .set-route .route-row select, .set-route .route-row input { width: 100%; max-width: none; }
}
.table-wrap { overflow-x: auto; }

/* «Касания и цвета»: таблица порогов слева, живой пример справа. */
.set-flags {
  display: grid; grid-template-columns: minmax(0, 1fr) 260px; gap: 24px;
  align-items: start; margin-bottom: 16px;
}
.set-flags .set-row-label { font-weight: 500; color: var(--text); min-width: 120px; }
.set-flags .table td { padding: 8px; }
.set-flags .with-unit input { width: 72px; }
.set-card p.help { font-size: 13px; color: var(--text-faint); margin: 8px 0 0; }
.set-flags .table td { vertical-align: middle; }
.set-flags .set-shared { border-left: 1px dashed var(--line); }
.set-flags .table tbody tr:hover { background: none; }
.set-preview {
  display: flex; flex-direction: column; gap: 8px;
  padding: 12px; border: 1px dashed var(--line-strong); border-radius: var(--radius);
  background: var(--bg);
}
.set-preview-cap { font-size: 12px; color: var(--text-faint); }
.set-preview .board-card { cursor: default; }
.set-preview .help { margin: 0; font-size: 12px; color: var(--text-faint); }
.set-grid {
  display: grid; gap: 0 24px; grid-template-columns: repeat(auto-fill, minmax(min(260px, 100%), 1fr));
}

/* Полоса сохранения — одна на экран, прилипает к низу окна. */
.set-savebar {
  position: sticky; bottom: 0; z-index: 5;
  display: flex; align-items: center; justify-content: flex-end; gap: 16px;
  margin-top: 16px; padding: 12px 16px;
  background: var(--bg-panel); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow);
}
.set-dirty-note { font-size: 13px; color: var(--text-faint); }
.set-dirty-note.is-dirty { color: var(--text); }
.set-savebar button { min-width: 140px; }

@media (max-width: 900px) {
  .set-screen { grid-template-columns: minmax(0, 1fr); gap: 16px; }
  .set-nav { position: static; }
  .set-nav-list {
    flex-direction: row; overflow-x: auto; gap: 4px; scrollbar-width: none;
  }
  .set-nav-item { flex: none; border-left: none; border-bottom: 2px solid transparent; border-radius: 0; }
  .set-nav-item.is-active { border-bottom-color: var(--accent); }
  .set-flags { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 640px) {
  .set-nav-item { min-height: 44px; }
  .set-savebar { margin: 16px -16px 0; border-radius: 0; border-left: none; border-right: none; }
  .set-savebar button { flex: 1 1 auto; }
  .set-lastcheck { margin-left: 0; width: 100%; }
  .with-unit input { width: 100px; }
}

/* ── Узкий экран ──────────────────────────────────────────────────────────
   ≤ 900px: сайдбар уезжает за край и выезжает по кнопке «≡» в шапке
   (`toggleSidebar()`), вкладки — горизонтальной прокруткой. ≤ 640px: карточка
   клиента одной колонкой, лента под полями; колонки канбана идут одна за
   другой с прокруткой ВНУТРИ доски, а не всей страницы; всё, по чему
   нажимают пальцем, — не меньше 44px. */
@media (max-width: 900px) {
  .sidebar {
    position: fixed; left: 0; top: 0; z-index: 40;
    transform: translateX(-100%); transition: transform .18s ease;
    box-shadow: var(--shadow);
  }
  body.nav-open .sidebar { transform: none; }
  body.nav-open::after {
    content: ""; position: fixed; inset: 0; z-index: 30; background: var(--scrim);
  }
  .menu-toggle { display: inline-grid; }
  .head-row { padding: 0 8px; }
  .topbar { padding: 8px 16px; flex-wrap: wrap; gap: 8px; }
  .topbar h1 { font-size: 17px; }
  .content { padding: 16px 16px 48px; }
}
@media (max-width: 640px) {
  .client-grid { grid-template-columns: 1fr; }
  .col-fields { max-height: none; overflow: visible; padding-right: 0; }
  .col-feed, .feed-card { position: static; max-height: none; }
  .feed { max-height: 70vh; }
  .board { overscroll-behavior-x: contain; scroll-snap-type: x proximity; }
  .board-col { scroll-snap-align: start; min-width: 84vw; max-width: 84vw; }
  .card { padding: 12px; }
  .table th, .table td { padding: 8px; }
  button, .btn, select,
  input:where(:not([type=checkbox], [type=radio], [type=range], [type=file], [type=hidden])) {
    min-height: 44px;
  }
  .icon-toggle { width: 44px; height: 44px; }
  .nav-item, .tabbar-item { min-height: 44px; display: flex; align-items: center; }
  .field-row { grid-template-columns: 1fr; }
  .field-stamp { grid-column: 1; }
  /* Кнопки действий карточки — одной строкой с прокруткой вбок: столбиком
     они занимали полэкрана прилипшей шапки. */
  .topbar-actions {
    flex-wrap: nowrap; overflow-x: auto; justify-content: flex-start;
    max-width: 100%; scrollbar-width: none;
  }
  .topbar-actions > * { flex: none; }
  /* Перенос с доски — строкой внутри карточки; 44px на «+1д» раздували её
     втрое. Цель всё равно шире пальца по горизонтали. */
  .card-flag .postpone { min-height: 32px; min-width: 40px; padding: 0 8px; }
  .flag-chip { height: 44px; }
}

/* ── Экран: одно предложение «зачем» под заголовком (§8) ──────────────────── */
.page-lead {
  margin: -8px 0 24px; max-width: 72ch;
  color: var(--text-dim); font-size: 14px;
}
.actions-row.flush { margin: 0; }
.metric-sub { color: var(--text-faint); font-size: 12px; margin-top: 4px; }
a.metric { color: inherit; text-decoration: none; }
a.metric:hover { border-color: var(--line-strong); background: var(--bg-hover); }

/* Якоря «исправить» со статистики — под прилипшей шапкой, а не под ней. */
.set-int, .set-provider { scroll-margin-top: calc(var(--head-h, 120px) + 16px); }

/* ── Статистика (UI_REDESIGN_SPEC §6) ──────────────────────────────────────── */
.dash-block { margin-bottom: 24px; }
.dash-title {
  font-size: 13px; font-weight: 500; letter-spacing: .02em;
  color: var(--text-dim); margin: 0 0 12px;
}
.dash-foot { margin: 12px 0 0; font-size: 12px; color: var(--text-faint); }

/* Четыре карточки «сегодня»: цвет — тот же, что у карточки на доске. */
.today-grid {
  display: grid; gap: 16px;
  grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr));
}
.today-card {
  --tone: var(--line-strong);
  display: flex; flex-direction: column; gap: 4px;
  padding: 16px; min-height: 148px;
  background: var(--bg-panel); color: var(--text); text-decoration: none;
  border: 1px solid var(--line); border-top: 3px solid var(--tone);
  border-radius: var(--radius);
  transition: border-color .12s ease, background .12s ease;
}
.today-card[data-state="overdue"] { --tone: var(--flag-overdue); }
.today-card[data-state="draft"] { --tone: var(--flag-draft); }
.today-card[data-state="silent"] { --tone: var(--flag-silent); }
.today-card:hover { background: var(--bg-hover); border-color: var(--line-strong); border-top-color: var(--tone); }
.today-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.today-n {
  font-family: var(--mono); font-size: 40px; line-height: 1.1; font-weight: 500;
  font-variant-numeric: tabular-nums; color: var(--tone);
}
.today-n.is-zero { color: var(--text-faint); }
.today-title { font-size: 15px; font-weight: 600; }
.today-hint { font-size: 13px; color: var(--text-dim); }
.today-oldest {
  margin-top: auto; padding-top: 8px; font-size: 12px; color: var(--text-faint);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.dash-alerts { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.dash-alerts .badge { text-decoration: none; }

/* Поток за период */
.flow-grid {
  display: grid; gap: 12px;
  grid-template-columns: repeat(auto-fit, minmax(min(160px, 100%), 1fr));
}
.bars {
  display: flex; align-items: flex-end; gap: 4px; height: 120px;
  margin-top: 24px; padding-top: 16px;
}
.bar-col {
  flex: 1 1 0; min-width: 0; height: 100%;
  display: grid; grid-template-rows: auto minmax(0, 1fr) auto;
}
.bar-track { display: flex; align-items: flex-end; min-height: 0; border-bottom: 1px solid var(--line); }
.bar-track .bar { width: 100%; }
.bar { background: var(--accent); border-radius: 2px 2px 0 0; min-height: 1px; opacity: .85; }
.bar-col:hover .bar { opacity: 1; }
.bar-col.is-out .bar { background: var(--line-strong); }
.bar-n, .bar-label {
  font-family: var(--mono); font-size: 11px; color: var(--text-faint);
  text-align: center; white-space: nowrap; overflow: hidden;
}
.bar-n { margin-bottom: 2px; min-height: 14px; }
.bar-label { margin-top: 4px; }
/* Тридцать подписей не помещаются — оставляем каждую пятую. */
.bars:has(.bar-col:nth-child(15)) .bar-col:not(:nth-child(5n)):not(:last-child) .bar-label { visibility: hidden; }
.bars:has(.bar-col:nth-child(15)) .bar-n { visibility: hidden; }

/* Воронка */
.dash-redline {
  display: flex; align-items: center; gap: 8px; margin: 0 0 12px;
  padding: 8px 12px; border-radius: var(--radius);
  background: var(--err-bg); color: var(--err); text-decoration: none; font-size: 14px;
}
.dash-redline b { font-family: var(--mono); }
.funnel-table td:first-child { min-width: 200px; }
.funnel-table td.is-alert { color: var(--err); font-weight: 500; }
.funnel-table tfoot td { border-top: 1px solid var(--line-strong); font-weight: 500; padding: 8px 12px; }
.stage-swatch {
  display: inline-block; width: 8px; height: 8px; border-radius: 2px;
  margin-right: 8px; vertical-align: 1px;
}
.stage-bar { display: block; height: 3px; margin-top: 4px; background: var(--bg-subtle); border-radius: 2px; }
.stage-bar i { display: block; height: 100%; background: var(--accent-dim); border-radius: 2px; }

/* Здоровье: три карточки в ряд, на узком — столбиком. */
.health-grid {
  display: grid; gap: 16px; align-items: start;
  grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
}
.health-grid .card { margin-bottom: 0; }
.health-grid + .card { margin-top: 16px; }
.health-list { list-style: none; margin: 0; padding: 0; }
.health-list li {
  display: grid; grid-template-columns: 8px minmax(0, 1fr) auto; align-items: center;
  column-gap: 8px; padding: 8px 0; border-bottom: 1px solid var(--line); font-size: 14px;
}
.health-list li:last-child { border-bottom: none; }
.health-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.health-signal { grid-column: 2; font-size: 12px; color: var(--text-faint); }
.health-fix { grid-column: 3; grid-row: 1 / span 2; font-size: 13px; }
.health-money { display: flex; gap: 24px; flex-wrap: wrap; margin-bottom: 12px; }
.health-money .metric-value { font-size: 22px; }

@media (max-width: 640px) {
  .page-lead { margin: -4px 0 16px; font-size: 13px; }
  .today-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
  .today-card { min-height: 0; padding: 12px; }
  .today-n { font-size: 32px; }
  .today-hint { display: none; }
  .bars { height: 96px; }
  .funnel-table td:first-child { min-width: 0; }
  .funnel-table { font-size: 13px; }
  .funnel-table th, .funnel-table td { padding: 8px 4px; }
  .flow-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
  .flow-grid .metric { padding: 12px; }
  .flow-grid .metric-value { font-size: 22px; }
}

/* ── Общие детали экранов §8 ─────────────────────────────────────────────── */
/* Подзаголовок внутри карточки (группа, направление). */
.card-head.sub-head { margin: 16px 0 8px; }
.card-head.sub-head h3 { font-size: 14px; font-weight: 600; }
/* Карточка-таблица: таблица встык к краям, отступ — только у шапки. */
.card.flush { padding: 0; overflow: hidden; }
.card.flush > .card-head { padding: 16px 16px 0; }
.card.flush > .card-note { padding: 0 16px; }
.card.flush > .planned, .card.flush > .empty-state { padding: 32px 16px; }
/* Опасная зона — отдельно, внизу экрана, с красной рамкой. */
.danger-zone { border-color: var(--err); border-style: dashed; background: var(--bg-panel); }
.danger-zone .card-head h2 { color: var(--err); }
.danger-row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 8px 0; border-top: 1px solid var(--line);
}
.danger-row:first-of-type { border-top: none; }
.danger-row .cell-sub { margin-left: 8px; }
/* Пустое состояние внутри карточки — без лишней высоты. */
.card .empty-state { padding: 32px 16px; }
.test-result > .cell-sub { margin-top: 8px; }
/* Полоса фильтров экрана: поля слева, ссылка-справочник справа. */
.toolbar { padding: 8px; background: var(--bg-panel); border: 1px solid var(--line); border-radius: var(--radius); }
.toolbar-end { margin-left: auto; }
.head-badges { display: inline-flex; flex-wrap: wrap; gap: 4px; margin-left: auto; }
.card-head h2 + .head-badges { align-self: center; }
.card.is-muted > .card-head h2 { color: var(--text-dim); }
.grow { flex: 1; min-width: 0; }
.correction-note { margin: 12px 0 0; }
.insight .suggestion + .cell-sub, .insight > .cell-sub { margin-top: 8px; }
/* Ряд полей с подписями над ними; кнопка — по нижнему краю полей. */
.form-row { display: flex; flex-wrap: wrap; gap: 0 16px; align-items: flex-end; }
.form-row .field { margin-bottom: 12px; }
.form-row .with-unit input { width: 96px; }
.form-row-end { margin-left: auto; }
label.btn { cursor: pointer; }
.list-count { margin: 0 0 8px; font-size: 13px; color: var(--text-faint); }
/* Очередь: группа — карточка с таблицей, цвет состояния точкой в заголовке. */
.flag-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 8px; vertical-align: 1px; background: currentColor; }
.queue-group { border-left: 3px solid var(--line-strong); }
.queue-group[data-flag="overdue"] { border-left-color: var(--flag-overdue); }
.queue-group[data-flag="draft"] { border-left-color: var(--flag-draft); }
.queue-group[data-flag="silent"] { border-left-color: var(--flag-silent); }
.queue-group[data-flag="stale"] { border-left-color: var(--flag-stale); }
.queue-group .card-head { margin-bottom: 8px; }
.queue-group .row-actions { flex-wrap: nowrap; }
/* Ширины полей — классами, а не инлайн-стилем (§8). */
.w-70 { width: 70px; }
.w-120 { width: 120px; }
.w-150 { width: 150px; }
.w-160 { max-width: 160px; }
.w-170 { max-width: 170px; }
.w-200 { max-width: 200px; }
.w-320 { max-width: 320px; }
.text-err { color: var(--err); }
.text-warn { color: var(--warn); }
.chip-row { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.inline-form { display: flex; gap: 8px; align-items: center; }
.grid-gap-bottom { margin-bottom: 16px; }
.msg.msg-wide { max-width: 100%; margin-bottom: 8px; }
/* Правка: подпись и текст — без пустых строк от отступов шаблона. */
.version-box { white-space: normal; }
.version-text { white-space: pre-wrap; overflow-wrap: anywhere; }
/* Фильтр чертежей: поиск шире, число модулей — узкое поле. */
.drawing-filters .filters input[type=search] { flex: 2 1 260px; max-width: none; }
.drawing-filters .filters input[name=model] { flex: 1 1 140px; max-width: 220px; }
.drawing-filters .filters input[name=modules] { flex: 0 0 110px; width: 110px; }

/* ── Форма расчёта: открытый расчёт, булавки, пресеты ткани ────────────────
   «Открыть в расчёте» у КП. Баннер — чей расчёт и по какому прайсу был;
   пометка у строк, которых нет в списке модели; булавка «по умолчанию» у
   поля; комбобокс пресетов ткани на два поля. Всё на токенах темы. */
.calc-opened {
  border: 1px solid var(--accent-dim); background: var(--accent-soft);
  border-radius: var(--radius); padding: 10px 14px; margin-bottom: 16px;
  font-size: 13px; color: var(--text-dim);
}
.calc-opened.is-warn { border-color: var(--warn); }
.calc-opened-head { color: var(--text); font-size: 14px; }
.calc-opened-head b { font-weight: 600; }
.calc-opened-sep { color: var(--text-faint); margin: 0 4px 0 0; }
.calc-opened-note { color: var(--warn); margin-top: 4px; }
.calc-opened-note::before { content: '! '; font-weight: 600; }
.calc-opened-foot { margin-top: 4px; }

.field-head { display: flex; align-items: center; gap: 4px; margin-bottom: 4px; }
.field-head label { margin-bottom: 0; }
.pin-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; padding: 0; min-height: 0;
  border: 1px solid transparent; border-radius: 4px; background: none;
  color: var(--text-faint); cursor: pointer; opacity: .7;
}
.pin-btn:hover { opacity: 1; color: var(--text); background: var(--bg-hover); border-color: transparent; }
.pin-btn.is-on { opacity: 1; color: var(--accent); background: var(--accent-soft); border-color: var(--accent-dim); }
.pin-btn svg { display: block; }

.combo { position: relative; }
.combo > input { padding-right: 34px; }
.combo-toggle {
  position: absolute; top: 1px; right: 1px; bottom: 1px; width: 30px;
  padding: 0; min-height: 0; border: 0; border-left: 1px solid var(--line);
  border-radius: 0 var(--radius) var(--radius) 0; background: none;
  color: var(--text-dim); font-size: 12px; cursor: pointer;
}
.combo-toggle:hover { color: var(--text); background: var(--bg-hover); border-color: var(--line); }
.combo > input[aria-expanded="true"] + .combo-toggle { color: var(--accent); }
/* Родные стрелки числового поля мешали бы ▾ — у цены ткани их прячем. */
.combo > input[type=number]::-webkit-inner-spin-button,
.combo > input[type=number]::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
.combo > input[type=number] { -moz-appearance: textfield; }
.combo-list {
  position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 40;
  min-width: 240px; max-height: 280px; overflow-y: auto;
  margin: 0; padding: 4px; list-style: none;
  background: var(--bg-raised); border: 1px solid var(--line-strong);
  border-radius: var(--radius); box-shadow: var(--shadow);
}
.combo-option {
  display: flex; align-items: center; gap: 6px;
  padding: 6px 8px; border-radius: 4px; cursor: pointer; font-size: 14px;
}
.combo-option:hover { background: var(--bg-hover); }
.combo-option.is-active { background: var(--bg-hover); box-shadow: inset 2px 0 0 var(--accent); }
.combo-name { color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.combo-price { color: var(--text-dim); font-variant-numeric: tabular-nums; white-space: nowrap; }
.combo-del { margin-left: auto; font-size: 15px; line-height: 1; }
.combo-add { color: var(--accent); border-top: 1px solid var(--line); margin-top: 4px; border-radius: 0 0 4px 4px; }
.combo-empty { color: var(--text-faint); font-size: 13px; padding: 6px 8px; }

/* Строка из снимка, которой нет в списке модели: посчитана, в прайс не
   записана. Подложка тихая, подпись — под названием. */
/* Состояние списка блоков: тихая строка, пока всё сохранено; подсвечена,
   пока в форме есть то, чего нет в прайсе. */
.calc-blocks-state {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin-top: 16px; padding: 8px 12px; font-size: 13px; color: var(--text-dim);
  background: var(--bg-subtle); border: 1px dashed var(--line-strong);
  border-radius: var(--radius);
}
.calc-blocks-state.is-dirty {
  color: var(--text); background: var(--accent-soft);
  border: 1px solid var(--accent);
}
.calc-blocks-state span { flex: 1 1 280px; }
tr.from-snapshot > td { background: var(--accent-soft); }
.block-origin { margin-top: 4px; }

/* ── Триггеры квалификации (навыки → «Квалификация лида») ─────────────────
   Таблица на широком экране; на узком строка становится карточкой с
   подписями полей (data-label), иначе семь колонок не читаются. */
.triggers { margin-top: 24px; padding-top: 16px; border-top: 1px solid var(--line); }
.triggers-head h3 { font-size: 14px; font-weight: 600; margin: 0 0 4px; }
.triggers-head .help { color: var(--text-faint); font-size: 13px; margin: 0 0 12px; max-width: 72ch; }
.triggers-table tbody tr:hover { background: none; }
.triggers-table td { vertical-align: top; }
.triggers-table .trigger-on { width: 40px; padding-top: 10px; }
.triggers-table .trigger-title { min-width: 180px; }
.triggers-table .trigger-hint { margin-top: 4px; color: var(--text-dim); }
.triggers-table .trigger-what { min-width: 260px; width: 34%; }
.triggers-table textarea { font-size: 13px; padding: 4px 8px; resize: vertical; }
.triggers-table select { min-width: 96px; font-size: 13px; }
.triggers-table .trigger-del { width: 40px; text-align: right; }
.triggers-table .trigger-del button { padding: 4px 8px; }
.triggers-table .trigger-del button:hover { color: var(--err); }
.trigger-min { display: flex; align-items: center; gap: 8px; color: var(--text-dim); font-size: 13px; }
.trigger-min input { max-width: 140px; }
.triggers-table tr[data-kind=words] .for-budget,
.triggers-table tr[data-kind=budget] .for-words { display: none; }
.triggers-howto { margin: 8px 0 0; font-size: 13px; color: var(--text-dim); }
.triggers-howto summary { cursor: pointer; color: var(--accent); }
.triggers-howto ul { margin: 8px 0 0; padding-left: 20px; max-width: 80ch; }
.triggers-howto li { margin: 4px 0; }
.triggers-howto code { font-family: var(--mono); font-size: 12px; background: var(--bg-subtle);
  padding: 0 4px; border-radius: 4px; color: var(--text); }
.trigger-check { margin-top: 16px; padding: 12px; border: 1px solid var(--line);
  border-radius: var(--radius); background: var(--bg-subtle); }
.trigger-check > label { display: block; font-size: 13px; font-weight: 500; color: var(--text-dim); margin-bottom: 4px; }
.trigger-check-row { display: flex; gap: 8px; }
.trigger-check-row button { flex: none; }
.trigger-check .help { color: var(--text-faint); font-size: 13px; margin: 4px 0 0; }
.trigger-result:empty { display: none; }
.trigger-result { margin-top: 12px; }
.trigger-verdict { margin: 0 0 8px; font-size: 14px; }
.trigger-hits { list-style: none; margin: 0; padding: 0; }
.trigger-hits li { padding: 8px 0; border-top: 1px solid var(--line); }
.trigger-hits li .badge { margin-left: 8px; }
@media (max-width: 720px) {
  .triggers-table thead { display: none; }
  .triggers-table, .triggers-table tbody, .triggers-table tr, .triggers-table td { display: block; width: 100%; }
  .triggers-table tr { position: relative; padding: 12px 0; border-bottom: 1px solid var(--line); }
  .triggers-table td { border: none; padding: 4px 0; }
  .triggers-table td[data-label]::before { content: attr(data-label); display: block;
    font-size: 12px; color: var(--text-faint); margin-bottom: 2px; }
  .triggers-table .trigger-on { display: flex; align-items: center; gap: 8px; width: auto; padding-top: 4px; }
  .triggers-table .trigger-on::before { margin: 0; }
  .triggers-table .trigger-what { width: 100%; min-width: 0; }
  .triggers-table .trigger-del { position: absolute; top: 8px; right: 0; width: auto; padding: 0; }
  .trigger-check-row { flex-direction: column; }
}

/* ── Выбор клиента (КП, конструктор) ──────────────────────────────────────
   Поле с подсказками + ⌗ «на доске»; выбранный клиент — плашкой. Подсказки —
   тот же `.combo-list`, что у пресетов ткани; окно доски — тот же `.overlay`,
   что у выбора касаний. */
.cpick { width: 100%; max-width: 460px; }
.cpick-field { display: flex; gap: 8px; align-items: stretch; }
.cpick-combo { flex: 1 1 auto; min-width: 0; }
.cpick-combo > input { width: 100%; padding-right: 8px; }
.cpick-board {
  flex: none; width: 36px; padding: 0; font-size: 16px; line-height: 1;
  color: var(--text-dim);
}
.cpick-board:hover { color: var(--accent); border-color: var(--accent); }
.cpick-list { max-height: 340px; }
.cpick-option { flex-direction: column; align-items: stretch; gap: 2px; padding: 8px 8px; }
.cpick-line { display: flex; align-items: center; gap: 8px; min-width: 0; }
.cpick-line b { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cpick-sub, .cpick-chip-sub {
  display: block; color: var(--text-faint); font-size: 12px; line-height: 1.4;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cpick-option mark { background: var(--warn-bg); color: var(--warn); border-radius: 3px; }
.cpick-chip {
  position: relative; display: flex; flex-direction: column; gap: 2px;
  padding: 6px 40px 6px 12px; min-height: 36px; justify-content: center;
  background: var(--accent-soft); border: 1px solid var(--accent-dim);
  border-radius: var(--radius);
}
.cpick-chip[hidden], .cpick-field[hidden] { display: none; }
.cpick-chip-main { display: flex; align-items: center; gap: 8px; min-width: 0; }
.cpick-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
.cpick-clear { position: absolute; top: 50%; right: 4px; transform: translateY(-50%); }
.cmp-client-field { flex: 1 1 320px; }

/* Мини-доска в окне: колонки те же, но без переноса, галочек и кнопок
   «отложить» — здесь карточка только выбирается. */
/* min-width: 0 — иначе ширина колонок доски распирала бы окно шире экрана
   (у флекс-ребёнка минимальная ширина — по содержимому). */
.cpick-board-box { max-height: 88vh; min-width: 0; }
.cpick-board-box > * { min-width: 0; }
.cpick-board-tools { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 8px; }
.cpick-board-tools input[type=search] { width: 100%; padding-left: 29px; }
.cpick-board-tools select { width: auto; }
.cpick-board-live { overflow: auto; min-height: 200px; margin-top: 8px; }
.cpick-board-live.is-searching { opacity: .6; }
.cpick-board-live .board-col { min-width: 220px; max-width: 220px; }
.cpick-board-live .board-card { cursor: pointer; }
.cpick-board-live .board-card:hover { border-color: var(--accent); }
.cpick-board-live .col-tools, .cpick-board-live .pick,
.cpick-board-live .postpone { display: none; }

@media (max-width: 640px) {
  .cpick { max-width: none; }
  .overlay:has(.cpick-board-box) { padding: 8px; }
  .cpick-board-box { max-height: 96vh; padding: 12px; }
  .cpick-board-tools .search-box { flex-basis: 100%; max-width: none; }
  .cpick-board-live .board-col { min-width: 200px; max-width: 200px; }
}

/* ── Цвет комплекта и «Элементы» ── */
.cmp-colors button { border: 0; border-right: 1px solid var(--line); border-radius: 0; background: transparent; }
.cmp-colors button:last-of-type { border-right: 0; }
.cmp-colors button.is-on { background: var(--accent-dim); color: var(--text); }
.cmp-colors button:disabled { opacity: .45; cursor: not-allowed; }
.cmp-colors .cell-sub { align-self: center; padding: 0 8px; }
.cmp-pal-more { display: inline-block; margin-top: 10px; font-size: 12px; }
.w-90 { width: 90px; }
.el-table input[type=text] { width: 100%; min-width: 120px; }
.el-table .el-num { width: 64px; padding-left: 6px; padding-right: 2px; }
.el-table select { min-width: 132px; }
.el-table th, .el-table td { padding-left: 6px; padding-right: 6px; }
.el-pics { display: flex; gap: 10px; }
.el-nopic { display: flex; align-items: center; justify-content: center; width: 64px; height: 44px;
  font-size: 11px; color: var(--text-faint); border: 1px dashed var(--line); border-radius: var(--radius); text-align: center; }
.el-table td { vertical-align: top; }
.el-size { white-space: nowrap; }
.el-pic { display: flex; flex-direction: column; gap: 4px; align-items: flex-start; }
.el-pic img { width: 64px; height: 44px; object-fit: contain; background: var(--bg-subtle);
  border: 1px solid var(--line); border-radius: var(--radius); }
.btn-sm { font-size: 12px; padding: 2px 8px; min-height: 0; }
label.btn { display: inline-flex; align-items: center; cursor: pointer; }

/* Состав комплекта — один вид везде (_set_contents.html, setContentsHtml). */
.set-contents { margin: 0; padding: 0; list-style: none; font-size: 12px; line-height: 1.5; }
.set-contents li { white-space: nowrap; }

/* ── Комплекты в карточке: расчёт + КП + схема одной строкой ── */
.set-rows { display: flex; flex-direction: column; }
.set-row { display: grid; grid-template-columns: 20px 112px 1fr auto; gap: 14px;
  padding: 12px 0; border-top: 1px solid var(--line); align-items: start; }
/* Отметка «удалить несколько разом» — своя колонка слева: строка остаётся
   читаемой, а отмеченную видно по подсветке. */
.set-row-pick { display: flex; align-items: center; justify-content: center;
  height: 72px; cursor: pointer; }
.set-row-pick input { width: 16px; height: 16px; margin: 0; cursor: pointer; }
.set-row.is-picked { background: var(--accent-soft); }
.set-row:first-child { border-top: none; }
.set-row-thumb img, .set-row-noscheme, .set-row-thumb .media-placeholder {
  width: 112px; height: 72px; object-fit: cover; border-radius: var(--radius);
  border: 1px solid var(--line); background: var(--bg-subtle); display: flex;
  align-items: center; justify-content: center; font-size: 11px; color: var(--text-faint); }
.set-row-main { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.set-row-main .set-contents { font-size: 13px; }
.set-row-price { color: var(--text); }
.set-row-text { margin: 0; font-size: 12px; white-space: pre-wrap; }
.set-row-quote { display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  font-size: 13px; padding: 4px 0 0; border-top: 1px dashed var(--line); }
.set-row-quote > span:first-child { margin-right: auto; }
.set-row-more { position: relative; }
.set-row-more summary { list-style: none; cursor: pointer; }
.set-row-more summary::-webkit-details-marker { display: none; }
.set-row-menu { position: absolute; right: 0; top: 100%; z-index: 5; display: flex;
  flex-direction: column; gap: 4px; padding: 6px; background: var(--bg-raised);
  border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow); }
.set-row-actions { display: flex; flex-direction: column; gap: 6px; align-items: stretch; min-width: 120px; }
@media (max-width: 700px) {
  .set-row { grid-template-columns: 20px 88px 1fr; }
  .set-row-pick { height: 60px; }
  .set-row-thumb img, .set-row-noscheme, .set-row-thumb .media-placeholder { width: 88px; height: 60px; }
  .set-row-actions { grid-column: 1 / -1; flex-direction: row; flex-wrap: wrap; }
}

/* ── Цех и план (пресеты производства) ── */
.shop-fold > summary { display: flex; align-items: baseline; gap: 10px; }
.shop-head { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 10px 0; }
.shop-head select { width: auto; min-width: 220px; }
.shop-dirty { font-size: 12px; color: var(--warn); }
.shop-section-title { font-size: 12px; font-weight: 600; text-transform: uppercase;
  letter-spacing: .04em; color: var(--text-dim); margin-bottom: 8px; }
/* «Задаём» — рамка акцентом: здесь правят. «Получается» — серое: справочно. */
.shop-edit { border: 1px solid var(--accent); border-radius: var(--radius);
  background: var(--accent-soft); padding: 12px; }
.shop-group + .shop-group { margin-top: 10px; }
.shop-edit .shop-field.is-check input { border-color: var(--warn); }
.shop-info { margin-top: 12px; padding: 12px; border: 1px solid var(--line);
  border-radius: var(--radius); background: var(--bg-subtle); }
.shop-sub { font-size: 12px; color: var(--text-dim); margin: 8px 0 6px; }
.shop-stats { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 8px; }
.shop-stat { display: flex; flex-direction: column; gap: 2px; padding: 8px 10px;
  border-radius: var(--radius); background: var(--bg-raised); }
.shop-stat b { font-variant-numeric: tabular-nums; }
.shop-toggle { display: flex; gap: 8px; align-items: flex-start; grid-column: span 2; }
.shop-toggle input { margin-top: 3px; }
.shop-toggle span { display: flex; flex-direction: column; gap: 2px; }
.shop-roles td, .shop-coeffs td, .shop-coeffs th { padding: 4px 6px; vertical-align: top; }
.shop-roles input, .shop-coeffs input { width: 96px; }
.shop-roles { max-width: 520px; }


/* Контекст расчёта в липкой шапке «Расчёт и КП» (quotes.js calcContextUpdate):
   модель, клиент ссылкой, ткань с ценой, цена в КП — пока поля формы за
   краем экрана. Мелко и спокойно: это напоминание, а не второй заголовок. */
.calc-context {
  display: inline-flex; gap: 6px; align-items: center; margin-left: 14px;
  vertical-align: middle; font-size: 13px; font-weight: 400;
}
.calc-context[hidden] { display: none; }
.calc-ctx {
  border: 1px solid var(--line); border-radius: 999px; padding: 2px 10px;
  background: var(--bg); color: inherit; font: inherit; cursor: pointer;
  white-space: nowrap; text-decoration: none; max-width: 22em;
  overflow: hidden; text-overflow: ellipsis;
}
.calc-ctx:hover { border-color: currentColor; }
.calc-ctx.ctx-client { font-weight: 600; }
.calc-ctx.is-empty { color: var(--warn); }
.calc-ctx.ctx-price { cursor: default; font-weight: 600; }


/* ── Оси меток и превью единиц (web/services/units.py, unitCardHtml) ─────────
   Владелец (03.10): «по названию не понять, что это за касание». Карточка
   единицы показывает содержимое, не открывая её: миниатюры, первые строки,
   цепочку шагов со ступенями, метки по значимости и цвету оси. Один вид на
   всех экранах — «Касания», доска карт, «Материалы» клиента. */
.ax-flag    { --ax: var(--ax-flag); }
.ax-model   { --ax: var(--ax-model); }
.ax-trigger { --ax: var(--ax-trigger); }
.ax-config  { --ax: var(--ax-config); }
.ax-style   { --ax: var(--ax-style); }
.ax-fabric  { --ax: var(--ax-fabric); }
.ax-size    { --ax: var(--ax-size); }
.ax-form    { --ax: var(--ax-form); }
.ax-moment  { --ax: var(--ax-moment); }
.ax-topic, .ax-objection, .ax-segment { --ax: var(--ax-topic); }
.ax-signal  { --ax: var(--accent); }
.ax-channel, .ax-free { --ax: var(--ax-other); }
.tag-label[class*="ax-"], .ulabel {
  background: color-mix(in srgb, var(--ax, var(--ax-other)) 16%, transparent);
  border: 1px solid color-mix(in srgb, var(--ax, var(--ax-other)) 45%, transparent);
  color: var(--text);
}
.tag-label.tag-secondary[class*="ax-"], .ulabel.is-secondary {
  background: none; border-style: dashed;
}
.ulabel { display: inline-flex; align-items: center; gap: 4px; padding: 1px 7px;
  border-radius: 999px; font-size: 11.5px; line-height: 18px; white-space: nowrap; }
.ulabel.is-inside { opacity: .7; }
.ulabel.ax-flag { background: var(--err-bg); color: var(--err); font-weight: 600; }
.ulabel .ax-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--ax); }
/* ✎ на метке карточки — переименовать везде; появляется на наведении. На
   досках карт карточка целиком — одна кнопка, там ✎ не показываем. */
.ulabel-ren { display: none; padding: 0 0 0 2px; border: none; background: none;
  font-size: 10.5px; line-height: 1; color: var(--text-faint); cursor: pointer; }
.ulabel:hover .ulabel-ren, .ulabel-ren:focus-visible { display: inline; }
.ulabel-ren:hover { color: var(--accent); }
.ulabel.is-renaming .label-chip-edit { font-size: 11px; }
.board .ulabel:hover .ulabel-ren, .ov-bn-row .ulabel:hover .ulabel-ren { display: none; }

.unit-card { display: flex; gap: 10px; min-width: 0; }
.unit-thumbs { display: grid; grid-template-columns: repeat(2, 44px); grid-auto-rows: 44px;
  gap: 3px; flex: none; }
.unit-thumbs.one { grid-template-columns: 64px; grid-auto-rows: 64px; }
.unit-thumb { width: 100%; height: 100%; object-fit: cover; border-radius: 4px;
  background: var(--bg-subtle); display: flex; align-items: center; justify-content: center;
  font-size: 11px; color: var(--text-dim); overflow: hidden; position: relative; }
.unit-thumb.is-video::after { content: "▶"; position: absolute; font-size: 12px;
  color: var(--on-media); text-shadow: 0 0 4px var(--on-media-shadow); }
.unit-thumb.more { font-weight: 600; }
.unit-body { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 3px; }
.unit-head { display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; }
.unit-kind { font-size: 11px; color: var(--text-faint); text-transform: uppercase;
  letter-spacing: .03em; }
.unit-title { font-weight: 600; color: var(--text); text-decoration: none; }
a.unit-title:hover { color: var(--accent); }
.unit-counts { font-size: 12px; color: var(--text-faint); }
.unit-lines { font-size: 13px; color: var(--text-dim); line-height: 1.35; }
.unit-lines p { margin: 0; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2;
  -webkit-box-orient: vertical; }
.unit-labels { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 2px; }
.unit-chain { display: flex; flex-wrap: wrap; gap: 3px; align-items: center; }
.uchain { font-size: 11px; padding: 0 6px; border-radius: 4px; line-height: 18px;
  background: var(--bg-subtle); color: var(--text-dim); white-space: nowrap; }
.uchain.text { border-left: 3px solid var(--accent); }
.uchain.media { border-left: 3px solid var(--ax-form); }
.uchain.pause { border-left: 3px solid var(--line-strong); }
.mode-badge { display: inline-block; font-size: 10.5px; padding: 0 5px; border-radius: 4px;
  font-weight: 600; line-height: 16px; }
.mode-0 { background: var(--bg-subtle); color: var(--text-dim); }
.mode-1 { background: var(--accent-soft); color: var(--accent); }
.mode-2 { background: var(--warn-bg); color: var(--warn); }
.mode-3 { background: var(--draft-bg); color: var(--draft); }
.unit-flags { display: flex; flex-wrap: wrap; gap: 4px; }
.unit-maps { font-size: 11.5px; color: var(--text-faint); }

/* Всплывающая подробная карточка: по наведению на любую единицу. */
.unit-pop { position: fixed; z-index: 60; width: min(440px, calc(100vw - 24px));
  max-height: min(70vh, 560px); overflow: auto; background: var(--bg-panel);
  border: 1px solid var(--line-strong); border-radius: 10px; box-shadow: var(--shadow);
  padding: 12px 14px; font-size: 13px; }
.unit-pop h4 { margin: 0 0 4px; font-size: 14px; }
.unit-pop .pop-reason { color: var(--text-dim); margin: 0 0 8px; }
.unit-pop .pop-step { display: flex; gap: 6px; align-items: flex-start; padding: 4px 0;
  border-top: 1px solid var(--line); }
.unit-pop .pop-step:first-child { border-top: 0; }
.unit-pop .pop-step-text { flex: 1; color: var(--text); }
.unit-pop .pop-media { display: flex; flex-wrap: wrap; gap: 3px; flex: 1; }
.unit-pop .pop-media .unit-thumb { width: 52px; height: 52px; }
.unit-pop .pop-section { margin-top: 10px; }
.unit-pop .pop-section-title { font-size: 11px; text-transform: uppercase;
  color: var(--text-faint); letter-spacing: .03em; margin-bottom: 4px; }
.unit-pop .pop-axis { display: flex; gap: 6px; align-items: baseline; margin: 2px 0; }
.unit-pop .pop-axis-name { width: 110px; flex: none; font-size: 11.5px; color: var(--text-faint); }
.unit-pop .pop-open { display: inline-block; margin-top: 10px; }
[data-unit] { cursor: help; }
a[data-unit], button[data-unit] { cursor: pointer; }

/* Экран «Касания»: сетка карточек-превью; открытая карточка — во всю ширину. */
.unit-filter { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 0 0 12px; }
/* Строка фильтров касаний едет со списком: сотня карточек — искать, не
   прокручивая обратно наверх. */
#touch-filter, #phrase-filter { position: sticky; top: var(--head-h); z-index: 3; }
#new-touch { margin-bottom: 12px; }
#touch-check { margin-top: 16px; }
.w-260 { max-width: 260px; }
.touch-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(360px, 100%), 1fr));
  gap: 10px; }
.touch-cards > .touch-tile { border: 1px solid var(--line); border-radius: 10px; margin: 0;
  background: var(--bg-panel); padding: 0; }
.touch-cards > .touch-tile[open] { grid-column: 1 / -1; padding-bottom: 12px; }
.touch-cards > .touch-tile > summary { list-style: none; padding: 10px 12px; display: flex;
  flex-direction: column; gap: 6px; cursor: pointer; }
.touch-cards > .touch-tile > summary::-webkit-details-marker { display: none; }
/* Звезда «в быстрые ответы» — в правом верхнем углу плитки (07.10), не
   отдельной строкой; название не заезжает под неё. */
.touch-cards > .touch-tile > summary { position: relative; }
.touch-cards > .touch-tile > summary > .quick-star { position: absolute; top: 6px; right: 6px; z-index: 1; }
.touch-cards > .touch-tile > summary > .quick-star ~ .touch-tile-unit { padding-right: 26px; }
.touch-cards > .touch-tile:hover { border-color: var(--line-strong); }
.touch-cards > .touch-tile[open] > summary { border-bottom: 1px solid var(--line); }
.touch-cards > .touch-tile > :not(summary) { margin-left: 12px; margin-right: 12px; }
.touch-tile-meta { font-size: 12px; color: var(--text-faint); display: flex; gap: 4px;
  flex-wrap: wrap; align-items: center; }
.touch-tile-open { margin-left: auto; color: var(--accent); }
.touch-tile[open] .touch-tile-open { visibility: hidden; }

/* Редактор касания (владелец 05.10): слева что получит клиент, справа когда
   отправлять. На узком экране — одной колонкой, клиентская часть первой. */
.te { display: grid; grid-template-columns: minmax(0, 3fr) minmax(300px, 2fr); gap: 16px;
  align-items: start; margin-top: 12px; }
@media (max-width: 900px) { .te { grid-template-columns: 1fr; } }
.te-h { font-size: 14px; margin: 0 0 4px; }
.te-main .help { margin-top: 0; }
.te-side { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.te-side .te-h { margin-top: 4px; }
.te-side .field { margin: 0; }
.te-row { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.te-stages { border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--bg-panel); }
.te-stages > summary { padding: 6px 10px; cursor: pointer; font-size: 13px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.te-stage-list { max-height: 240px; overflow-y: auto; padding: 4px 10px 8px;
  display: flex; flex-direction: column; gap: 2px; border-top: 1px solid var(--line); }
.te-stage-list .check { font-size: 13px; }
.te-stage-funnel { font-size: 11px; color: var(--text-faint); margin-top: 6px;
  text-transform: uppercase; letter-spacing: .04em; }
.te-fold { border-top: 1px solid var(--line); padding-top: 8px; }
.te-fold > summary { cursor: pointer; color: var(--text-dim); font-size: 13px; }
.te-fold[open] > summary { margin-bottom: 8px; }
.te-map-list { margin: 0; padding-left: 18px; font-size: 13px; line-height: 1.7; }
.te-bar { position: sticky; bottom: 0; z-index: 2; display: flex; flex-wrap: wrap;
  gap: 8px; align-items: center; padding: 10px 0 4px; background: var(--bg-panel);
  border-top: 1px solid var(--line); }
.te-bar .primary.is-dirty::after { content: ' •'; }

/* Фото и видео пункта — плитками, щелчок открывает просмотр. */
.step-thumbs { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
.step-thumb { position: relative; width: 96px; height: 96px; flex: none;
  border-radius: 8px; overflow: hidden; border: 1px solid var(--line);
  background: var(--bg-subtle); }
.step-thumb.is-missing { border-color: var(--err); }
.step-thumb-open { width: 100%; height: 100%; padding: 0; border: none; background: none;
  cursor: zoom-in; display: flex; align-items: center; justify-content: center; }
.step-thumb-open:disabled { cursor: default; }
.step-thumb-open img { width: 100%; height: 100%; object-fit: cover; display: block; }
.step-thumb-kind { position: absolute; left: 6px; bottom: 6px; padding: 0 6px;
  border-radius: 999px; font-size: 11px; line-height: 18px;
  background: var(--scrim); color: var(--text); }
.step-thumb-miss { position: absolute; inset: auto 0 0 0; font-size: 11px;
  text-align: center; background: var(--err-bg); color: var(--err); }
.step-thumb-del { position: absolute; top: 4px; right: 4px; width: 22px; height: 22px;
  padding: 0; border-radius: 50%; border: none; line-height: 22px; font-size: 12px;
  background: var(--scrim); color: var(--text); opacity: 0; }
.step-thumb:hover .step-thumb-del, .step-thumb-del:focus-visible { opacity: 1; }
@media (hover: none) { .step-thumb-del { opacity: 1; } }
.step-thumb-add { width: 96px; height: 96px; flex: none; border-radius: 8px;
  border: 1px dashed var(--line-strong); background: none; font-size: 24px;
  color: var(--text-dim); }
.step-thumb-add:hover { color: var(--accent); border-color: var(--accent); }
/* Перетаскивание медиа и пунктов (05.10): плитку — на другую плитку или «＋»
   в конце; пункт — за ⣿. «＋» между плитками — вставить текст или фразу. */
.step-thumb[draggable="true"] { cursor: grab; }
.step-thumb.is-dragging, .step-row.is-dragging { opacity: .4; }
.step-thumb.is-drop-target { box-shadow: -4px 0 0 var(--accent); }
.step-thumb-add.is-drop-target { border-color: var(--accent); }
/* Загрузка с компьютера (07.10): плитка «⤒» рядом с «＋»; файл, брошенный на
   пункт «медиа» или на редактор, подсвечивает, куда он ляжет. */
.step-thumb-upload { display: inline-flex; flex-direction: column; align-items: center;
  justify-content: center; gap: 2px; cursor: pointer; }
.step-thumb-upload small { font-size: 10.5px; }
.step-thumb-upload:hover { color: var(--accent); border-color: var(--accent); }
.step-editor.is-drop-target, #media-picker .modal-box.is-drop-target {
  outline: 2px dashed var(--accent); outline-offset: 4px; }
.step-row.is-drop-target { box-shadow: 0 -3px 0 var(--accent); }
.step-grip { cursor: grab; color: var(--text-faint); font-size: 13px; user-select: none; }
.step-grip:hover { color: var(--accent); }
.step-slot { position: relative; width: 14px; flex: none; display: flex; align-items: center;
  justify-content: center; }
.step-slot > button { width: 18px; height: 18px; padding: 0; border-radius: 50%; font-size: 12px;
  line-height: 16px; opacity: 0; }
.step-thumbs:hover .step-slot > button, .step-slot > button:focus-visible { opacity: 1; }
@media (hover: none) { .step-slot > button { opacity: 1; } }
.slot-menu { position: absolute; top: 100%; left: 50%; transform: translateX(-50%); z-index: 5;
  display: flex; flex-direction: column; gap: 4px; padding: 6px; background: var(--bg-panel);
  border: 1px solid var(--line-strong); border-radius: var(--radius); box-shadow: var(--shadow);
  white-space: nowrap; }
.slot-menu button { font-size: 12px; padding: 3px 8px; }

.media-viewer { align-items: center; padding: 16px; }
.media-viewer-box { display: flex; flex-direction: column; gap: 8px;
  width: min(1100px, 100%); max-height: 92vh; }
.media-viewer-head { display: flex; gap: 12px; align-items: center; color: var(--text);
  font-size: 13px; }
.media-viewer-head span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }
.media-viewer-body { display: flex; align-items: center; gap: 8px; min-height: 0; }
.media-viewer-body img, .media-viewer-body video { flex: 1; min-width: 0;
  max-height: 84vh; object-fit: contain; border-radius: 8px; background: var(--bg); }
.media-viewer-nav { font-size: 28px; padding: 4px 12px; background: var(--bg-panel); }

/* Класс карточки на карте (владелец 05.10): кружок в углу. Фиолетовый с
   номером — цепочка, серый с номером — очередь, пустой пунктир — по запросу. */
.board .lane-badge { cursor: pointer; }
.board .lane-badge circle { stroke-width: 2; }
.board .lane-badge text { font-size: 12px; font-weight: 700; pointer-events: none; }
.board .lane-badge.lane-chain circle { fill: var(--draft); stroke: var(--draft-bg); }
.board .lane-badge.lane-chain text { fill: var(--accent-ink); }
.board .lane-badge.lane-queue circle { fill: var(--text-faint); stroke: var(--bg-raised); }
.board .lane-badge.lane-queue text { fill: var(--accent-ink); }
.board .lane-badge.lane-request circle { fill: var(--bg-panel); stroke: var(--text-faint);
  stroke-dasharray: 3 3; }
.board .lane-badge:hover circle { stroke: var(--accent); }
/* Блоки «Вход» (у начала карты) и «Когда» (у касаний вне цепочки). */
.board .cond-block { cursor: pointer; }
.board .cond-block rect { fill: var(--bg-subtle); stroke: var(--line-strong);
  stroke-dasharray: 5 4; }
.board .cond-block:hover rect { stroke: var(--accent); }
.board .entry-block rect { stroke: var(--ok); stroke-dasharray: none; }
.board .cond-link { fill: none; stroke: var(--line-strong); }
.board .cond { box-sizing: border-box; height: 100%; padding: 8px 10px; font-size: 11.5px;
  color: var(--text); overflow: hidden; pointer-events: none; display: flex;
  flex-direction: column; gap: 3px; }
.board .cond-head { font-weight: 600; font-size: 12px; color: var(--text-dim); }
.board .cond-reason { line-height: 1.3; overflow: hidden; display: -webkit-box;
  -webkit-line-clamp: 3; -webkit-box-orient: vertical; }
.board .cond-reason.is-empty { color: var(--warn); }
.board .cond-meta { color: var(--text-dim); white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; }
.board .cond-meta b { font-weight: 600; color: var(--text-faint); }

/* Всплывающее окошко доски: меню класса и правка условий. */
.board-pop { position: fixed; z-index: 60; width: min(340px, calc(100vw - 32px));
  max-height: 80vh; overflow-y: auto; background: var(--bg-panel);
  border: 1px solid var(--line-strong); border-radius: var(--radius);
  box-shadow: var(--shadow); padding: 10px 12px; display: flex; flex-direction: column;
  gap: 8px; font-size: 13px; }
.board-pop .pop-head { font-weight: 600; }
.board-pop .pop-field { display: flex; flex-direction: column; gap: 4px; color: var(--text-dim);
  font-size: 12px; }
.board-pop textarea, .board-pop select { width: 100%; font-size: 13px; }
.board-pop .pop-stages { max-height: 180px; overflow-y: auto; border: 1px solid var(--line);
  border-radius: var(--radius); padding: 4px 8px; display: flex; flex-direction: column; gap: 2px; }
.board-pop .pop-checks { display: flex; flex-wrap: wrap; gap: 4px 12px; }
.board-pop .check { color: var(--text); font-size: 12.5px; }
.board-pop .pop-funnel { font-size: 11px; color: var(--text-faint); margin-top: 4px;
  text-transform: uppercase; letter-spacing: .04em; }
.board-pop .pop-row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.board-pop .pop-help { margin: 0; font-size: 11.5px; color: var(--text-faint); }
.lane-menu .lane-item { display: flex; align-items: center; gap: 8px; text-align: left; }
.lane-menu .lane-item i { width: 14px; height: 14px; border-radius: 50%; flex: none;
  border: 2px solid var(--text-faint); }
.lane-menu .lane-chain i { background: var(--draft); border-color: var(--draft); }
.lane-menu .lane-queue i { background: var(--text-faint); }
.lane-menu .lane-request i { border-style: dashed; }
.lane-menu .lane-item.is-on { border-color: var(--accent); }

/* Панель карты в одну строку: добавить · вход · включена · ⋯ (05.10). */
.map-bar { display: flex; flex-wrap: wrap; gap: 8px 16px; align-items: center;
  margin: 0 0 12px; }
.map-add, .map-meta { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.map-meta { margin-left: auto; }
.map-bar-title { font-size: 12px; color: var(--text-faint); }
.map-add button, .map-meta button { font-size: 13px; padding: 4px 10px; }
.map-entry-sum { max-width: 520px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  text-align: left; background: var(--bg-subtle); border: 1px dashed var(--ok); }
.map-entry-sum b { font-weight: 600; }
.map-entry-edit { color: var(--accent); }
.map-active { font-size: 13px; }
#board-hint { flex-basis: 100%; width: fit-content; }
.board-pop.add-pop input[type=search], .board-pop.add-pop input[type=text] { width: 100%; }
.board-pop .pop-list { max-height: 300px; overflow-y: auto; display: flex; flex-direction: column;
  gap: 2px; }
.board-pop .pop-item { text-align: left; border: none; background: none; padding: 5px 8px;
  border-radius: 6px; font-size: 13px; }
.board-pop .pop-item:hover { background: var(--bg-hover); }

/* Слияние на карте: кружок ⊕ в центре карточки под курсором (05.10). */
.board .merge-zone { pointer-events: none; }
.board .merge-zone circle { fill: var(--bg-panel); stroke: var(--text-faint); stroke-width: 2;
  stroke-dasharray: 4 3; }
.board .merge-zone text { fill: var(--text-dim); font-size: 22px; }
.board .merge-zone .merge-zone-hint { font-size: 11px; fill: var(--text-faint); }
.board .merge-zone.is-hot circle { fill: var(--accent-soft); stroke: var(--accent); stroke-dasharray: none; }
.board .merge-zone.is-hot text { fill: var(--accent); }
.board-pop.merge-pop p { margin: 0; }

/* Редактор касания поверх карты (05.10). */
.touch-modal { z-index: 70; padding-top: 4vh; }
.touch-modal-box { width: min(1200px, 100%); max-height: 92vh; overflow-y: auto; }
.touch-modal-box .card-head { display: flex; gap: 12px; align-items: center; }
.touch-modal-box .card-head h2 { margin: 0; flex: 1; min-width: 0; }

/* Выделение нескольких карточек и кнопки в углу доски (05.10). */
.board .node.is-selected rect { stroke: var(--accent); stroke-width: 2.5; }
.board .lasso { fill: var(--accent-soft); fill-opacity: .5; stroke: var(--accent);
  stroke-dasharray: 4 3; pointer-events: none; }
.board.is-selecting { cursor: crosshair; }
#select-btn.is-on { border-color: var(--accent); color: var(--accent); }
.board-wrap { position: relative; }
.board-corner { position: absolute; right: 12px; bottom: 12px; display: flex; gap: 8px;
  align-items: center; background: var(--bg-panel); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 6px; box-shadow: var(--shadow); }
.board-pop .pop-number { gap: 6px; color: var(--text-dim); font-size: 12px; }
.board-pop .pop-number input { width: 72px; }

/* Общее КП (05.10): позиции корзины клиента — ⣿, фото, название и текст,
   количество и цена, итог. */
.bundle-items { display: flex; flex-direction: column; gap: 8px; margin: 8px 0; }
.bundle-row { display: grid; grid-template-columns: 18px 100px minmax(0, 1fr) 190px 28px;
  gap: 12px; align-items: start; padding: 10px; border: 1px solid var(--line);
  border-radius: var(--radius); background: var(--bg-panel); }
@media (max-width: 760px) {
  .bundle-row { grid-template-columns: 18px 100px minmax(0, 1fr) 28px; }
  .bundle-money { grid-column: 2 / -1; }
}
.bundle-grip { cursor: grab; color: var(--text-faint); padding-top: 6px; user-select: none; }
.bundle-photos { display: flex; flex-wrap: wrap; gap: 4px; width: 100px; }
.bundle-photo { position: relative; width: 30px; height: 24px; border-radius: 5px; overflow: hidden;
  background: var(--bg-subtle); display: flex; align-items: center; justify-content: center; }
.bundle-photo.main { width: 100px; height: 72px; border-radius: 8px; }
.bundle-photo img { width: 100%; height: 100%; object-fit: cover; cursor: pointer; }
.bundle-photo.main img { cursor: default; }
.bundle-photo.empty img { object-position: 30% 60%; }
.bundle-photo.empty, .bundle-photo.add { cursor: pointer; border: 1px dashed var(--line-strong); }
.bundle-photo span { font-size: 11px; color: var(--text-faint); }
.bundle-photo.empty img + input + span { position: absolute; bottom: 2px; right: 4px; padding: 0 4px;
  border-radius: 4px; background: var(--bg-raised); opacity: 0; }
.bundle-photo.empty:hover img + input + span { opacity: 1; }
.bundle-photo-x { position: absolute; top: 1px; right: 1px; width: 16px; height: 16px; padding: 0;
  border: 0; border-radius: 50%; background: var(--on-media-shadow); color: var(--on-media); font-size: 11px;
  line-height: 16px; cursor: pointer; opacity: 0; }
.bundle-photo:hover .bundle-photo-x, .bundle-photo-x:focus { opacity: 1; }
.bundle-main { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.bundle-title { font-weight: 600; }
.bundle-comp { line-height: 1.4; }
.bundle-note, .bundle-fabric { font-size: 13px; }
.bundle-money { display: flex; flex-direction: column; gap: 6px; align-items: stretch; }
.bundle-money label { display: flex; justify-content: space-between; gap: 8px; align-items: center;
  font-size: 12px; color: var(--text-dim); }
.bundle-money input { width: 110px; text-align: right; }
.bundle-sum { text-align: right; font-size: 15px; }
.bundle-actions { flex-wrap: wrap; gap: 8px 16px; }

/* Карта открыта по ссылке «На картах» — карточку видно рамкой. */
.board .node.is-found rect { stroke: var(--accent); stroke-width: 3; }
.empty-note { color: var(--text-faint); padding: 16px 0; }
.sort-row[data-unit] { cursor: grab; }

/* Доска карт: подробная карточка (foreignObject) и подсветка цепочки. */
.board .bn { box-sizing: border-box; height: 100%; padding: 8px 30px 8px 10px;
  display: flex; flex-direction: column; gap: 4px; overflow: hidden; font-size: 12px;
  color: var(--text); pointer-events: none; }
.board .bn-head { font-size: 11px; color: var(--text-faint); white-space: nowrap; }
.board .bn-head b { color: var(--accent); }
.board .bn-start { color: var(--ok); }
.board .bn-title { font-weight: 600; font-size: 13px; line-height: 1.25; overflow: hidden;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.board .bn-thumbs { display: flex; gap: 3px; }
.board .bn-thumbs .unit-thumb { width: 30px; height: 30px; flex: none; }
.board .bn-line { color: var(--text-dim); white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; }
.board .bn-labels { display: flex; gap: 3px; overflow: hidden; flex-wrap: nowrap; }
.board .bn-labels .ulabel { font-size: 10.5px; line-height: 16px; }
.board.has-hl .edge:not(.is-hl) { opacity: .2; }
.board.has-hl .node:not(.is-hl) { opacity: .45; }
.board .edge.is-hl path { stroke: var(--accent); stroke-width: 2.2; }
.board .node.is-hl rect { stroke: var(--accent); }

/* Экран «Метки»: оси карточками, метки компактно по осям. */
.axis-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(220px, 100%), 1fr));
  gap: 8px; margin: 8px 0 12px; }
.axis-card { display: flex; flex-direction: column; gap: 2px; padding: 8px 10px;
  border-radius: 8px; text-decoration: none; color: var(--text);
  border: 1px solid color-mix(in srgb, var(--ax) 40%, var(--line));
  background: color-mix(in srgb, var(--ax) 8%, var(--bg-panel)); }
.axis-card:hover { border-color: var(--ax); }
.axis-name { font-weight: 600; display: flex; align-items: center; gap: 6px; }
.axis-count { font-size: 12px; color: var(--text-faint); }
.axis-help { font-size: 12px; color: var(--text-dim); line-height: 1.3; }
.ax-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%;
  background: var(--ax, var(--ax-other)); flex: none; }
.axis-section { border-left: 4px solid var(--ax); }
.axis-section h2 { display: flex; align-items: center; gap: 8px; }
.label-list { display: flex; flex-wrap: wrap; gap: 6px; }
.label-item { border: 1px solid transparent; border-radius: 8px; }
.label-item > summary { list-style: none; display: inline-flex; align-items: center; gap: 6px;
  cursor: pointer; padding: 2px 4px; }
.label-item > summary::-webkit-details-marker { display: none; }
.label-item[open] { flex-basis: 100%; border-color: var(--line); padding: 6px 10px 10px; }
.label-item-usage { font-size: 11px; color: var(--text-faint); min-width: 14px; }
.label-item-aliases { max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.phrase-line { flex: 1 1 260px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.media-card.is-target { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Список карт: тропа шагов под названием карты. */
.map-trail { display: flex; flex-wrap: wrap; gap: 4px; margin: 6px 0; }
.map-step { font-size: 12px; padding: 2px 8px; border-radius: 6px; background: var(--bg-subtle);
  color: var(--text-dim); max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.map-step b { color: var(--accent); }

/* Карточка клиента: следующий шаг агента и предпросмотр «что уйдёт». */
.next-step { background: var(--accent-soft); border-radius: 8px; padding: 10px 12px; }
.next-why { margin: 0 0 4px; }
.material-row.is-next { border-top-color: color-mix(in srgb, var(--accent) 25%, var(--line)); }
.dry-run .dr-chat { display: flex; flex-direction: column; gap: 8px; max-height: 64vh; overflow: auto;
  padding: 6px 2px; }
.dr-bubble { background: var(--accent-soft); border: 1px solid var(--line); border-radius: 12px 12px 12px 4px;
  padding: 8px 12px; max-width: 520px; white-space: normal; line-height: 1.4; }
.dr-note { font-size: 11.5px; color: var(--text-faint); margin: 3px 0 0 4px; }
.dr-media { display: flex; flex-wrap: wrap; gap: 4px; }
.dr-file { position: relative; width: 84px; height: 84px; display: inline-block; }
.dr-file .unit-thumb { width: 84px; height: 84px; }
.dr-file.is-sent .unit-thumb { opacity: .35; }
.dr-sent { position: absolute; left: 4px; right: 4px; bottom: 4px; font-size: 10.5px; text-align: center;
  background: var(--warn-bg); color: var(--warn); border-radius: 4px; }
.dr-pause { font-size: 12px; color: var(--text-faint); text-align: center; }
.touch-dry { align-self: flex-start; font-size: 12px; }

/* Выбор фразы в редакторе шагов. */
.phrase-pick-list { display: flex; flex-direction: column; gap: 6px; max-height: 60vh; overflow: auto; margin-top: 8px; }
.phrase-pick { display: flex; flex-direction: column; gap: 3px; text-align: left; padding: 8px 10px;
  border: 1px solid var(--line); border-radius: 8px; background: var(--bg-panel); }
.phrase-pick:hover { border-color: var(--accent); }
.phrase-pick-head { display: flex; gap: 8px; align-items: baseline; }
.phrase-pick-text { font-size: 12.5px; color: var(--text-dim); }
.next-map { display: inline-flex; gap: 6px; align-items: center; margin: 2px 0 4px; font-size: 13px; }

/* Перед отправкой касания: тексты в полях, вид — как у предпросмотра. */
.dr-edit { width: 100%; font: inherit; padding: 8px 10px; border-radius: 12px;
  border: 1px solid var(--line); background: var(--bg-raised); color: var(--text);
  resize: vertical; }
.dr-edit:focus { border-color: var(--accent); outline: none; }
.review-touch + .review-touch { margin-top: 16px; border-top: 1px solid var(--line); padding-top: 12px; }
.review-touch h3 { margin: 0 0 8px; font-size: 15px; }

/* Быстрые ответы: переключатель на экранах и список в карточке. */
.quick-toggle.is-on { background: var(--accent-dim); color: var(--text); border-color: var(--accent); }
.quick-list { display: flex; flex-direction: column; gap: 6px; max-height: 60vh; overflow-y: auto; }
.quick-item { display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
  text-align: left; padding: 8px 10px; border: 1px solid var(--line); border-radius: 10px;
  background: var(--bg-raised); color: var(--text); cursor: pointer; }
.quick-item:hover { border-color: var(--accent); }
.quick-kind { font-size: 11px; color: var(--text-faint); text-transform: uppercase; letter-spacing: .04em; }
#new-phrase { margin-bottom: 12px; }
.touch-text-hit { display: flex; flex-direction: column; gap: 2px; padding: 8px 10px;
  border: 1px solid var(--line); border-radius: 10px; margin-bottom: 6px; color: var(--text);
  text-decoration: none; }
.touch-text-hit:hover { border-color: var(--accent); }
.touch-text-hit span { color: var(--text-dim); font-size: 13px; }
/* Доска: одинаковый индекс у двух карточек — видно сразу. */
.board .node.dup-code > rect { stroke: var(--err); stroke-width: 2; stroke-dasharray: 5 3; }

/* Общая карта касаний (04.10): рамки карт, стрелки переходов, «по условию». */
.overview-card { padding: 0; overflow: hidden; }
.board.overview { width: 100%; height: calc(100vh - var(--head-h) - 140px); min-height: 480px;
  display: block; }
.board.overview .ov-frame { cursor: grab; }
.ov-frame > rect { fill: color-mix(in srgb, var(--bg-panel) 70%, transparent); stroke: var(--line); stroke-width: 1.5; }
.ov-frame.is-off > rect { stroke-dasharray: 8 6; opacity: .8; }
.ov-frame:hover > rect { stroke: var(--accent); }
.ov-title { fill: var(--text); font-size: 22px; font-weight: 600; }
.ov-entry { fill: var(--text-dim); font-size: 13px; }
/* Карточки общей карты — те же классы, что на доске (.board .node …). */
.board .kind-map rect { fill: color-mix(in srgb, var(--ok) 16%, var(--bg-panel)); stroke: var(--ok); }
.board .kind-pick rect { stroke-dasharray: 4 3; }
/* Навык и действие на карте (владелец 13.10): «сделать» и «перейти» видно
   издалека, не путая с касаниями. */
.board .kind-skill rect { fill: color-mix(in srgb, var(--warn) 14%, var(--bg-panel)); stroke: var(--warn); }
.board .kind-action rect { fill: color-mix(in srgb, var(--draft) 16%, var(--bg-panel)); stroke: var(--draft);
  stroke-dasharray: 6 3; }
.ov-edge { fill: none; stroke: var(--text-faint); stroke-width: 1.6; }
.ov-jump { fill: none; stroke: var(--ok); stroke-width: 3; stroke-dasharray: 8 6; }
#ov-arrow path { fill: var(--text-faint); }
.ov-lane > rect { fill: var(--bg-panel); stroke: var(--warn); stroke-dasharray: 6 4; }
/* Доска одной карты: полоса «Вход в карту» и стрелка «вход». */
.map-entries { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-bottom: 8px; }
.entry-pill.is-off { opacity: .6; }
.board .entry-arrow path { stroke: var(--ok); stroke-width: 2; stroke-dasharray: 5 3; }


/* ── Пульт агента (/agent, владелец 04.10: «непонятно, что где включается») ──
   Цвет режима один везде: выключен — серый, только CRM — синий, с
   подтверждением — фиолетовый (как черновики), сам — зелёный. */
.ac-section { margin: 0 0 28px; }
.ac-h { font-size: 15px; font-weight: 600; margin: 0 0 12px; letter-spacing: .01em; }
.ac-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 12px; }
.ac-tile {
  background: var(--bg-panel); border: 1px solid var(--line); border-radius: 10px;
  padding: 14px 16px; display: flex; flex-direction: column; gap: 8px; min-width: 0;
}
.ac-tile-head { display: flex; align-items: center; gap: 8px; }
.ac-tile-title { font-weight: 600; }
.ac-tile-note { margin: 0; color: var(--text-dim); font-size: 13px; line-height: 1.45; }
.ac-tile .btn { align-self: flex-start; }
.ac-select { max-width: 100%; }
.ac-select.small { font-size: 13px; padding: 3px 6px; margin: 4px 0 2px; }

.ac-switches { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 10px; margin-bottom: 8px; }
.ac-switch-row {
  display: flex; gap: 12px; align-items: flex-start; cursor: pointer;
  background: var(--bg-panel); border: 1px solid var(--line); border-radius: 10px; padding: 12px 14px;
}
.ac-switch-text { display: flex; flex-direction: column; gap: 3px; font-size: 14px; }
.ac-switch { position: relative; flex: 0 0 auto; width: 38px; height: 22px; margin-top: 1px; }
.ac-switch input { position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; z-index: 1; }
.ac-switch-track {
  position: absolute; inset: 0; border-radius: 11px; background: var(--line-strong);
  transition: background .15s ease;
}
.ac-switch-track::after {
  content: ""; position: absolute; top: 3px; left: 3px; width: 16px; height: 16px; border-radius: 50%;
  background: var(--bg-panel); box-shadow: var(--shadow); transition: transform .15s ease;
}
.ac-switch input:checked + .ac-switch-track { background: var(--ok); }
.ac-switch input:checked + .ac-switch-track::after { transform: translateX(16px); }
.ac-switch input:focus-visible + .ac-switch-track { outline: 2px solid var(--accent); outline-offset: 2px; }
.ac-switch.small { width: 32px; height: 18px; }
.ac-switch.small .ac-switch-track::after { width: 12px; height: 12px; }
.ac-switch.small input:checked + .ac-switch-track::after { transform: translateX(14px); }

.ac-stages-head { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; margin-bottom: 10px; }
.ac-stages-head .ac-h { margin: 0; }
/* Пауза «вы пишете сами» и раздел «Клиенты» (владелец 13.10). */
.ac-quiet-row {
  display: flex; gap: 12px; align-items: center; justify-content: space-between; flex-wrap: wrap;
  background: var(--bg-panel); border: 1px solid var(--line); border-radius: 10px;
  padding: 12px 14px; margin-bottom: 8px;
}
.ac-quiet-row > span:first-child { display: flex; flex-direction: column; gap: 3px; font-size: 14px; max-width: 640px; }
.ac-quiet-input { display: inline-flex; align-items: center; gap: 6px; font-size: 14px; color: var(--text-dim); }
.ac-quiet-input input { width: 84px; }
.ac-clients-q { flex: 1 1 220px; max-width: 320px; margin-left: auto; }
.ac-clients-table { overflow-x: auto; }
.ac-clients td { min-width: 0; }
.ac-clients td > .cell-sub { display: block; margin-top: 2px; }
.ac-client-chips { display: flex; gap: 4px; flex-wrap: wrap; margin-top: 4px; }
.ac-client-mode { min-width: 168px; border-left: 4px solid var(--mode, var(--line)); }
.ac-client-now b { color: var(--mode, var(--text)); font-weight: 600; }
.ac-legend { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-bottom: 12px; }
.ac-mode-chip {
  display: inline-flex; align-items: center; gap: 6px; font-size: 12px; padding: 3px 9px;
  border-radius: 999px; border: 1px solid var(--line); color: var(--text-dim);
}
.ac-mode-dot { width: 8px; height: 8px; border-radius: 50%; background: currentColor; flex: 0 0 auto; }
.ac-bulk { margin-left: auto; display: inline-flex; flex-wrap: wrap; gap: 6px; align-items: center;
  font-size: 12px; color: var(--text-faint); }
.mode-off { --mode: var(--text-faint); --mode-bg: var(--bg-subtle); }
.mode-crm { --mode: var(--accent); --mode-bg: var(--accent-soft); }
.mode-draft { --mode: var(--draft); --mode-bg: var(--draft-bg); }
.mode-auto { --mode: var(--ok); --mode-bg: var(--ok-bg); }
.ac-mode-chip { color: var(--mode); }

.ac-board {
  display: grid; grid-auto-flow: column; grid-auto-columns: 272px; gap: 12px;
  overflow-x: auto; padding: 2px 2px 14px; scroll-snap-type: x proximity;
}
.ac-stage {
  scroll-snap-align: start; position: relative; display: flex; flex-direction: column;
  background: var(--bg-panel); border: 1px solid var(--line); border-radius: 10px; overflow: hidden;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.ac-stage:hover { border-color: var(--line-strong); box-shadow: var(--shadow); }
.ac-stage-cap { height: 4px; }
.ac-stage-head { display: flex; align-items: flex-start; gap: 8px; padding: 10px 12px 8px; cursor: pointer; }
.ac-stage-title { font-weight: 600; font-size: 14px; line-height: 1.3; flex: 1; }
.ac-stage-count {
  font-size: 12px; color: var(--text-dim); background: var(--bg-subtle); border-radius: 999px;
  padding: 1px 8px; flex: 0 0 auto;
}
.ac-modes { display: grid; grid-template-columns: repeat(2, 1fr); gap: 4px; padding: 0 12px 10px; }
.ac-mode {
  font-size: 12px; padding: 5px 4px; border-radius: 6px; border: 1px solid var(--line);
  background: transparent; color: var(--text-dim); cursor: pointer; text-align: center;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ac-mode:hover { border-color: var(--mode); color: var(--text); }
.ac-mode.is-on { background: var(--mode-bg); border-color: var(--mode); color: var(--mode); box-shadow: inset 0 0 0 1px var(--mode); }
.ac-facts { list-style: none; margin: 0; padding: 8px 12px; border-top: 1px solid var(--line);
  display: flex; flex-direction: column; gap: 4px; font-size: 12px; color: var(--text-faint); cursor: pointer; flex: 1; }
.ac-facts li.is-on { color: var(--text-dim); }
.ac-facts li.is-on b { color: var(--text); }
.ac-facts li.is-warn b { color: var(--warn); }
.ac-open {
  border: none; border-top: 1px solid var(--line); background: transparent; color: var(--accent);
  padding: 8px 12px; text-align: left; cursor: pointer; font-size: 13px;
}
.ac-open:hover { background: var(--bg-hover); }

/* Панель стадии — справа, на всю высоту. */
body.ac-locked { overflow: hidden; }
.ac-drawer-scrim { position: fixed; inset: 0; background: var(--scrim); z-index: 80; }
.ac-drawer {
  position: fixed; top: 0; right: 0; bottom: 0; width: min(640px, 100vw); z-index: 81;
  background: var(--bg-panel); border-left: 1px solid var(--line); box-shadow: var(--shadow);
  display: flex; flex-direction: column;
}
.ac-d-head { display: flex; align-items: flex-start; gap: 12px; padding: 16px 18px 12px; border-bottom: 1px solid var(--line); }
.ac-d-cap { width: 6px; align-self: stretch; border-radius: 3px; flex: 0 0 auto; }
.ac-d-title { flex: 1; min-width: 0; }
.ac-d-title h3 { margin: 0 0 4px; font-size: 18px; }
.ac-d-close { flex: 0 0 auto; }
.ac-d-nav { display: flex; flex-direction: row; gap: 4px; flex-wrap: wrap; padding: 8px 18px; border-bottom: 1px solid var(--line); }
.ac-d-nav a { display: inline-block; font-size: 12px; color: var(--text-dim); padding: 3px 8px; border-radius: 6px; text-decoration: none; }
.ac-d-nav a:hover { background: var(--bg-hover); color: var(--text); }
.ac-d-body { overflow-y: auto; padding: 4px 18px 40px; scroll-behavior: smooth; }
.ac-d-sec { padding: 16px 0; border-bottom: 1px solid var(--line); }
.ac-d-sec:last-child { border-bottom: none; }
.ac-d-sec h4 { margin: 0 0 8px; font-size: 14px; }
.ac-d-sec > .cell-sub { display: block; margin-bottom: 8px; line-height: 1.45; }
.ac-mode-cards { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; margin-bottom: 12px; }
.ac-mode-card {
  display: flex; flex-direction: column; gap: 4px; text-align: left; cursor: pointer;
  border: 1px solid var(--line); border-radius: 8px; padding: 10px 12px; background: transparent; color: var(--text);
}
.ac-mode-card:hover { border-color: var(--mode); }
.ac-mode-card.is-on { border-color: var(--mode); background: var(--mode-bg); }
.ac-mode-name { display: inline-flex; align-items: center; gap: 7px; font-weight: 600; color: var(--mode); }
.ac-d-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 10px; align-items: end; font-size: 13px; }
.ac-d-grid label { display: flex; flex-direction: column; gap: 4px; color: var(--text-dim); }
.ac-d-grid .ac-check { flex-direction: row; align-items: center; gap: 8px; color: var(--text); }
.ac-num { width: 120px; }
.ac-when { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.ac-when li { display: flex; gap: 10px; align-items: flex-start; font-size: 13px; }
.ac-when li > span:last-child { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ac-mark { width: 20px; flex: 0 0 auto; text-align: center; color: var(--text-dim); }
.ac-text { width: 100%; box-sizing: border-box; resize: vertical; margin-bottom: 8px; font: inherit; line-height: 1.45; }
.ac-prompt { font-size: 13px; }
.ac-map-row { display: flex; gap: 10px; align-items: flex-start; padding: 8px 0; border-bottom: 1px dashed var(--line); }
.ac-map-row:last-of-type { border-bottom: none; margin-bottom: 8px; }
.ac-map-text { display: flex; flex-direction: column; gap: 2px; font-size: 13px; min-width: 0; }

@media (max-width: 720px) {
  .ac-bulk { margin-left: 0; }
  .ac-mode-cards { grid-template-columns: 1fr; }
  .ac-board { grid-auto-columns: 82vw; }
}
.ac-settings-link {
  display: flex; align-items: center; gap: 12px; margin-top: 10px; padding: 12px 14px;
  border: 1px solid var(--accent-dim); background: var(--accent-soft); border-radius: 10px;
  color: var(--text); text-decoration: none;
}
.ac-settings-link:hover { border-color: var(--accent); }
.ac-settings-link > span:nth-child(2) { display: flex; flex-direction: column; gap: 2px; flex: 1; }
.ac-settings-icon { font-size: 20px; color: var(--accent); }
.ac-settings-go { color: var(--accent); font-size: 18px; }

/* ── Отправить клиенту: вкладки и строки (владелец 04.10) ────────────────── */
.lib-tabs { margin: 4px 0 8px; flex-wrap: wrap; }
.lib-count { margin-left: 6px; font-size: 11px; color: var(--text-faint); }
.lib-tabs a.is-active .lib-count { color: var(--text-dim); }
.lib-question { margin: 0 0 8px; font-size: 13px; color: var(--text-dim); }
.lib-list { display: flex; flex-direction: column; gap: 8px; max-height: 62vh; overflow-y: auto; }
.lib-row { border: 1px solid var(--line); border-radius: 8px; padding: 10px 12px;
  display: flex; flex-direction: column; gap: 5px; background: var(--bg-panel); }
.lib-row-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.lib-row-meta { display: flex; gap: 4px; flex-wrap: wrap; }
.lib-row-text { margin: 0; font-size: 13px; color: var(--text-dim); white-space: pre-line; line-height: 1.4; }
.lib-row-actions { display: flex; gap: 6px; }
.next-question:empty { display: none; }
.next-question { border: 1px solid var(--accent-dim); background: var(--accent-soft); border-radius: 8px;
  padding: 8px 10px; margin: 6px 0 8px; display: flex; flex-direction: column; gap: 5px; }
.nq-head { font-size: 12px; color: var(--text-dim); }
.nq-q { color: var(--text); }
.nq-row { display: flex; align-items: center; gap: 8px; font-size: 13px; }
.nq-title { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.nq-about { white-space: nowrap; max-width: 30%; overflow: hidden; text-overflow: ellipsis; }
/* Общая карта: детали при приближении (overview.js, DETAIL_AT). */
.board.overview:not(.is-detailed) .ov-detail { display: none; }
.board.overview.is-detailed .ov-node.has-detail > text { display: none; }
.board .ov-bn { padding: 5px 8px; display: flex; flex-direction: column; gap: 2px; overflow: hidden; }
.board .ov-bn .bn-title { font-size: 12px; white-space: nowrap; text-overflow: ellipsis; }
.ov-bn-row { display: flex; gap: 3px; align-items: center; overflow: hidden; }
.ov-bn-row .unit-thumb { width: 20px; height: 20px; flex: none; }
.ov-bn-row .ulabel { font-size: 9.5px; line-height: 14px; }

/* Чей элемент в палитре конструктора: модель или «все модели». */
.cmp-tile .cmp-tile-owner { display: block; font-size: 11px; color: var(--text-faint); }

/* Вращение за уголок выбранного блока (composerSpin). */
.cmp-r {
  position: absolute; width: 12px; height: 12px; border-radius: 50%;
  background: var(--accent); opacity: .0; z-index: 4; cursor: grab; touch-action: none;
}
.composer-block.picked .cmp-r { opacity: .55; }
.composer-block.picked .cmp-r:hover { opacity: 1; }
.cmp-r-nw { top: -10px; left: -10px; } .cmp-r-ne { top: -10px; right: -10px; }
.cmp-r-se { bottom: -10px; right: -10px; } .cmp-r-sw { bottom: -10px; left: -10px; }
@media (pointer: coarse) { .cmp-r { width: 22px; height: 22px; } }

/* ── Новый клиент ─────────────────────────────────────────────────────────── */
.board-add { display: block; width: calc(100% - 8px); margin: 0 4px 6px; padding: 4px 0;
  border: 1px dashed var(--line-strong); border-radius: var(--radius); background: none;
  color: var(--text-faint); font-size: 12px; cursor: pointer; }
.board-add:hover { color: var(--text); border-color: var(--accent); }
.nc-box { width: min(560px, 100%); gap: 10px; }
.nc-field { display: flex; flex-direction: column; gap: 4px; font-size: 12px; color: var(--text-dim); }
.nc-name input { font-size: 15px; }
.nc-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px 12px;
  overflow-y: auto; }
@media (max-width: 560px) { .nc-grid { grid-template-columns: 1fr; } }


/* ── Карточка внутри окна мессенджера (`?embed=`) ─────────────────────────
   Без меню панели: окно и так поверх неё. «card» — карточка целиком, с её
   шапкой и кнопкой «Сохранить»; «chat» — только переписка и поле ответа. */
body.embed .head-row { display: none; }
body.embed .content { padding: 12px 16px 24px; max-width: none; }
body.embed-chat .page-head, body.embed-chat .client-head, body.embed-chat .col-fields,
body.embed-chat .merged-note, body.embed-chat .scan-result { display: none !important; }
body.embed-chat .content { padding: 0; }
body.embed-chat .client-grid { display: block; }
body.embed-chat .col-feed { position: static; }
body.embed-chat .feed-card { position: static; height: 100vh; max-height: none; margin: 0;
  border: 0; border-radius: 0; }
body.embed-chat .feed-card > .card-head h2 { display: none; }
.follow-btn.is-on { color: var(--warn); border-color: var(--warn); }

/* ── Мессенджер панели (владелец 06.10) ───────────────────────────────────
   Кнопка в правом нижнем углу, окошко чатов над ней, окно на 70% экрана для
   карточки клиента и отслеживаемых. Цвета — токены темы. */
.msgr { position: fixed; right: 24px; bottom: 24px; z-index: 45; display: flex;
  flex-direction: column; align-items: flex-end; gap: 12px; }
.msgr-fab { position: relative; width: 52px; height: 52px; border-radius: 50%; padding: 0;
  display: flex; align-items: center; justify-content: center; border: 1px solid var(--line-strong);
  background: var(--accent); color: var(--accent-ink); box-shadow: var(--shadow); cursor: pointer; }
.msgr-fab svg { width: 24px; height: 24px; }
.msgr-badge { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px;
  padding: 0 5px; border-radius: 10px; background: var(--err); color: var(--on-media);
  font-size: 11px; font-weight: 600; line-height: 20px; text-align: center; }
.msgr-panel { width: min(400px, calc(100vw - 32px)); height: min(620px, calc(100vh - 110px));
  display: flex; flex-direction: column; background: var(--bg-panel);
  border: 1px solid var(--line-strong); border-radius: 12px; box-shadow: var(--shadow); overflow: hidden; }
.msgr-head, .msgr-pop-head { display: flex; align-items: center; gap: 8px; padding: 10px 12px;
  border-bottom: 1px solid var(--line); }
.msgr-title { font-weight: 600; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }
.msgr-tools { display: flex; align-items: center; gap: 4px; margin-left: auto; }
.msgr-tools a.icon-btn { text-decoration: none; }
.msgr-list-view, .msgr-chat-view { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.msgr-search { margin: 10px 12px; width: auto; }
/* Фильтр мессенджера — общий ряд `.fbar` (ниже), здесь только отступы
   под поиском окошка. */
.msgr-filterbar { margin: -4px 12px 8px; }
.msgr-list { flex: 1; min-height: 0; overflow-y: auto; }
.msgr-row { display: flex; gap: 10px; align-items: center; padding: 9px 12px; cursor: pointer;
  border-bottom: 1px solid var(--line); }
.msgr-row:hover, .msgr-row.is-active { background: var(--bg-hover); }
.msgr-ava { position: relative; flex: 0 0 40px; width: 40px; height: 40px; border-radius: 50%;
  background: var(--ava, var(--line-strong)); color: var(--on-media); display: flex;
  align-items: center; justify-content: center; font-weight: 600; font-size: 14px; }
.msgr-ch { position: absolute; right: -6px; bottom: -4px; font-style: normal; font-size: 9px;
  padding: 0 4px; border-radius: 6px; background: var(--bg-raised); color: var(--text-dim);
  border: 1px solid var(--line-strong); line-height: 14px; }
.msgr-row-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.msgr-row-top, .msgr-row-bottom { display: flex; gap: 8px; align-items: baseline; min-width: 0; }
.msgr-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-weight: 500; }
.msgr-row.is-unread .msgr-name { font-weight: 700; }
.msgr-pin { color: var(--warn); margin-right: 4px; }
.msgr-when { font-size: 11px; color: var(--text-faint); flex: 0 0 auto; }
.msgr-text { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 12.5px; color: var(--text-dim); }
.msgr-row.is-unread .msgr-text { color: var(--text); }
.msgr-num { color: var(--text-faint); }
.msgr-count { flex: 0 0 auto; min-width: 18px; height: 18px; padding: 0 5px; border-radius: 9px;
  background: var(--accent); color: var(--accent-ink); font-size: 11px; font-weight: 600;
  line-height: 18px; text-align: center; border: 0; cursor: pointer; }
/* Кружок — кнопка (07.10): с числом — «прочитано»; у прочитанного чата —
   пустой кружок при наведении, «пометить непрочитанным». */
.msgr-count:hover { box-shadow: 0 0 0 2px var(--accent-soft); }
.msgr-mark { flex: 0 0 auto; width: 18px; height: 18px; padding: 0; border-radius: 50%;
  border: 1.5px solid var(--line-strong); background: transparent; cursor: pointer;
  visibility: hidden; }
.msgr-row:hover .msgr-mark, .msgr-mark:focus-visible { visibility: visible; }
.msgr-mark:hover { border-color: var(--accent); }
@media (hover: none) { .msgr-mark { visibility: visible; opacity: .5; } }
.msgr-frame, .msgs-frame, .msgr-pop-frame { flex: 1; width: 100%; min-height: 0; border: 0;
  background: var(--bg-panel); }
.msgr-fresh { padding: 6px 12px; font-size: 12px; background: var(--accent-soft); color: var(--text); }
.msgr-pop { position: fixed; inset: 0; z-index: 60; background: var(--scrim); display: flex;
  align-items: center; justify-content: center; padding: 16px; }
.msgr-pop-box { width: min(1280px, 78vw); height: 82vh; display: flex; flex-direction: column;
  background: var(--bg); border: 1px solid var(--line-strong); border-radius: 12px;
  box-shadow: var(--shadow); overflow: hidden; }
@media (max-width: 900px) { .msgr-pop-box { width: 100%; height: 92vh; } }
.msgr-pop-body { flex: 1; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; }
.msgr-pop-body > #msgr-follow-cards, .msgr-follow-add { padding: 0 16px; }
.msgr-follow-add { padding-top: 12px; }
.msgr-follow-add .msgr-search { margin: 0 0 8px; width: min(420px, 100%); }
.msgr-found-row { display: flex; justify-content: space-between; align-items: center; gap: 12px;
  padding: 6px 0; border-bottom: 1px solid var(--line); max-width: 520px; }
.msgr-follow-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 12px; padding: 12px 0 16px; }
.msgr-follow-item .board-card { cursor: pointer; }
.msgr-follow-item .board-card .pick { display: none; }
.msgr-follow-stage { display: flex; justify-content: space-between; align-items: center;
  font-size: 12px; color: var(--text-dim); padding: 0 2px 4px; border-top: 3px solid var(--stage);
  padding-top: 4px; }
/* Страница «Сообщения» */
.msgs-page { display: grid; grid-template-columns: minmax(280px, 360px) minmax(0, 1fr); padding: 0;
  height: calc(100vh - var(--head-h, 120px) - 120px); min-height: 480px; overflow: hidden; }
.msgs-side { display: flex; flex-direction: column; min-height: 0; border-right: 1px solid var(--line); }
.msgs-main { display: flex; flex-direction: column; min-height: 0; }
.msgs-head { display: flex; align-items: center; gap: 10px; padding: 10px 14px;
  border-bottom: 1px solid var(--line); }
.msgs-who { display: flex; flex-direction: column; min-width: 0; }
.msgs-empty { margin: auto; }
@media (max-width: 760px) { .msgs-page { grid-template-columns: 1fr; height: auto; }
  .msgs-frame { height: 70vh; } }
body.embed .topbar-back { display: none; }

/* ── Форма расчёта: поля по содержимому (владелец 06.10) ─────────────────
   «Другие формы, особенно касания, приятнее: поля не растягиваются на 60%
   ширины». У каждого поля своя ширина — по тому, что в нём пишут. */
.calc-params { display: flex; flex-wrap: wrap; gap: 4px 16px; align-items: flex-start; }
.calc-params .field { margin-bottom: 12px; }
.calc-f-product { width: 300px; }
.calc-f-fabric { width: 280px; }
.calc-f-num { width: 170px; }
.calc-f-short { width: 110px; }
.calc-f-memory { flex: 1 1 100%; margin-bottom: 4px !important; }
.calc-f-memory .help { margin: 0; }
.calc-client-row { display: flex; flex-wrap: wrap; gap: 12px 20px; align-items: flex-start;
  padding-top: 12px; border-top: 1px solid var(--line); }
.calc-f-client { width: 360px; margin-bottom: 0; }
.calc-client-sets { flex: 1 1 420px; min-width: 0; }
.mini-sets-head { font-size: 12px; color: var(--text-dim); margin-bottom: 6px; }
.mini-sets { display: flex; gap: 10px; overflow-x: auto; padding-bottom: 6px; }
.mini-set { flex: 0 0 210px; display: flex; gap: 8px; padding: 8px; border: 1px solid var(--line);
  border-radius: var(--radius); background: var(--bg-subtle); color: var(--text); text-decoration: none; }
.mini-set:hover { border-color: var(--accent); }
.mini-set.is-open { border-color: var(--accent); background: var(--accent-soft); }
.mini-set-thumb { flex: 0 0 58px; height: 82px; border-radius: 4px; overflow: hidden;
  background: var(--bg-panel); border: 1px solid var(--line); display: flex; align-items: center;
  justify-content: center; }
.mini-set-thumb img { width: 100%; height: 100%; object-fit: cover; object-position: top; }
.mini-set-model { font-size: 10px; color: var(--text-faint); text-align: center; padding: 2px; }
.mini-set-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; font-size: 12px; }
.mini-set-body b { font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mini-set-body .cell-sub { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mini-set-price { font-weight: 600; }
.mini-set-kp { color: var(--accent); }
/* Таблицы блоков — колонки по содержимому, а не поровну на всю ширину. */
.calc-blocks-bar { display: flex; gap: 12px; align-items: stretch; flex-wrap: wrap; margin-top: 16px; }
.calc-blocks-bar .calc-blocks-state { flex: 1 1 420px; margin-top: 0; }
.calc-blocks-table { width: auto; }
.table.compact.calc-blocks-table input.b-name { width: 260px; }
.table.compact.calc-blocks-table input.b-len, .table.compact.calc-blocks-table input.b-wid,
.table.compact.calc-blocks-table input.b-hei { width: 96px; }
.table.compact.calc-blocks-table input.b-cnt { width: 72px; }
/* Свёрнутый блок со шапкой карточки: стрелка, название и пояснение — слева
   подряд, а не разнесены по краям (`.card-head` раздвигает детей). */
summary.card-head.fold-head { justify-content: flex-start; margin-bottom: 0; }
summary.card-head.fold-head > .cell-sub:last-child { margin-left: auto; }
/* «Форма — значения с прошлого расчёта» — в конце строки параметров, чтобы
   не разрывать её посередине. */
.calc-f-memory { order: 10; }
.calc-blocks-table td, .calc-blocks-table th { padding-right: 10px; }
.msgr-ava img { position: absolute; inset: 0; width: 100%; height: 100%; border-radius: 50%;
  object-fit: cover; }


/* ── Большие экраны (владелец 06.10) ─────────────────────────────────────
   Содержимое — во всю ширину, но строка текста шире ~110 знаков не
   читается, а поле ввода на 2000px выглядит как ошибка вёрстки. */
.card-note, .page-lead, .help, .lead { max-width: 110ch; }
.field > input:not([type=checkbox]):not([type=radio]), .field > select,
.field > textarea { max-width: 960px; }
@media (min-width: 1800px) {
  .content { padding: 24px 32px 64px; }
  /* Карточка клиента: переписка — не шире удобного для чтения, поля слева
     раскладываются в две колонки вместо одной длинной ленты. */
  .client-grid { grid-template-columns: minmax(0, 1fr) minmax(560px, 900px); }
  /* Две колонки СЕТКОЙ, а не CSS-колонками: у колонки полей своя
     прокрутка с высотой экрана, и CSS-колонки при такой высоте уходили
     вбок новыми колонками — прокрутить к полям было нельзя (владелец
     06.10 на большом мониторе). Сетка растёт вниз и прокручивается. */
  .col-fields { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
    align-content: start; align-items: start; }
  .col-fields > .card { margin-bottom: 0; }
  /* «Сообщения»: чаты слева чуть шире — помещается больше текста строки. */
  .msgs-page { grid-template-columns: minmax(320px, 420px) minmax(0, 1fr); }
  /* Настройки: карточки подразделов в две колонки, а не узкой лентой в
     левой половине экрана. */
  .set-screen { max-width: none; }
  .set-section { columns: 2 560px; column-gap: 16px; }
  .set-section > .set-section-head { column-span: all; }
  .set-section > .set-card { break-inside: avoid; }
}
/* Звезда «отслеживать» в окошке и в строке чата (владелец 06.10). */
.msgr-star.is-on, .msgr-row-star.is-on { color: var(--warn); }
.msgr-row { position: relative; }
.msgr-row-star { position: absolute; left: 42px; top: 6px; width: 20px; height: 20px; padding: 0;
  border: 0; border-radius: 50%; background: var(--bg-panel); color: var(--text-faint);
  font-size: 12px; line-height: 20px; cursor: pointer; display: none; z-index: 1; }
.msgr-row:hover .msgr-row-star { display: block; }
/* Чат в окне мессенджера: лента на фоне чуть темнее пузырей. */
body.embed-chat .feed { background: var(--bg); padding: 8px 10px; }
body.embed-chat .feed-card { padding: 0; }
body.embed-chat .composer { padding: 8px 10px 10px; margin-top: 0; }
body.embed-chat .feed-card > .card-head { padding: 6px 10px; margin: 0; }

/* НЕВЫСОКОЕ ОКНО И ОКОШКО МЕССЕНДЖЕРА (владелец 06.10: «из мессенджера не
   получается отправить отредактированное касание»). Окно «Отправить
   клиенту» занимало 76% высоты, и шапка с поиском, вкладками и нижней
   полосой съедали почти всё: списку касаний оставалось ~80px, кнопку
   «Отправить…» у касания перекрывала полоса «Отправить выбранные». Здесь
   окно — во всю высоту и прокручивается целиком, а кнопки отправки
   прилипают к низу и видны всегда. */
@media (max-height: 760px) {
  .overlay { padding: 8px; align-items: stretch; }
  .overlay-box { max-height: calc(100vh - 16px); overflow-y: auto; padding: 12px; }
  .overlay-box > * { flex-shrink: 0; }
  .overlay-box .touch-grid, .overlay-box .lib-list, .dry-run .dr-chat { max-height: none; overflow: visible; }
  .overlay-box .composer-foot { position: sticky; bottom: -12px; z-index: 2; margin: 8px -12px -12px;
    padding: 8px 12px; background: var(--bg-panel); border-top: 1px solid var(--line); }
  #touch-order-note { display: none; }
}
body.embed-chat .overlay { padding: 8px; align-items: stretch; }
body.embed-chat .overlay-box { max-height: calc(100vh - 16px); overflow-y: auto; padding: 12px; }
body.embed-chat .overlay-box > * { flex-shrink: 0; }
body.embed-chat .overlay-box .touch-grid, body.embed-chat .overlay-box .lib-list,
body.embed-chat .dry-run .dr-chat { max-height: none; overflow: visible; }
body.embed-chat .overlay-box .composer-foot { position: sticky; bottom: -12px; z-index: 2;
  margin: 8px -12px -12px; padding: 8px 12px; background: var(--bg-panel);
  border-top: 1px solid var(--line); }
body.embed-chat #touch-order-note { display: none; }

/* ── КП и схемы клиента — окно у поля ответа (владелец 06.10) ─────────────
   Плитки с миниатюрами: КП узнают по первой странице, схему — по рисунку.
   Номер на плитке — очередь отправки, как у касаний. */
.ss-set + .ss-set { margin-top: 14px; }
.ss-set-head { display: flex; align-items: baseline; gap: 6px; margin-bottom: 6px; font-size: 13px; }
.ss-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; }
.ss-tile { position: relative; display: flex; flex-direction: column; gap: 4px; padding: 6px;
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--bg-raised);
  cursor: pointer; transition: border-color .12s; }
.ss-tile:hover { border-color: var(--text-dim); }
.ss-tile.is-picked { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.ss-thumb { display: block; aspect-ratio: 4 / 3; border-radius: 6px; overflow: hidden; background: var(--bg-subtle); }
.ss-thumb img { display: block; width: 100%; height: 100%; object-fit: contain; }
.ss-nothumb { display: grid; place-items: center; height: 100%; color: var(--text-faint); font-size: 12px; }
.ss-cap { font-size: 12px; line-height: 1.3; color: var(--text-dim); }
.ss-cap b { color: var(--text); font-weight: 600; }
.ss-sent { font-size: 11px; color: var(--warn); }
.ss-num { position: absolute; top: -7px; left: -7px; width: 24px; height: 24px; border-radius: 50%;
  background: var(--accent); color: var(--accent-ink); display: none; place-items: center;
  font-size: 13px; font-weight: 600; }
.ss-tile.is-picked .ss-num { display: grid; }
.ss-open { position: absolute; top: 10px; right: 10px; width: 24px; height: 24px; border-radius: 50%;
  display: grid; place-items: center; background: var(--bg-panel); border: 1px solid var(--line);
  color: var(--text-dim); font-size: 12px; text-decoration: none; }
.ss-open:hover { color: var(--text); border-color: var(--line-strong); }
.ss-none { margin: 0; }

/* ── Маленькое окошко мессенджера — меньше обвязки (владелец 06.10: «слишком
   много места занимает интерфейс, минимизировать иконки») ─────────────────
   Шапка — одна строка с иконками 28px; в открытом чате — только ← имя ☆ ⤢ ×.
   Полоса вкладок над лентой — только когда каналов больше одного: «Черновик»
   остаётся в развёрнутой карточке (⤢). Под полем ответа — строка, только если
   в ней есть что сказать (выбор канала, очередь касаний, файлы). */
.msgr-head { padding: 4px 6px 4px 10px; gap: 2px; min-height: 40px; }
.msgr-head .icon-btn { width: 28px; height: 28px; padding: 0; font-size: 14px;
  display: inline-flex; align-items: center; justify-content: center; }
.msgr-tools { gap: 0; }
.msgr-panel.in-chat .msgr-list-only { display: none; }
.msgr-search { margin: 8px 10px; }
body.embed-chat #draft-mode { display: none; }
body.embed-chat .feed-card > .card-head:not(:has(.tab[data-channel])) { display: none; }
body.embed-chat .feed-card > .card-head { padding: 4px 8px; }
body.embed-chat .feed-tabs .tab { padding: 2px 10px; font-size: 12px; }
body.embed-chat .composer { padding: 6px 8px 8px; }
body.embed-chat .composer-bar { gap: 0; padding: 3px 3px 3px 4px; }
body.embed-chat .composer-bar textarea { min-height: 32px; padding: 6px 4px; }
body.embed-chat .cmp-btn { width: 30px; height: 32px; }
body.embed-chat .cmp-btn svg { width: 18px; height: 18px; }
body.embed-chat .cmp-send { width: 34px; height: 34px; }
body.embed-chat .composer-hint, body.embed-chat .composer-sub > .pill { display: none; }
body.embed-chat .composer-sub:not(:has(select)):not(:has(.cell-sub:not(:empty):not(.composer-hint))) {
  display: none; }
/* Окошко шириной 400px попадает под правила телефона (≤640px): кнопки по
   44px под палец и лента не выше 70% экрана. На компьютере с мышью это
   только раздувало обвязку и оставляло пустую полосу под полем ответа. */
body.embed-chat .feed { max-height: none; }
@media (pointer: fine) {
  body.embed-chat button, body.embed-chat .btn, body.embed-chat select,
  body.embed-chat input:where(:not([type=checkbox], [type=radio], [type=range], [type=file], [type=hidden])) {
    min-height: 0; }
}
/* Канал у пузыря нужен, только когда каналов несколько. */
.feed-one-channel .msg-chan { display: none; }

/* Звезда «в быстрые ответы» у касания и фразы — везде, откуда их отправляют
   (владелец 06.10). Пустая — бледная, отмеченная — тёплая. */
.quick-star { flex: none; width: 26px; height: 26px; padding: 0; border: 0; border-radius: 50%;
  background: none; color: var(--text-faint); font-size: 16px; line-height: 26px; cursor: pointer; }
.quick-star:hover { color: var(--warn); background: var(--bg-hover); }
.quick-star.is-on { color: var(--warn); }
.lib-row-head .quick-star { margin-left: auto; }
.touch-card > .quick-star { position: absolute; top: 6px; right: 6px; }
.touch-card > .quick-star ~ h3 { padding-right: 24px; }

/* ── Канбан по высоте экрана (владелец 06.10: «на канбане нет слайдера, как
   минимум на большом экране») ────────────────────────────────────────────────
   Доска росла по самой длинной колонке, и полоса прокрутки вбок оказывалась
   под нижним краем экрана. Теперь доска — до низа экрана (верх меряет
   app.js → --board-top), колонки прокручиваются внутри, полоса доски видна
   всегда — и на Mac, где системная прячется до начала прокрутки. Телефон
   (≤640px) — как был: колонки во всю ширину с прилипанием. */
/* Не ниже 78% экрана (владелец 06.10, маленький экран: «основную часть
   занимают фильтры, вниз не пролистать, только маленькое окошко»): если
   фильтры высокие, страница прокручивается вниз, и доска занимает почти весь
   экран; на большом экране — по-прежнему ровно до низа. */
#board.is-fit { height: max(520px, 78vh, calc(100vh - var(--board-top, 220px) - 16px));
  align-items: stretch; padding-bottom: 6px; }
#board.is-fit .board-col { max-height: 100%; }
/* Прокрутка колонки, дойдя до конца, переходит на страницу: с «contain»
   колесо над доской крутило только колонку, и страницу вниз было не
   пролистать (владелец 06.10, маленький экран). */
#board.is-fit .board-cards { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
#board.is-fit .board-cards > * { flex-shrink: 0; }   /* карточки не сплющиваются */
.content:has(#board.is-fit) { padding-bottom: 16px; }
#board.is-fit::-webkit-scrollbar { height: 12px; }
#board.is-fit::-webkit-scrollbar-track { background: var(--bg-subtle); border-radius: 6px; }
#board.is-fit::-webkit-scrollbar-thumb { background: var(--line-strong); border-radius: 6px;
  border: 2px solid var(--bg-subtle); }
#board.is-fit::-webkit-scrollbar-thumb:hover { background: var(--text-faint); }
@supports not selector(::-webkit-scrollbar) {
  #board.is-fit { scrollbar-color: var(--line-strong) var(--bg-subtle); }
}

/* Окна панели вместо системных (владелец 06.10): uiConfirm/uiAlert/uiPrompt. */
.ui-dialog { z-index: 90; align-items: flex-start; padding-top: 18vh; }
.ui-dialog-box { width: min(460px, 100%); gap: 12px; padding: 18px 18px 14px; }
.ui-dialog-title { margin: 0; font-size: 15px; }
.ui-dialog-text { margin: 0; white-space: pre-wrap; line-height: 1.45; }
.ui-dialog-input { width: 100%; }
.ui-dialog-actions { display: flex; justify-content: flex-end; gap: 8px; }
.ui-dialog-choices { display: flex; flex-direction: column; gap: 6px; }
.ui-dialog-choice { display: flex; justify-content: space-between; gap: 12px; text-align: left; }
/* Несохранённые правки карточки — черновиком (вместо «Покинуть сайт?»). */
.card-draft { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 8px 12px;
  margin-bottom: 12px; border: 1px solid var(--warn); border-radius: var(--radius);
  background: var(--warn-bg); font-size: 13px; }
/* Итог расчёта, пока считается новый (quotes.js recalc). */
#calc-result.is-busy { opacity: .55; transition: opacity .15s; }

/* Сообщение переписки → фразы, медиатека, касание (07.10): меню по правой
   кнопке, выбранные сообщения и строка «Выбрано: N · Добавить касание». */
.feed-menu { position: fixed; z-index: 80; min-width: 220px; display: flex;
  flex-direction: column; padding: 4px; background: var(--bg-raised);
  border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow); }
.feed-menu[hidden] { display: none; }
.feed-menu button { text-align: left; border: 0; background: none; padding: 7px 10px;
  border-radius: 6px; color: var(--text); cursor: pointer; font: inherit; }
.feed-menu button:hover, .feed-menu button:focus-visible { background: var(--bg-hover); }
.feed.is-picking .msg { cursor: pointer; }
.msg.is-picked { outline: 2px solid var(--accent); outline-offset: 2px; }
.msg.is-picked::after { content: "✓"; position: absolute; top: -8px; right: -8px; width: 18px;
  height: 18px; border-radius: 50%; background: var(--accent); color: var(--accent-ink);
  font-size: 11px; line-height: 18px; text-align: center; }
.feed-pickbar { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px;
  padding: 6px 10px; margin: 4px 0; border-radius: var(--radius); font-size: 12.5px;
  background: var(--accent-soft); }
.feed-pickbar > span { flex: 1; min-width: 0; }


/* ── Фильтр: пресеты и условия (владелец 09.10) ─────────────────────────────
   Один ряд на доску и мессенджер (`fbar*` в app.js): пресеты — плашками
   «в одно касание», условия — плашками с крестиком, правка — в окошке.
   Выбранное — заливкой акцента, остальное приглушено: в покое ряд не
   пестрит. */
.fbar { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; font-size: 12.5px; }
.board-bar .fbar { margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--line); }
.fbar-presets { display: flex; gap: 4px; align-items: center; max-width: 100%; min-width: 0; }
.fbar-presets-scroll { display: flex; gap: 4px; align-items: center; min-width: 0;
  overflow-x: auto; scrollbar-width: thin; padding: 1px; }
.fbar-preset, .fbar-more {
  flex: none; height: 28px; padding: 0 12px; border-radius: 999px; white-space: nowrap;
  border: 1px solid var(--line); background: none; color: var(--text-dim); font-size: 12.5px;
  cursor: pointer; transition: background-color .15s ease-out, color .15s ease-out,
    border-color .15s ease-out, transform .1s ease-out;
}
.fbar-preset:hover, .fbar-more:hover { color: var(--text); border-color: var(--line-strong);
  background: var(--bg-hover); }
.fbar-preset:active, .fbar-more:active, .fbar-add:active { transform: scale(.97); }
.fbar-preset.is-on { color: var(--text); border-color: var(--accent); background: var(--accent-soft); }
.fbar-more { width: 28px; padding: 0; display: inline-flex; align-items: center;
  justify-content: center; letter-spacing: .05em; }
.fbar-rules { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; min-width: 0; }
.fbar-token { display: inline-flex; align-items: stretch; height: 28px; max-width: 380px; min-width: 0;
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--bg-subtle); }
.fbar-token-main { min-width: 0; border: 0; background: none; padding: 0 4px 0 10px;
  color: var(--text); font-size: 12.5px; white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; cursor: pointer; }
.fbar-token-main:hover { color: var(--accent); }
.fbar-token-k { color: var(--text-dim); }
.fbar-token-x { flex: none; width: 24px; border: 0; background: none; color: var(--text-faint);
  font-size: 14px; line-height: 1; cursor: pointer; border-radius: 0 var(--radius) var(--radius) 0; }
.fbar-token-x:hover { color: var(--err); background: var(--bg-hover); }
.fbar-add { height: 28px; padding: 0 10px; border: 1px dashed var(--line-strong);
  border-radius: var(--radius); background: none; color: var(--text-dim); font-size: 12.5px;
  cursor: pointer; transition: color .15s ease-out, border-color .15s ease-out, transform .1s ease-out; }
.fbar-add:hover { color: var(--accent); border-color: var(--accent); }
.fbar-rules button.link { font-size: 12.5px; }
/* Узкое место (окошко мессенджера): пресеты строкой с прокруткой, условия
   под ними. */
.fbar-compact { flex-direction: column; align-items: stretch; gap: 6px; }
.fbar-compact .fbar-token { max-width: 100%; }
.fbar-compact .fbar-preset, .fbar-compact .fbar-more { height: 26px; font-size: 12px; }
.fbar-compact .fbar-more { width: 26px; }
.fbar-compact .fbar-token, .fbar-compact .fbar-add { height: 26px; font-size: 12px; }

.fbar-pop { position: fixed; z-index: 75; width: min(320px, calc(100vw - 16px));
  max-height: min(460px, 72vh); display: flex; flex-direction: column; gap: 8px; padding: 10px;
  background: var(--bg-panel); border: 1px solid var(--line-strong); border-radius: 10px;
  box-shadow: var(--shadow); font-size: 13px; transform-origin: top left;
  animation: fbar-in .14s ease-out; }
@keyframes fbar-in { from { opacity: 0; transform: translateY(-4px) scale(.98); } }
@media (prefers-reduced-motion: reduce) {
  .fbar-pop { animation: none; }
  .fbar-preset, .fbar-more, .fbar-add { transition: none; }
}
.fbar-pop-head { display: flex; align-items: center; gap: 6px; font-weight: 600; }
.fbar-pop-head small { margin-left: auto; font-weight: 400; font-size: 11.5px; color: var(--text-faint); }
.fbar-back { border: 0; background: none; color: var(--text-dim); padding: 0 6px; font-size: 15px;
  line-height: 1.4; border-radius: 4px; cursor: pointer; }
.fbar-back:hover { color: var(--text); background: var(--bg-hover); }
.fbar-search { width: 100%; }
.fbar-ops { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; overflow: hidden;
  border: 1px solid var(--line); border-radius: var(--radius); }
.fbar-ops button { border: 0; border-left: 1px solid var(--line); background: none; padding: 5px 4px;
  font-size: 12px; color: var(--text-dim); cursor: pointer; white-space: nowrap; }
.fbar-ops button:first-child { border-left: 0; }
.fbar-ops button:hover { color: var(--text); background: var(--bg-hover); }
.fbar-ops button.is-on { color: var(--text); background: var(--accent-dim); }
.fbar-values { display: flex; flex-direction: column; gap: 6px; min-height: 0; flex: 1 1 auto; }
.fbar-values[hidden] { display: none; }
.fbar-list { display: flex; flex-direction: column; gap: 1px; min-height: 0; flex: 1 1 auto;
  max-height: 300px; overflow-y: auto; margin: 0 -4px; padding: 0 4px; }
.fbar-opt { display: flex; align-items: center; gap: 8px; padding: 5px 6px; border-radius: 5px;
  cursor: pointer; color: var(--text); }
.fbar-opt:hover { background: var(--bg-hover); }
.fbar-opt input { margin: 0; flex: none; }
.fbar-pick { display: flex; align-items: center; justify-content: space-between; gap: 8px;
  width: 100%; border: 0; background: none; padding: 6px 8px; border-radius: 5px;
  color: var(--text); text-align: left; cursor: pointer; font-size: 13px; }
.fbar-pick:hover { background: var(--bg-hover); }
.fbar-pick small { color: var(--accent); font-size: 11px; }
.fbar-group { padding: 8px 6px 2px; font-size: 10.5px; text-transform: uppercase;
  letter-spacing: .05em; color: var(--text-faint); }
.fbar-group:first-child { padding-top: 2px; }
.fbar-empty { margin: 6px; color: var(--text-faint); font-size: 12px; }
.fbar-pop-foot { display: flex; justify-content: space-between; align-items: center;
  padding-top: 8px; border-top: 1px solid var(--line); }
.fbar-preset-row { display: flex; align-items: center; gap: 2px; border-radius: 6px; padding-right: 2px; }
.fbar-preset-row:hover { background: var(--bg-hover); }
.fbar-preset-row.is-on { background: var(--accent-soft); }
.fbar-preset-name { flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: flex-start;
  gap: 1px; border: 0; background: none; padding: 6px 8px; color: var(--text); text-align: left;
  cursor: pointer; }
.fbar-preset-name span { font-weight: 500; }
.fbar-preset-name small, .fbar-preset-name span { max-width: 100%; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.fbar-preset-name small { color: var(--text-faint); font-size: 11px; }
.fbar-save { display: flex; gap: 6px; padding-top: 8px; border-top: 1px solid var(--line); }
.fbar-save input { flex: 1; min-width: 0; }
.fbar-save .fbar-empty { margin: 0; }

/* ── Документы (владелец 09.10) ───────────────────────────────────────────────
   «Документы»: шаблоны, реквизиты, нумерация, коды полей; в карточке —
   блок «Документы» со списком выпущенного. */
.doc-tpl-list, .doc-counter-list { display: flex; flex-direction: column; gap: 8px; }
.doc-tpl, .doc-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 10px 12px; border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--bg-subtle); }
.doc-tpl-main, .doc-row-main { flex: 1 1 260px; min-width: 0; display: flex;
  flex-direction: column; gap: 2px; }
.doc-tpl-title, .doc-row-title { font-weight: 600; }
.doc-tpl-meta, .doc-row-meta { font-size: 12px; color: var(--text-dim); }
.doc-tpl-warn, .doc-row-warn { font-size: 12px; color: var(--warn); }
.doc-tpl-actions, .doc-row-actions { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.doc-row.is-void { opacity: .6; }
.doc-row.is-void .doc-row-title { text-decoration: line-through; }
.doc-tpl-new { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line); }
.doc-form-grid { display: grid; gap: 10px 14px; margin: 8px 0 10px;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); }
.doc-form-grid label { display: flex; flex-direction: column; gap: 4px; font-size: 12px;
  color: var(--text-dim); }
.doc-form-grid input, .doc-form-grid select { width: 100%; }
.doc-counter { display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 8px 12px; border: 1px solid var(--line); border-radius: var(--radius); }
.doc-counter-title { flex: 1 1 200px; font-weight: 600; }
.doc-counter-next { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-dim); }
.doc-counter-next input { width: 120px; font-family: var(--mono); }
.doc-counter-mode button { border: 0; border-right: 1px solid var(--line); background: none;
  padding: 6px 10px; font-size: 12.5px; color: var(--text-dim); cursor: pointer; }
.doc-counter-mode button:last-child { border-right: 0; }
.doc-counter-mode button:hover { color: var(--text); }
.doc-counter-mode button.is-active { background: var(--accent-dim); color: var(--text); }
.doc-codes-client { display: flex; gap: 6px; }
.doc-codes-client input { width: 200px; }
#doc-codes-q { flex: 1 1 240px; max-width: 360px; }
.doc-codes-group { margin-top: 12px; }
.doc-codes-group[hidden], .doc-code[hidden] { display: none; }
.doc-codes { display: flex; flex-direction: column; }
.doc-code { display: grid; grid-template-columns: minmax(160px, 1.2fr) minmax(180px, 1.4fr) minmax(0, 1fr) auto;
  gap: 10px; align-items: center; padding: 5px 4px; border-bottom: 1px solid var(--line);
  font-size: 13px; }
.doc-code-token { font-family: var(--mono); font-size: 12px; color: var(--accent);
  overflow-wrap: anywhere; }
.doc-code-example { color: var(--text-dim); font-size: 12px; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
@media (max-width: 720px) {
  .doc-code { grid-template-columns: 1fr auto; }
  .doc-code-token, .doc-code-example { grid-column: 1 / -1; }
}
.docs-new { margin-left: auto; display: inline-flex; gap: 6px; align-items: center; }
.docs-new select { max-width: 240px; }
#docs-rows { display: flex; flex-direction: column; gap: 8px; }

/* Поля формы в общем окне (`uiDialog({fields})`): обязательные поля при
   переводе на стадию (владелец 09.10). */
.ui-dialog-fields { display: flex; flex-direction: column; gap: 10px; margin: 4px 0 12px; }
.ui-dialog-field { display: flex; flex-direction: column; gap: 4px; font-size: 12.5px;
  color: var(--text-dim); }
.ui-dialog-field .ui-dialog-control { width: 100%; font-size: 13px; }
.ui-dialog-field.is-invalid { color: var(--err); }
.ui-dialog-field.is-invalid .ui-dialog-control { border-color: var(--err); }
/* Анкета для договора в блоке «Документы». */
.docs-form { display: flex; align-items: center; gap: 8px 12px; flex-wrap: wrap; padding: 8px 0 12px;
  margin-bottom: 4px; border-bottom: 1px solid var(--line); }
.docs-form:empty { display: none; }
.docs-form-title { font-weight: 600; }
.docs-form-state { color: var(--text-dim); font-size: 12.5px; }
.docs-form-state.is-done { color: var(--ok); }
.docs-form-actions { display: inline-flex; gap: 6px; flex-wrap: wrap; margin-left: auto; }
.doc-assets { display: flex; gap: 14px; flex-wrap: wrap; }
.doc-asset { display: flex; flex-direction: column; gap: 8px; align-items: flex-start; }
.doc-asset-img { width: 200px; height: 120px; display: flex; align-items: center; justify-content: center;
  border: 1px dashed var(--line-strong); border-radius: var(--radius); background: var(--bg-subtle); }
.doc-asset-img img { max-width: 92%; max-height: 92%; }

/* Оценка черновиков (владелец 13.10: «готов один раз оценить ~100 пар»). */
.rt-head { font-size: 15px; margin-bottom: 10px; }
.rt-context { display: flex; flex-direction: column; gap: 4px; margin-bottom: 14px;
  max-height: 260px; overflow-y: auto; padding: 8px; border: 1px solid var(--line); border-radius: 8px; }
.rt-line { font-size: 13px; color: var(--text-dim); white-space: pre-wrap; }
.rt-line.is-in { color: var(--text); }
.rt-at { color: var(--text-faint); margin-right: 8px; font-size: 12px; }
.rt-pair { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 16px; margin-bottom: 12px; }
.rt-pair h3 { font-size: 13px; margin: 0 0 6px; color: var(--text-dim); font-weight: 600; }
.rt-bubble { white-space: pre-wrap; font-size: 14px; padding: 8px 10px; border-radius: 10px; margin-bottom: 6px;
  background: var(--bg-raised); border: 1px solid var(--line); }
.rt-bubble.agent { border-color: var(--draft); background: var(--draft-bg); }
.rt-bubble.owner { border-color: var(--ok); background: var(--ok-bg); }
.rt-bubble.empty { color: var(--text-faint); }
#rt-note { width: 100%; margin-bottom: 10px; }
.rt-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.rt-stats { display: flex; flex-wrap: wrap; gap: 16px; margin-bottom: 10px; font-size: 14px; }
.rt-stat b { font-size: 18px; }
