/* Пайплайн — стили MVP.
   Значения взяты из design/HANDOFF.md (раздел Design Tokens), чтобы рабочая
   система и прототип не разъезжались визуально. Правим здесь — сверяемся там. */

:root {
  --bg: #eff3f6;
  --surface: #ffffff;
  --soft: rgba(22, 48, 58, 0.045);
  --line: #eef3f6;
  --line-2: #e2eaee;
  --field: #dbe5ea;

  --text: #16242b;
  --text-2: #35505c;
  --text-3: #46626e;
  --muted: #6b8592;
  --muted-2: #94a9b2;

  --accent: #0f766e;
  /* Мягкий акцент: подложка пузыря сообщения, чипов и тегов.
     Объявлен 2026-09-10 — до этого на него ссылались десять правил, а самой
     переменной не было: браузер считал её пустой, и всё это рисовалось
     прозрачным. Заметно стало на экране воронок, когда вокруг пузыря убрали
     лишнюю рамку и подложке стало нечем себя показать. */
  --accent-soft: #e6f4f2;
  --accent-dark: #0b5c56;
  --accent-500: #17a396;
  --accent-700: #14958a;

  --danger: #b42318;
  --danger-bg: rgba(180, 35, 24, 0.1);
  --warn: #8a6208;
  --warn-bg: #fef0c7;

  /* Ширина строки поиска и зарезервированной под неё зоны в шапке.
     Одна переменная на оба места — см. .head. */
  --gs-w: 400px;

  --r-sm: 8px;
  --r-md: 12px;
  --r-lg: 16px;
  --r-xl: 20px;

  --shadow-sm: 0 12px 26px -20px rgba(22, 48, 58, 0.55), inset 0 1px 0 #ffffff;
  --shadow-md: 0 20px 40px -26px rgba(22, 48, 58, 0.6), inset 0 1px 0 #ffffff;
  --shadow-lg: 0 28px 52px -26px rgba(22, 48, 58, 0.65), inset 0 1px 0 #ffffff;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

body {
  min-height: 100vh;
  font: 400 14px/1.45 Manrope, "Segoe UI", system-ui, sans-serif;
  color: var(--text);
  background:
    radial-gradient(1100px 520px at 78% -12%, #d8ece9 0%, rgba(216, 236, 233, 0) 62%),
    radial-gradient(760px 420px at 8% 108%, #dde7ee 0%, rgba(221, 231, 238, 0) 60%),
    var(--bg);
}

h1, h2, h3, h4 { font-weight: 800; letter-spacing: -0.03em; line-height: 1.14; }
h2 { font-size: 27px; }
h3 { font-size: 23px; }
h4 { font-size: 19px; }

::selection { background: rgba(15, 118, 110, 0.18); }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.scroll::-webkit-scrollbar { width: 9px; height: 9px; }
.scroll::-webkit-scrollbar-thumb { background: #c3d1d8; border-radius: var(--r-sm); }
.scroll::-webkit-scrollbar-track { background: transparent; }

/* Атрибут `hidden` обязан прятать — всегда.
 *
 * Браузер задаёт `[hidden] { display: none }` в своей таблице, и ЛЮБОЕ правило
 * автора с `display` его перебивает. Ошибка получается бесшумной: скрипт
 * ставит `hidden`, свойство узла честно становится true, а элемент остаётся на
 * экране. Так у всплывающего окна переписки не работал крестик: `.chat-pop`
 * объявлен `display: flex`, и окно висело поверх карточки постоянно
 * (замечание владельца 2026-09-03).
 *
 * Поэтому правило общее и с `!important`: без него оно проиграет тому же
 * `display` в классе, а перечислять руками каждый прячущийся элемент — значит
 * однажды забыть. Противоречия здесь нет: «скрыт и при этом показан» —
 * бессмысленное состояние.
 */
[hidden] { display: none !important; }

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

/* Каркас: сайдбар стоит на месте, прокручивается только рабочая область.
   Раньше прокручивался весь документ, и на окне уже 1358px сайдбар уезжал
   влево вместе с содержимым — навигация исчезала ровно тогда, когда таблица
   не влезала и до неё надо было доскроллить. */
.app { display: flex; height: 100vh; overflow: hidden; }

.sidebar {
  flex: none;
  display: flex; flex-direction: column; gap: 14px;
  /* 292, а не 266 (замечание владельца 2026-09-07: «чутка не влазит левая
     панель»): длинные пункты с счётчиком упирались в край. */
  width: 292px; height: 100%; padding: 18px 14px;
  overflow-y: auto;
  background: linear-gradient(178deg, #143039 0%, #0e242c 62%, #0b1d24 100%);
  color: #e8f1f3;
  /* Тень отделяет сайдбар от светлой рабочей области: без неё тёмная полоса
     выглядит приклеенной к краю экрана, а не лежащей поверх. */
  box-shadow: 14px 0 40px -22px rgba(11, 29, 36, 0.55);
  z-index: 2;
}

.brand { display: flex; align-items: center; gap: 9px; padding: 4px 8px 10px; }
.brand-dot {
  width: 11px; height: 11px; border-radius: 999px;
  background: #5eead4; animation: pulse 1.8s ease-in-out infinite;
}
.brand-name { font-weight: 800; font-size: 17px; letter-spacing: -0.02em; }
@keyframes pulse { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: 0.42; transform: scale(0.8); } }

.nav { display: flex; flex-direction: column; gap: 3px; }
.nav a {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 11px; border-radius: 11px;
  color: #9db6bf; font-size: 14px; font-weight: 600; text-decoration: none;
  transition: background 0.15s, color 0.15s;
}
/* Полоска слева: в прототипе она есть у каждого пункта и подсвечивается у
   активного. Держим её всегда, иначе при переключении текст дёргается на 13px. */
.nav a::before {
  content: ""; flex: none; width: 3px; height: 19px; border-radius: 2px;
  background: transparent; transition: background 0.15s;
}
.nav a:hover { color: #e8f1f3; background: rgba(255, 255, 255, 0.05); }
.nav a.on {
  color: #ffffff;
  background: linear-gradient(120deg, var(--accent), var(--accent-500));
  box-shadow: 0 12px 22px -12px rgba(15, 118, 110, 0.9);
}
.nav a.on::before { background: #ffffff; }
/* Значок пункта. Размер задан жёстко: у svg без него ширина берётся из
   viewBox, и в свёрнутой полосе значки разъезжаются на пиксель-два — это
   заметно, когда они стоят столбиком. */
.nav-ic { flex: none; display: inline-flex; width: 18px; height: 18px; }
.nav-ic svg {
  width: 18px; height: 18px;
  fill: none; stroke: currentColor; stroke-width: 1.7;
  stroke-linecap: round; stroke-linejoin: round;
}
.nav-lb { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nav .count { margin-left: auto; font-size: 12px; font-weight: 700; opacity: 0.75; }

/* Кнопка сворачивания. Селектор нарочно с .brand: класс состояния висит на
   .app, и правило по одному имени класса поймало бы сам контейнер приложения —
   он стал бы блоком 30x30, а рабочая область схлопнулась бы в ноль. Проверено
   на живом экране 2026-09-04.

   Вид как у колокольчика рядом — это одна и та же
   полка мелких действий в шапке меню, и разъехавшийся вид читался бы как
   разное поведение. */
.brand .nav-min {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; padding: 0; margin-left: 4px;
  border: 0; border-radius: 999px; cursor: pointer;
  color: #9db6bf; background: rgba(255, 255, 255, 0.06);
  transition: background 0.15s, color 0.15s;
}
.brand .nav-min:hover { color: #e8f1f3; background: rgba(255, 255, 255, 0.16); }
.brand .nav-min svg {
  width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round;
}

/* ── свёрнутое меню ──────────────────────────────────────────────────────

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

   Ширина 68px — это 18px значка плюс поля: меньше делает попадание мышью
   лотереей, больше начинает выглядеть недорисованной колонкой. */
.app.side-min .sidebar { width: 68px; padding-left: 10px; padding-right: 10px; }
/* Шапка столбиком: колокольчик остаётся на месте и в полосе. Прятать его
   нельзя — на нём счётчик непрочитанного, а это единственное, что зовёт
   человека обратно к работе; втроём в ряд они в 68px не помещаются. */
.app.side-min .brand { flex-direction: column; gap: 8px; padding: 4px 0 12px; }
.app.side-min .bell { margin-left: 0; }
.app.side-min .brand-name,
.app.side-min .nav-lb,
.app.side-min .nav .count,
.app.side-min .me-txt,
.app.side-min .me-gear,
.app.side-min #logout { display: none; }
/* Полоска-указатель у активного пункта в полосе не помещается: она съедает
   3px из 18-ти, и значок уезжает из середины. Убираем её вместе с подписью —
   активный пункт и так виден заливкой. */
.app.side-min .nav a { justify-content: center; gap: 0; padding: 9px 0; }
.app.side-min .nav a::before { display: none; }
.app.side-min .me { justify-content: center; padding: 6px 0; }
/* Кнопка остаётся единственным содержимым шапки и встаёт по центру полосы. */
.app.side-min .brand .nav-min { margin-left: 0; }
.nav .count.bad { color: #ffb4a8; opacity: 1; }

.role-box { margin-top: auto; }
.role-list { display: flex; flex-direction: column; gap: 2px; }
.role-list button {
  padding: 7px 12px; border: 0; border-radius: 999px;
  font: inherit; font-size: 13px; font-weight: 600; text-align: left;
  color: #9db6bf; background: transparent; cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
.role-list button:hover { color: #e8f1f3; background: rgba(255, 255, 255, 0.05); }
.role-list button.on { color: #0b1d24; background: #bcdcda; }

/* Рабочая область — собственный контейнер прокрутки. Ниже 1280px колонки не
   сжимаются, а появляется горизонтальная прокрутка: так задано в прототипе. */
.main { flex: 1; min-width: 0; overflow: auto; }
.wrap { min-width: 1280px; padding: 14px 30px 60px; }

/* Заявки из Telegram — исключение: нижнего предела ширины нет.

   Предел 1280px оправдан таблицами (лиды, звонки, пользователи): их колонки
   действительно не сжимаются, и прокрутка вбок лучше каши. Но поток заявок —
   не таблица, а сетка карточек `repeat(auto-fill, minmax(340px, 1fr))`: в
   узком окне ей достаточно положить в ряд две карточки вместо трёх.

   Пока предел действовал и здесь, узкое окно уводило экран за правый край:
   заголовки поджимались, часть карточек оказывалась за прокруткой, и это
   читалось как «поплыли стили» (замечание владельца 2026-09-22). Полоса
   поиска — сосед рабочей области внутри .main, поэтому предел снимается и
   с неё: иначе она распирала бы .main в одиночку. */
.main:has(.rd-screen) > .wrap,
.main:has(.rd-screen) > .topbar { min-width: 0; }

/* ── поиск по системе ───────────────────────────────────────────────────
   Строка в шапке рабочей области, на всех экранах. Замечание владельца
   2026-09-03: «сделать поиск на всех страницах сверху справа, чтобы быстро
   можно было ориентироваться по системе из любого раздела».

   Прилипшая к верху (sticky), а не уезжающая с содержимым: искать чаще всего
   надо, дочитав до середины длинного списка, — то есть ровно тогда, когда
   уехавшая строка уже не видна. Прокручивается здесь .main, поэтому top: 0
   считается от него. */
/* Поиск стоит в ОДНОЙ строке с заголовком экрана и его кнопками, по центру
   между ними. Замечание владельца 2026-09-03: «зачем спуск после поиска —
   поиск по центру, чтобы мы могли всё в один уровень делать».

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

   Поэтому полоса не занимает высоты вовсе (`height: 0`) и не ловит нажатия:
   заголовок слева и кнопки справа рисует сам экран, и перехватывать нажатия по
   ним полосе нечем. Липкость при этом остаётся — искать чаще всего надо,
   дочитав список до середины, когда уехавшая строка уже не видна. */
.topbar {
  position: sticky; top: 0; z-index: 30;
  /* align-items обязателен: у полосы высота 0, а флекс по умолчанию тянет
     дочерние на всю высоту контейнера — то есть в ноль. Строка поиска тогда
     получает нулевую высоту, и значки внутри неё, привязанные к её середине
     (top: 50%), уезжают к верхнему краю поля. Ровно это и было видно
     (замечание владельца 2026-09-03: «съехали иконки»). */
  display: flex; justify-content: center; align-items: flex-start;
  min-width: 1280px; height: 0; padding: 0 30px;
  overflow: visible; pointer-events: none;
}
/* pointer-events возвращается самой строке: полоса вокруг прозрачна для
   нажатий, поле — нет. Отступ сверху ставит строку на уровень заголовка. */
/* Высота задана явно, а не выведена из содержимого: значки внутри позиционируются
   от середины ЭТОГО блока, и любая неопределённость его высоты сдвигает их. */
.gs {
  position: relative; width: 100%; max-width: calc(var(--gs-w) - 20px);
  height: 38px; margin-top: 16px; pointer-events: auto;
}
.gs-ic {
  position: absolute; left: 12px; top: 50%; transform: translateY(-50%);
  font-size: 15px; color: var(--muted); pointer-events: none;
}
/* Тень нужна не для красоты: полоса высоты не занимает, и при прокрутке
   содержимое проезжает ПОД строкой. Без тени она сливается с тем, что под ней,
   и читается как случайная надпись поверх текста. */
.gs input {
  width: 100%; height: 38px; padding: 0 42px 0 33px;
  border-radius: 999px; background: var(--surface);
  box-shadow: 0 10px 22px -14px rgba(22, 48, 58, 0.8);
}
/* Подсказка про «/» гаснет, как только в поле начали печатать: дальше она
   перекрывала бы конец набранного. */
.gs-key {
  position: absolute; right: 12px; top: 50%; transform: translateY(-50%);
  min-width: 17px; padding: 1px 5px; border-radius: 5px;
  font: inherit; font-size: 11px; text-align: center;
  color: var(--muted); background: var(--soft); pointer-events: none;
}
.gs input:focus ~ .gs-key { display: none; }

.gs-drop {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 40;
  width: 100%; max-height: 62vh; overflow-y: auto;
  padding: 6px; border-radius: var(--r-md);
  background: var(--surface); box-shadow: var(--shadow-lg);
}
.gs-group + .gs-group { margin-top: 4px; border-top: 1px solid var(--line); padding-top: 4px; }
.gs-cap {
  display: flex; align-items: baseline; gap: 8px; padding: 6px 9px 4px;
  font-size: 10px; font-weight: 700; letter-spacing: 0.09em;
  text-transform: uppercase; color: var(--muted);
}
/* «Показано 6 из 41» — не украшение: без этой строки шесть находок читаются
   как «всего шесть», и запрос перестают уточнять. */
.gs-more { margin-left: auto; font-size: 10px; font-weight: 600; letter-spacing: 0; text-transform: none; }
.gs-hit {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 2px 8px;
  width: 100%; padding: 7px 9px; border: 0; border-radius: var(--r-sm);
  font: inherit; text-align: left; background: transparent; cursor: pointer;
}
.gs-hit.on { background: #d9f2ef; }
.gs-hit-t { font-size: 13px; font-weight: 600; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gs-hit-s { grid-column: 1 / -1; font-size: 11px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gs-hit .tag { align-self: center; }
.gs-none { padding: 12px 10px; font-size: 12px; line-height: 1.45; color: var(--muted); }

/* Шапка экрана — три зоны: заголовок слева, ПУСТО по центру, действия справа.
   Центр пуст не случайно: там висит строка поиска. Она живёт вне #view (иначе
   теряла бы набранное при каждой перерисовке) и в потоке шапки не участвует —
   значит место под неё надо зарезервировать здесь, иначе действия справа
   налезают на неё на экранах, где их много.

   Ширина центральной зоны и ширина самой строки заданы одной переменной: две
   независимые цифры разъехались бы, и налезание вернулось бы молча. */
.head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--gs-w) minmax(0, 1fr);
  align-items: start; gap: 16px; margin-bottom: 18px;
}
.head > :first-child { min-width: 0; }
.head-cap {
  font-size: 10px; font-weight: 700; letter-spacing: 0.09em;
  text-transform: uppercase; color: var(--muted); margin-bottom: 5px;
}
/* Название вакансии в шапке карточки кандидата — ссылка на саму вакансию.
   Подчёркивание пунктиром, а не сплошное: строка набрана капителью и мелким
   кеглем, сплошная черта под ней читается как помарка. Цвет остаётся
   приглушённым — это подпись, а не заголовок. */
.head-vac { color: inherit; text-decoration: none; border-bottom: 1px dotted var(--muted); }
.head-vac:hover { color: var(--accent-dark); border-bottom-color: var(--accent); }
/* Третья зона сетки. Перенос строк — страховка: на самом полном экране
   (карточка лида) действий четыре, и лучше вторая строка кнопок, чем кнопка,
   уехавшая за край. */
.head-actions {
  grid-column: 3; display: flex; flex-wrap: wrap; gap: 8px;
  align-items: center; justify-content: flex-end;
}

/* ── кнопки, поля, теги ─────────────────────────────────────────────────── */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 9px 18px; border: 0; border-radius: 999px;
  font: inherit; font-size: 14px; font-weight: 600; line-height: 1.2;
  cursor: pointer; white-space: nowrap;
  transition: background 0.15s, box-shadow 0.15s, color 0.15s;
  /* Кнопкой бывает не только <button>: переход на другой экран — это <a class="btn">
     («Воронка продаж», «В колл-центр», «Печать анкет» и ещё десяток мест).
     Без сброса браузер подчёркивает у них подпись, и одна и та же кнопка
     выглядит по-разному в зависимости от того, чем она сделана — замечание
     владельца 2026-09-03. */
  text-decoration: none;
}
.btn:disabled { opacity: 0.42; cursor: default; }
/* Внутренней подсветки сверху здесь НЕТ, и это не упущение.
   `inset 0 1px 0` на кнопке со скруглением 999px рисуется не полоской вверху:
   смещённая на точку копия скругления расходится с исходным сильнее всего там,
   где граница вертикальна, — то есть у левого и правого торца. Получаются два
   светлых серпа, и на глаз это ровно «битые пиксели внутри кнопки» (замечание
   владельца 2026-09-03, дважды: сперва на вкладке «Архив», потом на кнопках).
   Объём кнопке даёт внешнее свечение — оно скруглению не противоречит. */
.btn-primary {
  color: #fff; background: linear-gradient(120deg, var(--accent), var(--accent-500));
  box-shadow: 0 12px 22px -10px rgba(15, 118, 110, 0.85);
}
/* Наведение — тот же градиент под ровной тёмной вуалью. Раньше подменялся
   другим, от --accent-dark к --accent-700: левый край темнел заметно сильнее
   правого, и подсветка читалась пятном («при наведении не ровное цветовое
   выделение», владелец 2026-09-23). */
.btn-primary:hover:not(:disabled) { background: linear-gradient(rgba(4, 40, 38, 0.2), rgba(4, 40, 38, 0.2)), linear-gradient(120deg, var(--accent), var(--accent-500)); }
/* Заблокированный акцентный градиент даже при opacity 0.42 читается как рабочая
   кнопка. Гасим его в плоский серый: кнопка, которая выглядит нажимаемой, но не
   нажимается, — источник «система не работает». */
.btn-primary:disabled { background: #cdd9de; color: #7e929b; box-shadow: none; opacity: 1; }
.btn-secondary {
  color: var(--text-2); background: #fff;
  box-shadow: inset 0 0 0 1.5px var(--field), 0 4px 10px -6px rgba(22, 48, 58, 0.3);
}
.btn-secondary:hover:not(:disabled) { background: #f5f9fa; }
.btn-danger {
  color: #fff; background: linear-gradient(120deg, var(--danger), #d0402f);
  box-shadow: 0 12px 22px -12px rgba(180, 35, 24, 0.8);
}
.btn-sm { padding: 6px 13px; font-size: 13px; }
/* Совсем мелкая — для кнопок внутри карточки диалога, где ряд действий не
   должен отбирать место у самой переписки. */
.btn-xs { padding: 4px 10px; font-size: 12px; }

/* Круглая кнопка набора — трубка вместо слова «Набрать».
   Карточка телефонии узкая и стоит третьей колонкой: кнопка во всю ширину
   съедала строку ради слова, которое трубка говорит без слов. Слово при этом
   не потеряно — оно в подписи для наведения и для чтения с экрана. */
.btn-call {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; padding: 0; border: 0; border-radius: 999px;
  color: #fff; background: linear-gradient(120deg, var(--accent), var(--accent-500));
  /* Без inset-подсветки — см. .btn-primary: на круге она даёт светлые серпы. */
  box-shadow: 0 12px 22px -12px rgba(15, 118, 110, 0.9);
  cursor: pointer; transition: background 0.15s, box-shadow 0.15s, opacity 0.15s;
}
.btn-call:hover:not(:disabled) { background: linear-gradient(rgba(4, 40, 38, 0.2), rgba(4, 40, 38, 0.2)), linear-gradient(120deg, var(--accent), var(--accent-500)); }
.btn-call:disabled { opacity: 0.45; cursor: default; box-shadow: none; }
.btn-call svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 1.9; }

/* Второстепенный набор — произвольный номер. Обводка, а не заливка: две
   одинаково яркие кнопки в одной карточке спорят за то, какая из них главная. */
.btn-call.ghost {
  width: 34px; height: 34px; color: #9dd7cf; background: transparent; box-shadow: none;
  border: 1.5px solid rgba(157, 215, 207, 0.45);
}
.btn-call.ghost:hover:not(:disabled) {
  color: #0e242c; border-color: transparent;
  background: linear-gradient(120deg, #9dd7cf, #7fc9bf);
}

/* Поле «другой номер» на тёмной карточке: общее правило для input светлое,
   поэтому цвета и высота задаются здесь, а не инлайном на каждой перерисовке. */
.dial-any {
  flex: 1; min-width: 0; height: 38px; padding: 0 12px;
  border: 1.5px solid #2b4a55; border-radius: 10px;
  font: inherit; font-size: 14px; letter-spacing: 0.02em;
  color: #e8f1f3; background: #0e242c;
}
.dial-any::placeholder { color: #6f8993; }
.dial-any:focus { outline: none; border-color: var(--accent-500); box-shadow: none; }

.field { display: flex; flex-direction: column; gap: 5px; }
.field label { font-size: 12px; font-weight: 600; color: var(--text-3); }
.field .hint { font-size: 11px; color: var(--muted-2); }
input, select, textarea {
  width: 100%; padding: 9px 12px;
  border: 1.5px solid var(--field); border-radius: var(--r-md);
  font: inherit; font-size: 14px; color: var(--text); background: #fff;
  transition: border-color 0.15s, box-shadow 0.15s;
}
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(15, 118, 110, 0.14);
}
textarea { min-height: 74px; resize: vertical; }
/* Флажок и переключатель — не поля ввода: ширина по содержимому.
   Без этого правила общее `input { width: 100% }` растягивает квадратик на всю
   строку, подпись прижимается к правому краю и переносится. Снаружи это
   выглядит как «вёрстка поехала», а причина в одной строке выше. */
input[type="checkbox"], input[type="radio"] {
  width: 16px; height: 16px; min-width: 16px; flex: none;
  margin: 0; padding: 0; accent-color: var(--accent);
}
/* Выпадающий список — свой контрол, как в прототипе.
   Размеры сняты с `design/kit-data-forms-modals.dc.html`, а не подобраны. */
.dd { position: relative; }
.dd-btn {
  width: 100%; display: flex; align-items: center; gap: 10px;
  padding: 10px 13px; text-align: left;
  border: 1.5px solid var(--field); border-radius: 11px;
  font: inherit; font-size: 14px; color: var(--text); background: #fff;
  cursor: pointer;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.dd-btn:hover { border-color: #c6d5dc; }
.dd-btn:focus-visible {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(15, 118, 110, 0.14);
}
.dd.open .dd-btn { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(15, 118, 110, 0.14); }
.dd-btn:disabled { opacity: 0.45; cursor: default; background: var(--soft); }

.dd-val { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dd-val.ph { color: var(--muted-2); }

/* Шеврон: квадрат 7×7 из двух бордеров, повёрнутый на 45°. */
.dd-arrow {
  flex: 0 0 auto; width: 7px; height: 7px;
  border-right: 2px solid var(--muted); border-bottom: 2px solid var(--muted);
  transform: translateY(-2px) rotate(45deg);
  transition: transform 0.15s;
}
.dd.open .dd-arrow { transform: translateY(2px) rotate(-135deg); }

.dd-pop {
  position: absolute; top: calc(100% + 6px); left: 0; right: 0; z-index: 20;
  padding: 6px; border-radius: 14px; background: #fff;
  box-shadow: 0 22px 40px -20px rgba(22, 48, 58, 0.5), inset 0 0 0 1px #e4edf0;
  max-height: 264px; overflow-y: auto;
}
/* Список выбора вопроса-условия в редакторе теста.
   Обычный .dd-pop повторяет ширину своей ячейки, а ячейка в ряду вопроса
   узкая — тексты вопросов ломались в столбик по одному слову и уезжали под
   горизонтальную прокрутку (замечание владельца 2026-09-10). Здесь список
   шире своей кнопки и обрезает длинный вопрос многоточием: узнают его по
   началу формулировки, а не по концу. */
/* Ряд перестановки вопроса: номер слева, управление справа.
   Стрелки стоят у номера, а не в ряду с «Дублировать»: там уже четыре
   элемента, и на узкой карточке ряд переносился бы на вторую строку. */
.q-move { display: flex; align-items: center; gap: 6px; margin-bottom: 5px; }
.q-move .icon-btn { font-size: 15px; line-height: 1; }
.dd.dd-movecat { min-width: 132px; }
.dd.dd-movecat .dd-btn { padding: 5px 10px; font-size: 13px; }
.dd.dd-movecat .dd-pop { right: auto; min-width: 100%; width: max-content; max-width: min(360px, 50vw); }
.dd.dd-movecat .dd-item { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.dd.dd-showif { min-width: 200px; max-width: 300px; flex: 1 1 200px; }
.dd.dd-showif .dd-pop { right: auto; min-width: 100%; width: max-content; max-width: min(560px, 60vw); }
.dd.dd-showif .dd-item {
  display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.dd-item {
  width: 100%; display: flex; align-items: center; gap: 10px;
  padding: 9px 11px; border: 0; border-radius: 10px;
  font: inherit; font-size: 13px; font-weight: 500; text-align: left;
  color: var(--text-2); background: transparent; cursor: pointer;
}
.dd-item:hover, .dd-item:focus-visible { outline: none; background: var(--soft); }
.dd-item.on { font-weight: 700; color: var(--accent-dark); background: #e9f6f4; }
.dd-empty { padding: 9px 11px; font-size: 13px; color: var(--muted-2); }

/* Узкий вариант — там, где список стоит в строке таблицы. */
.dd.sm .dd-btn { padding: 6px 10px; font-size: 13px; border-radius: 10px; }

/* Список с поиском по вводу — для перечней, которые глазами не читаются
   (3006 компаний после переноса выгрузки amoCRM). Прокручивается сам перечень,
   а не карточка целиком: строка поиска обязана остаться на виду, иначе, уехав
   вверх, она перестаёт быть поиском. */
.dd.find .dd-pop { max-height: none; overflow: visible; }
.dd-q { padding: 0 0 6px; }
.dd-q input {
  width: 100%; padding: 8px 11px;
  border: 1.5px solid var(--field); border-radius: 10px;
  font: inherit; font-size: 13px; color: var(--text); background: #fff;
}
/* 200px, а не сколько влезет: строка поиска и счётчик добавляют высоты, а
   карточка целиком не должна стать выше прежних 264px — она раскрывается
   в модалке, которая сама прокручивается, и переросший список уехал бы
   за её край. */
.dd-list { max-height: 200px; overflow-y: auto; }
/* Счётчик скрытого. Пустым не занимает места — правило `:empty` держит
   карточку короткой, когда показано всё. */
.dd-note { padding: 7px 11px 2px; font-size: 12px; color: var(--muted-2); }
.dd-note:empty { display: none; }

/* Отметка верного варианта в конструкторе теста.
   Кнопка, а не чекбокс: у вопроса «несколько вариантов» отмеченных бывает
   больше одного, и состояние должно читаться одним взглядом по всей колонке. */
.mark {
  flex: none; width: 26px; height: 26px; border: 1.5px solid var(--field);
  border-radius: 8px; background: #fff; color: transparent;
  font-size: 13px; font-weight: 800; line-height: 1; cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.mark:hover { border-color: #c6d5dc; color: var(--muted-2); }
.mark.on { border-color: var(--accent); background: #e9f6f4; color: var(--accent-dark); }

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

   Здесь оставлен настоящий `<select>`, но его собственная стрелка убрана, а
   шеврон нарисован фоном. Причина, по которой контрол не заменён на список из
   div-ов: настоящий select умеет клавиатуру, поиск по первым буквам и
   экранный диктор, а самодельный список пришлось бы учить этому заново — и
   он бы это умел хуже. */
select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 34px;
  background-image:
    url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='11' height='7' viewBox='0 0 11 7'%3E%3Cpath d='M1 1l4.5 4.5L10 1' fill='none' stroke='%236b8592' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 13px center;
  cursor: pointer;
}
select:hover { border-color: #c6d5dc; }
select:disabled {
  opacity: 0.45; cursor: default; background-color: var(--soft);
}
/* Список раскрывается силами браузера — там задать можно только цвет текста
   и фон, и это единственное, что здесь настраивается. */
select option { color: var(--text); background: #fff; }

/* Раскрытый список — нашим видом, а не системным белым листом Windows
   (замечание владельца 2026-09-23: «выпадающие списки не везде стилизованы
   при раскрытии»). `appearance: base-select` оставляет настоящий select —
   клавиатура, поиск по буквам и диктор те же, — но отдаёт странице и сам
   раскрытый список. Chromium (Chrome, Edge, Яндекс) умеет это с 2025 года;
   браузер, который не умеет, пропускает весь блок и показывает системный
   список, как раньше. Стрелка остаётся фоновой — своя (::picker-icon)
   спрятана, иначе у поля их две. */
@supports (appearance: base-select) {
  select:not([multiple]), select:not([multiple])::picker(select) { appearance: base-select; }
  select:not([multiple])::picker-icon { display: none; }
  select:not([multiple])::picker(select) {
    margin-top: 4px; padding: 4px;
    border: 1px solid var(--line); border-radius: var(--r-sm);
    background: #fff; box-shadow: 0 10px 28px rgba(4, 40, 38, 0.16);
    max-height: min(360px, 60vh); overflow-y: auto;
  }
  select:not([multiple]) option {
    display: flex; align-items: center; gap: 8px;
    padding: 7px 10px; border-radius: 6px;
    font-size: 13px; line-height: 1.35; white-space: normal; cursor: pointer;
  }
  select:not([multiple]) option:hover,
  select:not([multiple]) option:focus-visible { background: var(--accent-soft); outline: none; }
  select:not([multiple]) option:checked { font-weight: 700; color: var(--accent-dark); }
  select:not([multiple]) option::checkmark { order: 1; margin-left: auto; color: var(--accent); }
  select:not([multiple]) option:disabled { color: var(--muted); cursor: default; background: transparent; }
  select:not([multiple]) optgroup { padding: 4px 0; }
  select:not([multiple]) optgroup legend { padding: 6px 10px 2px; font-size: 11px; font-weight: 700; color: var(--muted); }
}

.req-empty input, .req-empty textarea { border-color: rgba(180, 35, 24, 0.45); }
/* Поле, не прошедшее проверку типа. Отличается от `req-empty` намеренно: там
   «ещё не заполнено», здесь «заполнено не тем» — и лечится это по-разному. */
.field.bad input, .field.bad textarea, .field.bad .dd-btn {
  border-color: var(--danger); box-shadow: 0 0 0 3px rgba(180, 35, 24, 0.1);
}

/* Поле анкеты квалификации, которое ещё не спросили. Третий оттенок рядом с
   двумя предыдущими, и это намеренно: «не заполнено» в брифе запрещает запуск
   поиска, а здесь не запрещает ничего — анкета сохранится такой, какая есть.
   Красным это красить нельзя: четыре красных поля при открытии колл-центра
   учат не смотреть на красное вовсе. */
.field.qual-gap input, .field.qual-gap textarea, .field.qual-gap .dd-btn {
  border-color: rgba(138, 98, 8, 0.4); background: rgba(254, 240, 199, 0.28);
}

/* Откуда взялось значение анкеты. Мелким и приглушённым: это сноска к ответу,
   а не сам ответ. */
.qual-since { font-size: 11px; color: var(--muted-2); margin-top: 4px; }

/* «Узнали в этом звонке» в истории. Отбито слева линией, а не рамкой: это
   продолжение строки звонка, а не отдельная запись, и вторая рамка внутри
   ленты читалась бы как ещё одно событие. */
.qual-learned {
  margin-top: 8px; padding: 8px 0 2px 10px;
  border-left: 2px solid var(--line);
}
.qual-learned .cap {
  font-size: 10px; font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--muted-2); margin-bottom: 6px;
}
/* Внутри ленты места вдвое меньше, чем на карточке, — сводка идёт в одну
   колонку, иначе значение переносится после каждого второго слова. */
.qual-learned .brief-fold { grid-template-columns: 1fr; }

.tag {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 10px; border-radius: 999px;
  font-size: 11px; font-weight: 700; white-space: nowrap;
  color: var(--text-3); background: #eaf0f3;
}
.tag-accent { color: var(--accent-dark); background: linear-gradient(120deg, #d9f2ef, #c3e9e3); }
.tag-danger { color: var(--danger); background: var(--danger-bg); }
.tag-warn { color: var(--warn); background: var(--warn-bg); }

/* Строка со ссылкой наружу: поле во всю ширину и кнопка «Скопировать» рядом.
   Ссылку не читают глазами, её копируют — поэтому кнопка, а не только текст. */
.linkrow { display: flex; gap: 8px; align-items: flex-start; }
.linkrow textarea {
  flex: 1; min-width: 0; font-size: 12px; line-height: 1.45;
  /* min-height глобальной textarea (74px) здесь ни к чему: строка со ссылкой
     занимает две строки, а не поле для абзаца. */
  min-height: 0; height: auto; padding: 8px 10px;
  resize: none; word-break: break-all; white-space: pre-wrap; overflow: hidden;
}
.linkrow .btn { flex: none; }
.grow { flex: 1; min-width: 0; }

.card {
  background: var(--surface); border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm); padding: 18px;
}
.card-t {
  font-size: 10px; font-weight: 700; letter-spacing: 0.09em;
  text-transform: uppercase; color: var(--muted); margin-bottom: 12px;
}

/* ── метрики ────────────────────────────────────────────────────────────── */

.kpis { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; margin-bottom: 18px; }
.kpi { background: #fff; border-radius: var(--r-md); box-shadow: var(--shadow-sm); padding: 14px 16px; }
.kpi .cap {
  font-size: 10px; font-weight: 700; letter-spacing: 0.09em;
  text-transform: uppercase; color: var(--muted);
}
.kpi .val { margin-top: 6px; font-size: 27px; font-weight: 800; letter-spacing: -0.03em; }
.kpi .val.bad { color: var(--danger); }
.kpi .sub { font-size: 12px; color: var(--muted); }

/* ── вакансии ───────────────────────────────────────────────────────────── */

.vgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(430px, 1fr)); gap: 14px; align-items: stretch; }
.vcard {
  display: flex; flex-direction: column; gap: 12px;
  background: #fff; border-radius: var(--r-lg); box-shadow: var(--shadow-sm);
  padding: 18px; text-decoration: none; color: inherit;
  transition: box-shadow 0.15s, transform 0.15s;
}
.vcard:hover { box-shadow: var(--shadow-md); }
.vcard.late { box-shadow: var(--shadow-sm), inset 0 0 0 1.5px rgba(180, 35, 24, 0.4); }
.vcard.closed { opacity: 0.55; }
.vcard-top { display: flex; align-items: flex-start; gap: 10px; }
.vcard-title { font-size: 17px; font-weight: 800; letter-spacing: -0.02em; }
.vcard-sub { margin-top: 3px; font-size: 12px; color: var(--muted); }

.funnel { display: flex; align-items: flex-end; gap: 6px; height: 56px; }
.funnel .col { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 4px; justify-content: flex-end; }
.funnel .bar { width: 100%; border-radius: 4px 4px 0 0; background: rgba(22, 48, 58, 0.07); }
.funnel .bar.on { background: var(--accent-700); }
.funnel .n { font-size: 11px; font-weight: 700; color: var(--text-3); }
.funnel .lb { font-size: 9px; color: var(--muted-2); text-align: center; line-height: 1.1; }

.next {
  display: flex; align-items: center; gap: 10px; min-height: 56px;
  padding: 12px 14px; border-radius: var(--r-md); background: var(--soft);
}
.next .t { font-size: 10px; font-weight: 700; letter-spacing: 0.09em; text-transform: uppercase; color: var(--muted); }
.next .v { margin-top: 2px; font-size: 14px; font-weight: 600; }

.vcard-foot { margin-top: auto; display: flex; align-items: center; gap: 8px; padding-top: 4px; }
.vcard-fee { font-size: 13px; font-weight: 700; color: var(--text-2); margin-right: auto; }

/* ── карточка вакансии ──────────────────────────────────────────────────── */

.cols { display: grid; grid-template-columns: 1fr 340px; gap: 18px; align-items: start; }

/* В панели кандидата правая колонка шире: с 2026-09-03 в ней живёт переписка,
   а в 340 точках сообщения ужимаются до нечитаемой лапши. Панель широкая
   (до 1180), место есть — забирается оно у левой колонки, где лежат заметки и
   результат теста, то есть текст, которому лишние сто точек ничего не дают. */
.panel .cols { grid-template-columns: 1fr 420px; }

/* Карточка компании — правая колонка тоже 420, а не 340 (владелец, 2026-09-06:
   «задачи слипаются»). В 340 точках строке задачи оставалось 136 на заголовок:
   «Подготовить целевое КП: Самолет+» ломался на ТРИ строки и налезал на плашку
   срока с крестиком. Восемьдесят точек забраны у левой колонки, где лежат этап,
   вакансии и история, — тексту, который и так во всю ширину, они ничего не
   давали. Правило точечное, а не общее для .cols: на вакансии и в списках
   правая колонка узкая по делу, там короткие подписи. */
.cols-co { grid-template-columns: 1fr 420px; }
.stack { display: flex; flex-direction: column; gap: 14px; }

/* Сетка брифа — шесть колонок, чтобы поле могло занять треть, половину или всю
   строку. Ширина задаётся в шаблоне брифа: раньше её решал тип поля, и четыре
   абзаца подряд растягивали карточку на пол-экрана. */
.brief-grid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 14px; }
.brief-grid .field.w-s { grid-column: span 2; }
.brief-grid .field.w-m { grid-column: span 3; }
.brief-grid .field.w-l { grid-column: span 6; }
/* Предпросмотр раскладки в шаблоне брифа: показывает, а не принимает ввод.
   Поле, в которое можно печатать, но нельзя сохранить, хуже, чем картинка. */
.brief-grid.preview { pointer-events: none; }

/* Плитки устройства системы на экране настроек: сюда переехали экраны,
   которых не должно быть в меню — это настройка, а не ежедневная работа. */
.setup-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; }
.setup-tile {
  display: block; padding: 13px 15px; border-radius: var(--r-md);
  background: var(--soft); color: inherit; text-decoration: none;
  transition: background 0.15s, box-shadow 0.15s;
}
.setup-tile:hover { background: #ffffff; box-shadow: var(--shadow-sm); }
.setup-tile .nm { font-size: 14px; font-weight: 700; }
.setup-tile .ct { margin-top: 3px; font-size: 11px; color: var(--muted); line-height: 1.45; }
.brief-head { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; }
.brief-head > :last-child { margin-left: auto; }
.brief-count { margin-left: auto; font-size: 13px; font-weight: 700; color: var(--text-2); }

/* Свёрнутый бриф: заполненный он нужен как справка, а не как форма.
   Две колонки «поле — значение», без рамок полей и кнопок. */
/* Чего не хватает — строкой над справкой: сворачивается теперь и бриф с
   пустыми обязательными, и без этой строки причина серой кнопки «Запустить
   поиск» пропадала бы вместе с формой. */
.brief-miss {
  display: flex; align-items: center; gap: 10px; margin-bottom: 12px;
  padding: 9px 12px; border-radius: var(--r-md);
  font-size: 12px; color: var(--danger); background: var(--danger-bg);
}
.brief-miss > span { flex: 1; }
.brief-fold { display: grid; grid-template-columns: 1fr 1fr; gap: 5px 18px; }
/* min-width: 0 — иначе ячейка грида растягивается по длине ответа в одну
   строку (auto у грид-элемента), колонки разъезжаются шире карточки и
   значения уходят за её правый край. */
.brief-fold > div { display: flex; gap: 8px; font-size: 13px; align-items: baseline; min-width: 0; }
/* Подпись поля — только первый span в строке: у длинного ответа рядом стоит
   второй, со значением, и общее правило сплющивало бы его до 42% и одной
   строки с многоточием. */
.brief-fold > div > span:first-child {
  flex: 0 0 42%; font-size: 11px; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Длинные ответы. Бриф с тремя абзацами занимает свёрнутым столько же места,
   сколько формой (замечание владельца 2026-09-19: «дело в длинных текстах»),
   поэтому ответ обрезается одной строкой с многоточием, а целиком показывается
   подсказкой при наведении. Две строки вместо одной уже пробовали: строки
   выходили разной высоты и справка выглядела грязно. */
.brief-fold .v {
  flex: 1 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.dot-ok, .dot-no {
  display: inline-block; width: 8px; height: 8px; border-radius: 999px; margin-right: 6px;
}
.dot-ok { background: var(--accent-700); }
.dot-no { background: rgba(180, 35, 24, 0.55); }

table.t { width: 100%; border-collapse: collapse; }
table.t th {
  padding: 0 10px 8px 0; text-align: left;
  font-size: 10px; font-weight: 700; letter-spacing: 0.09em;
  text-transform: uppercase; color: var(--muted);
}
table.t td { padding: 11px 10px 11px 0; border-top: 1px solid var(--line); font-size: 14px; vertical-align: middle; }
table.t tr:hover td { background: #f5f9fa; }
table.t td.right, table.t th.right { text-align: right; padding-right: 0; }

.cand-name { font-weight: 700; }
.cand-sub { font-size: 12px; color: var(--muted); }

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

.cand-tools { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin-bottom: 10px; }
/* Поле поиска — справа, за пилюлями: оно растягивается остатком строки, а
   пилюли занимают столько, сколько нужно (владелец 2026-09-07). */
.cand-tools .pills { flex: 0 1 auto; }
.pill-ico { display: inline-flex; vertical-align: -2px; margin-right: 5px; }
.pill-ico svg { width: 12px; height: 12px; }
/* Поиск ужат с 210 до 100 точек (владелец 2026-09-09): в ряд встали кнопки
   пола, и место для них взято отсюда, а не новой строкой в шапке.

   Число не на глаз: карточка в самом узком случае 826 точек, пилюли занимают
   571, кнопки пола 124, отступы 20 — полю остаётся 111. Минимум в 130 не
   помещался, и ряд переносился на вторую строку, то есть шапка росла ровно
   там, где просили не расти.

   Растягиваться остатком строки поле по-прежнему умеет: на широком мониторе
   оно длиннее, сотня — это только нижняя граница. */
.cand-q {
  flex: 1; min-width: 100px; padding: 8px 10px;
  border: 1.5px solid var(--field); border-radius: var(--r-sm);
  font: inherit; font-size: 13px; color: var(--text); background: #fff;
}
.cand-q:focus { border-color: var(--accent); outline: none; }
.cand-q::placeholder { color: var(--muted-2); }

/* Заголовок группы читается как строка воронки: подпись и сразу за ней число.
   В конце строки число пришлось бы искать глазами, а именно оно и есть ответ
   на первый вопрос к вакансии — сколько народу где стоит. */
.cg-head { display: flex; align-items: center; gap: 8px; border-top: 1px solid var(--line); }
.cgroup:first-child .cg-head { border-top: 0; }
.cg-t {
  display: flex; align-items: center; gap: 8px; flex: 1; min-width: 0;
  padding: 9px 0; border: 0; background: none; font: inherit;
  color: var(--text); text-align: left; cursor: pointer;
}
.cg-t b { font-size: 13px; font-weight: 700; }
.cg-t .n {
  min-width: 24px; padding: 1px 8px; border-radius: 999px; background: var(--soft);
  font-size: 12px; font-weight: 700; color: var(--text-3); text-align: center;
}
.cg-arrow {
  width: 0; height: 0; border-left: 5px solid var(--muted);
  border-top: 4px solid transparent; border-bottom: 4px solid transparent;
  transition: transform 0.12s;
}
.cgroup.open .cg-arrow { transform: rotate(90deg); }
.cg-all {
  display: flex; align-items: center; gap: 6px;
  font-size: 12px; color: var(--muted); cursor: pointer; white-space: nowrap;
}
.cg-body { padding-bottom: 8px; }
.cg-more { width: 100%; margin-top: 6px; }

.crow {
  position: relative;
  display: grid; align-items: center; gap: 10px;
  grid-template-columns: 20px 26px minmax(0, 1fr) auto 76px;
  padding: 6px 8px 6px 2px; border-radius: var(--r-sm);
}
.crow:hover { background: #f5f9fa; }
.crow.gone .ini, .crow.gone .cand-name { opacity: 0.62; }
/* Оценка кандидата — один значок на все экраны: таблица, диалоги, панель.
   Круг с числом, а не звёзды и не полоска: он одинаково читается и в плотной
   строке списка, и рядом с именем в шапке, и не растёт вместе со шкалой.

   Три цвета вместо десяти оттенков — цвет отвечает «брать ли в работу», а не
   «на сколько именно»; десять оттенков одного цвета в списке неразличимы. */
.rate {
  position: relative; display: inline-flex; align-items: center; justify-content: center;
  flex: none; width: 26px; height: 26px; margin-left: 6px; vertical-align: -8px;
}
/* Поворот на четверть — здесь, а не атрибутом в разметке: дуга обязана
   начинаться сверху, а не справа, и это оформление. Заодно в скрипте не
   остаётся `rotate(` — проверка «каждый вызванный помощник объявлен»
   принимает его за вызов функции. */
.rate svg { position: absolute; inset: 0; width: 26px; height: 26px; transform: rotate(-90deg); }
.rate circle { fill: none; stroke-width: 2.4; }
.rate .rate-track { stroke: rgba(22, 48, 58, 0.1); }
.rate .rate-arc { stroke-linecap: round; }
.rate b {
  font-size: 11px; font-weight: 800; font-variant-numeric: tabular-nums; line-height: 1;
}
.rate-high .rate-arc { stroke: var(--accent); }
.rate-high b { color: var(--accent-dark); }
.rate-mid .rate-arc { stroke: #d99a06; }
.rate-mid b { color: #8a6208; }
.rate-low .rate-arc { stroke: var(--danger); }
.rate-low b { color: var(--danger); }

/* Кольцо исхода отбора — тот же инструмент, что и кольцо оценки (просьба
   владельца 2026-09-10). Цвет несёт исход, дуга — долю пройденных условий:
   «11» у отсеянного и у годного выглядят одинаково, а решения по ним
   противоположные. */
.vd-pass .rate-arc { stroke: var(--accent); }
.vd-pass b { color: var(--accent-dark); }
.vd-cond .rate-arc { stroke: #d99a06; }
.vd-cond b { color: #8a6208; }
.vd-hold .rate-arc { stroke: #6b7fd7; }
.vd-hold b { color: #465ba8; }
.vd-ask .rate-arc { stroke: var(--muted-2); }
.vd-ask b { color: var(--text-3); }
.vd-stop .rate-arc { stroke: var(--danger); }
.vd-stop b { color: var(--danger); }

/* Слово рядом с кольцом: кольцо показывает «сколько», слово — «что делать».
   Без слова «условно» и «отложить» различались бы только оттенком.

   Ширина слова ФИКСИРОВАНА, и это не косметика. Колонка отметки прижата к
   правому краю, слова разной длины («годен» и «уточнить» отличаются втрое), и
   без фиксации кольца съезжали бы по горизонтали от строки к строке —
   столбик, по которому и читают список сверху вниз, рассыпается (замечание
   владельца 2026-09-10). */
.vd-cell { display: inline-flex; align-items: center; gap: 5px; }
.vd-cell .rate { margin-left: 0; }
.vd-word {
  min-width: 58px; text-align: left;
  font-size: 11px; font-weight: 700; white-space: nowrap;
}
.vd-w-pass { color: var(--accent-dark); }
.vd-w-cond { color: #8a6208; }
.vd-w-hold { color: #465ba8; }
.vd-w-ask { color: var(--text-3); }
.vd-w-stop { color: var(--danger); }

/* Кружки и доли исхода — в кнопках полосы отбора. */
.vb-pass .rb-dot { background: var(--accent); }
.vb-cond .rb-dot { background: #d99a06; }
.vb-hold .rb-dot { background: #6b7fd7; }
.vb-ask .rb-dot { background: var(--muted-2); }
.vb-stop .rb-dot { background: var(--danger); }
.pill.vb-pass.on { background: var(--accent); }
.pill.vb-cond.on { background: #d99a06; }
.pill.vb-hold.on { background: #6b7fd7; }
.pill.vb-ask.on { background: var(--text-3); }
.pill.vb-stop.on { background: var(--danger); }
.rb-seg.vb-pass { background: var(--accent); }
.rb-seg.vb-cond { background: #d99a06; }
.rb-seg.vb-hold { background: #6b7fd7; }
.rb-seg.vb-ask { background: var(--muted-2); }
.rb-seg.vb-stop { background: var(--danger); }

/* Выбор оценки — ШКАЛА, а не десять одинаковых кнопок (замечание владельца
   2026-09-08: «просто цифры не красиво»). Ячейки заполняются слева направо,
   и выбор читается как уровень, а не как номер варианта: видно, что семь —
   это «больше половины», а не «седьмой пункт».

   Наведение подсвечивает всё до курсора обычным CSS: заливаются все ячейки,
   а те, что ПОСЛЕ наведённой, гасятся правилом-соседом. Скрипт для этого не
   нужен, и предпросмотр не зависит от того, успел ли он отработать. */
.rate-scale { display: flex; gap: 3px; align-items: center; }
.rate-scale button {
  width: 26px; height: 30px; padding: 0; border-radius: 6px;
  border: 0; background: rgba(22, 48, 58, 0.07);
  font: inherit; font-size: 11px; font-weight: 700; color: var(--muted);
  cursor: pointer; transition: background 0.1s, color 0.1s, transform 0.1s;
}
.rate-scale button.on { color: #fff; background: var(--accent); }
.rate-scale button.on.mid { background: #d99a06; }
.rate-scale button.on.low { background: var(--danger); }

.rate-scale:hover button { color: #fff; background: var(--accent-500); }
.rate-scale button:hover { transform: translateY(-1px); }
.rate-scale button:hover ~ button {
  color: var(--muted); background: rgba(22, 48, 58, 0.07); transform: none;
}

/* Итог под шкалой: число крупно, «из 10» мельче — иначе десятка читается как
   часть оценки. Кнопка снятия рядом, а не спрятана в повторном нажатии:
   скрытое действие не находят, и ошибочная оценка остаётся навсегда. */
.rate-now { display: flex; align-items: baseline; gap: 6px; margin-top: 10px; }
.rate-now .n { font-size: 22px; font-weight: 800; line-height: 1; letter-spacing: -0.03em; }
.rate-now .n.high { color: var(--accent-dark); }
.rate-now .n.mid { color: #8a6208; }
.rate-now .n.low { color: var(--danger); }
.rate-now .of { font-size: 12px; color: var(--muted); }
.rate-now .rate-off {
  margin-left: auto; padding: 3px 10px; border-radius: 999px;
  border: 1px solid var(--line-2); background: #fff;
  font: inherit; font-size: 12px; color: var(--muted); cursor: pointer;
}
.rate-now .rate-off:hover { border-color: var(--danger); color: var(--danger); }

/* Полоса оценок: сводка и фильтр одним управлением (замечание владельца
   2026-09-08). Число, на которое нельзя нажать, кончается тем, что этих
   девятерых ищут глазами по ста сорока двум строкам.

   ОДНА строка на всё: кнопки полос, доли и подпись с покрытием («чтобы шапка
   не была слишком большой», 2026-09-08). В строку фильтров полосы не встают —
   там нужно 1214 точек, а `.wrap` держит min-width 1280, то есть расчётная
   ширина карточки 826: до ~1900 на мониторе ряд переносился бы, и шапка
   становилась ВЫШЕ, а не ниже. Поэтому сжата сама полоса.

   Кнопки мельче пилюль — это второе измерение списка, а не ещё четыре фильтра
   в общий ряд: одинаковые кнопки девятью подряд читались бы как один набор, из
   которого выбирают одну.

   Пустой контейнер прячется целиком: пока в вакансии не оценён никто, полосы
   нет, а оставшийся от неё зазор читался бы как сбой вёрстки. */
#cand-rateline {
  display: flex; align-items: center; gap: 5px; flex-wrap: wrap; margin: 0 0 10px;
}
#cand-rateline:empty { display: none; }
/* Ряд исхода отбора живёт по тем же правилам, что полоса оценок: пустой —
   не занимает места вовсе. У вакансии без размеченного теста исхода нет ни у
   кого, и пять нулей отвечали бы на несуществующий вопрос. */
#cand-verdictline {
  display: flex; align-items: center; gap: 5px; flex-wrap: wrap; margin: 0 0 10px;
}
#cand-verdictline:empty { display: none; }
.rf-t {
  margin-right: 1px; font-size: 10px; font-weight: 800; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--muted-2);
}
/* Подпись прижата к правому краю, как поле поиска этажом выше: там заканчивают
   читать. Покрытие ходит вместе со средним и никогда без него — «средняя 8,5»
   по двум оценённым из двухсот врёт в приятную сторону. */
.rf-avg { flex: none; margin-left: 4px; font-size: 12px; color: var(--muted); }

.pill.rb {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 9px; font-size: 11px; font-weight: 700;
}
.rb-dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.rb-high .rb-dot { background: var(--accent); }
.rb-mid .rb-dot { background: #d99a06; }
.rb-low .rb-dot { background: var(--danger); }
.rb-none .rb-dot { background: var(--muted-2); }
/* Выбранная полоса красится СВОИМ цветом, а не общим акцентным: цвет здесь и
   есть смысл полосы, и «1–4», залитая зелёным, читалась бы как «хорошие». */
.pill.rb-mid.on { background: #d99a06; }
.pill.rb-low.on { background: var(--danger); }
.pill.rb-none.on { background: var(--text-3); }
.pill.rb.on .rb-dot { background: rgba(255, 255, 255, 0.85); }
.pill.rb:disabled:not(.on) .rb-dot { opacity: 0.35; }

/* Доли — то, чего числа не дают: «5 / 9 / 3 / 45» требует арифметики, а серый
   кусок во всю ширину сразу показывает, что оценивали единицы. Именно это и
   есть главный ответ полосы: сначала покрытие, потом распределение. */
/* Полоска долей забирает остаток строки: между кнопками и подписью её ширина
   — то, что осталось, и на широком мониторе она просто длиннее. Минимум в 90
   точек не даёт ей выродиться в закорючку на узком. */
.rate-bar {
  display: flex; flex: 1; min-width: 90px; height: 6px; margin: 0 5px; overflow: hidden;
  border-radius: 999px; background: var(--soft);
}
.rb-seg { display: block; height: 100%; }
.rb-seg.rb-high { background: var(--accent); }
.rb-seg.rb-mid { background: #d99a06; }
.rb-seg.rb-low { background: var(--danger); }
.rb-seg.rb-none { background: rgba(22, 48, 58, 0.13); }

/* Анкета по ссылке — внизу карточки вакансии: три числа и полоса «из всех
   открывших» (просьба владельца 2026-09-11).

   Оттенок один, бирюзовый, от светлого к тёмному: чем дальше человек прошёл,
   тем темнее. Светлая ступень #6cbfb4 взята темнее --accent-soft нарочно: та
   на белой карточке не видна вовсе. Проверено валидатором палитры: ступени
   монотонны по светлоте, соседние различимы, светлая держит 2.15:1 к белому
   при пороге 2:1.

   Между сегментами — зазор в 2 точки цвета карточки, а не граница: соседние
   ступени одного оттенка без зазора сливаются в одну. min-width держит
   видимым сегмент из одного человека рядом с сотней. */
.lf-tiles { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-bottom: 12px; }
.lf-n { font-size: 22px; font-weight: 800; letter-spacing: -0.02em; line-height: 1.1; }
.lf-l { font-size: 12px; color: var(--muted); margin-top: 3px; line-height: 1.25; }
.lf-s { font-size: 11px; color: var(--muted-2); margin-top: 2px; }
.lf-bar { display: flex; gap: 2px; height: 10px; margin-bottom: 8px; }
.lf-seg { display: block; flex-basis: 0; min-width: 4px; border-radius: 3px; }
.lf-done { background: var(--accent-dark); }
.lf-inside { background: var(--accent-500); }
.lf-before { background: #6cbfb4; }
/* «Шаг неизвестен» — открытия до 11.09 из лога сервера. Штриховкой, а не
   сплошным: по светлоте этот серый почти совпадает со светлой бирюзой (1.15:1),
   и отличить их должен рисунок, а не оттенок. Сам серый держит 2.47:1 к белому. */
.lf-unsplit { background: repeating-linear-gradient(135deg, #9aa7ad 0 3px, #dfe5e8 3px 6px); }
.lf-bar.sm { height: 6px; gap: 1px; margin: 6px 0 0; }
.lf-bar.sm .lf-seg { min-width: 2px; border-radius: 2px; }

/* «Где уходят» — шаги анкеты под кнопкой в блоке карточки. Колонка узкая
   (340 точек), поэтому строка в два этажа: подпись шага сверху, под ней полоса
   «дошли» и числа. Худший шаг помечен словами в метке, а не одним цветом. */
.lf-steps-btn { width: 100%; justify-content: center; margin-top: 10px; }
.lf-steps { margin-top: 8px; }
.lf-step { padding: 7px 0; border-top: 1px solid var(--line); }
.lf-step.sub { padding-left: 12px; }
.lf-step.worst .lf-step-l { font-weight: 700; }
.lf-step-l { font-size: 12.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lf-step-tag { display: inline-block; margin-top: 3px; }
.lf-step-row { display: flex; align-items: center; gap: 8px; margin-top: 4px; font-size: 11.5px; color: var(--muted); }
.lf-step-bar { flex: 1; min-width: 40px; height: 6px; border-radius: 999px; background: var(--soft); overflow: hidden; }
.lf-step-bar i { display: block; height: 100%; border-radius: 999px; background: var(--accent-500); }
.lf-step-n, .lf-step-x { flex: none; font-variant-numeric: tabular-nums; }
.lf-step-n { color: var(--text-2); }
.lf-steps-foot { margin-top: 6px; }

/* Строка анкеты на плитке списка: подпись капсом, как «Следующий шаг», и три
   числа словами владельца. */
.vcard-lf-row { display: flex; align-items: baseline; flex-wrap: wrap; gap: 2px 12px; font-size: 12px; color: var(--muted); }
.vcard-lf-row b { font-size: 13px; font-weight: 700; color: var(--text); }
.vcard-lf-t { font-size: 10px; font-weight: 700; letter-spacing: 0.09em; text-transform: uppercase; color: var(--muted); }
.lf-legend { display: flex; flex-wrap: wrap; gap: 4px 12px; margin-bottom: 8px; font-size: 12px; color: var(--muted); }
.lf-key { display: inline-flex; align-items: center; gap: 5px; }
.lf-sw { display: inline-block; width: 9px; height: 9px; border-radius: 2px; }

/* Отметка пола рядом с именем.

   Догадка и решение человека выглядят по-разному, и это главное в отметке.
   Выведенный из имени знак бледный и с пунктиром снизу — «проверьте перед
   письмом»; проставленный рекрутёром сплошной и в цвете текста — за ним
   разговор, а не словарь. Одинаковый вид выдавал бы догадку за проверенное,
   а обжигаются именно на ней: «уважаемая Александра» мужчине читается как
   небрежность.

   Цветом пол НЕ красится (ни розовым, ни голубым): это служебный признак
   строки, а не украшение, и цвет в списке уже занят — им говорят об оценке и
   о нерабочем времени у собеседника. */
.gmark {
  margin-left: 5px; font-size: 12px; line-height: 1; color: var(--muted);
  border-bottom: 1px dotted var(--muted-2); cursor: help;
}
.gmark.set { color: var(--text-3); border-bottom: none; font-weight: 700; }

/* Пол в шапке карточки — не подпись, а управление: нажал и поменял, не
   заходя в правку карточки (замечание владельца 2026-09-09). Поэтому у него
   вид кнопки, а не текста, — иначе на него не нажмут.

   Ростом ниже имени и без жирности: рядом стоит имя человека, и спорить с ним
   за внимание значку незачем. Ширина по содержимому — подписи разной длины
   («♀ по имени», «— по имени не вышло»), и фиксированная либо обрезала бы
   длинную, либо оставляла дыру у короткой. */
.dd.gsel { display: inline-block; width: auto; vertical-align: 3px; margin-left: 8px; }
.dd.gsel .dd-btn {
  padding: 3px 8px; font-size: 12px; font-weight: 400;
  border-radius: 8px; color: var(--muted); gap: 6px;
}
.dd.gsel .dd-pop { min-width: 168px; }

/* Кнопки пола в строке полос — того же размера, что и полосы оценки: это
   соседние фильтры одного веса, и разный рост читался бы как разная важность.
   Знак чуть крупнее числа, потому что по нему кнопку и находят. */
#cand-gender { display: inline-flex; align-items: center; gap: 5px; flex: 0 0 auto; }
/* Поджаты по горизонтали: кнопки стоят в ряду фильтров, и каждая лишняя
   точка приближает перенос ряда на вторую строку — то есть рост шапки, ради
   которого их сюда и переносили. */
.pill.gb {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 7px; font-size: 11px; font-weight: 700;
}
.pill.gb-none { letter-spacing: 0.02em; }

/* Кнопка «речь?» — тот же ряд, тот же вес, но словом, а не знаком: у неё нет
   пары, и знак пришлось бы объяснять легендой. Не красная и не
   предупреждающая: это очередь на звонок, а не проблема с человеком. */
.pill.gb-l-check, .pill.gb-l-ru, .pill.gb-l-none { letter-spacing: 0.01em; font-weight: 600; }

/* Отметка «речь?» в строке списка — того же роста и того же приглушённого
   тона, что и значок пола: оба выведены из имени, оба стоит проверить, и
   разный вид читался бы как разная надёжность. Пунктир снизу — то же самое
   «это догадка, наведите и прочтите». */
/* Значок стоит в одной строке с именем, кнопкой пола и оценкой, и у всех троих
   разная природа: текст, кнопка и кружок. Без общей опоры значок «плавал» —
   в карточке садился ниже кнопки пола (замечание владельца 2026-09-10).
   inline-block с выравниванием по середине даёт эту опору. */
/* Резюме с hh.ru. Значок буквенный, а не логотип: логотип чужой, возить его
   с собой нельзя, а две буквы в строке узнаются не хуже. */
.hh-mark {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 20px; height: 15px; padding: 0 4px; margin-left: 6px;
  border-radius: 4px; font-size: 10px; font-weight: 700; line-height: 1;
  text-decoration: none; vertical-align: middle; white-space: nowrap;
}
.hh-mark.ok { color: var(--accent); background: var(--accent-soft); }
.hh-mark.ok:hover { color: var(--accent-dark); }
/* Скрепка «у кандидата есть файлы» в таблице кабинета: тот же значок, что hh. */
.hh-mark.file-mark { gap: 2px; cursor: help; }
.hh-mark.many { color: var(--warn); background: var(--warn-bg); cursor: help; }
/* «Кратко» — тот же цвет, что у полного, но контуром вместо заливки: у
   заказчика это тоже «резюме есть», только короче, и красить его тревожно
   значило бы звать разбираться там, где разбираться не с чем. */
.hh-mark.brief {
  color: var(--accent); background: none; cursor: help;
  box-shadow: inset 0 0 0 1px var(--accent-soft);
}
/* «Не нашли» — приглушённо: это не беда и не работа человеку, а лишь отметка,
   что искать уже пробовали. */
.hh-mark.none { color: var(--muted-2); background: var(--soft); cursor: help; }
/* «Ещё не искали» и «искать негде» — контуром, без заливки: место значок
   занимает (иначе строки прыгают, когда поиск доходит до человека), но взгляд
   не держит. Различает их подсказка: первое про очередь, второе про настройку. */
.hh-mark.wait, .hh-mark.off {
  color: var(--muted-2); background: none; cursor: help;
  box-shadow: inset 0 0 0 1px var(--line);
}

/* Ход поиска резюме на hh: занимает место кнопки, пока ответа нет.

   Точка пульсирует, и это не украшение: «идёт» отличается от «стоит» только
   движением — неподвижная надпись читается как очередная подпись, и человек
   снова не понимает, работает система или нет. Тем, у кого движение на экране
   отключено системно, остаётся сама надпись. */
.hh-wait {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; font-weight: 600; color: var(--accent);
}
.hh-wait::before {
  content: ''; width: 7px; height: 7px; border-radius: 50%;
  background: currentColor; animation: hh-pulse 1.1s ease-in-out infinite;
}
@keyframes hh-pulse {
  0%, 100% { opacity: .25; transform: scale(.75); }
  50% { opacity: 1; transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .hh-wait::before { animation: none; opacity: 1; }
}

/* Спорные однофамильцы: строка варианта с переходом и выбором. Кнопки
   справа, чтобы взгляд шёл по именам сверху вниз, а не по кнопкам. */
.hh-opt {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 0; border-top: 1px solid var(--line);
}
.hh-opt-main { flex: 1; min-width: 0; }
.hh-opt-act { display: flex; gap: 6px; flex: none; }

/* Значок hh в заголовке брифа. Сама настройка объявлений постоянно на глазах
   не нужна (владелец, 2026-09-21: «редко настраивается»), а ответ «ищутся ли
   резюме по этой вакансии» нужен всегда — поэтому состояние в заголовке, а
   карточка раскрывается по клику. */
.hh-pill.on { color: var(--accent); }
.hh-pill.off { color: var(--muted-2); }

.hh-title { font-size: 13px; font-weight: 600; color: var(--text); }
.hh-skills { display: flex; flex-wrap: wrap; gap: 4px; margin: 8px 0; }
.hh-skill {
  font-size: 11px; line-height: 1.6; padding: 0 7px; border-radius: 999px;
  color: var(--text-3); background: var(--soft);
}
.hh-auto {
  margin-left: 6px; padding: 0 6px; border-radius: 999px; cursor: help;
  font-size: 10px; font-weight: 700; color: var(--warn); background: var(--warn-bg);
}
.hh-links { margin-top: 8px; font-size: 12px; }

.lmark {
  display: inline-block; vertical-align: middle; font-weight: 400;
  margin-left: 6px; font-size: 11px; line-height: 1.6; color: var(--muted);
  border-bottom: 1px dotted var(--muted-2); cursor: help; white-space: nowrap;
}
/* Жирность НЕ наследуется от имени: в шапке карточки имя набрано крупным и
   плотным, и метка, унаследовав это, спорила с ним за внимание. */
.panel-head h3 .lmark { font-weight: 400; }
/* «Среда» — без пунктира: смотреть там не на что, работа не нужна. Пунктир
   остаётся там, где есть что сделать. Кегль чуть крупнее, иначе значок в
   строке не виден вовсе — а он и заведён затем, чтобы отличать «посчитано и
   всё в порядке» от «не сработало». */
.lmark.ok { border-bottom: none; font-size: 12px; opacity: 0.85; }
/* «Не определено» — только в карточке и только словами: в списке это была бы
   строка-прочерк у каждой третьей карточки, а ответить на вопрос «сломано или
   нет» надо там, где человек этим вопросом задаётся. */
.lmark.none { border-bottom: none; opacity: 0.7; }

/* Часовой пояс кандидата в строке списка. Обычное время — как остальная
   подпись; нерабочее у собеседника — цветом предупреждения: это и есть весь
   смысл пояса в таблице, «сейчас туда звонить нельзя». */
.cand-tz { white-space: nowrap; }
.cand-tz.quiet { color: var(--warn); font-weight: 700; }

.cpick { display: flex; align-items: center; justify-content: center; }
.cpick input { width: 15px; height: 15px; accent-color: var(--accent); cursor: pointer; }
.cwho { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.cwho .cand-name {
  border: 0; background: none; padding: 0; font: inherit; font-weight: 700;
  color: var(--text); text-align: left; cursor: pointer;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cwho .cand-name:hover { color: var(--accent); }
.cmark { display: flex; justify-content: flex-end; }
.cwhen { text-align: right; white-space: nowrap; }

/* Действия строки — по наведению, как на карточке очереди колл-центра. Всегда
   видимые, они означали бы двести списков этапов и двести кнопок «Отказ» в
   поле зрения при том, что за один заход трогают единицы. Полоса перекрывает
   правый край строки, поэтому под неё не резервируется место. */
.crow-acts {
  position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
  z-index: 1;
  display: flex; align-items: center; gap: 6px;
  padding-left: 20px; opacity: 0; transition: opacity 0.12s;
  background: linear-gradient(90deg, rgba(245, 249, 250, 0), #f5f9fa 20px);
}
/* z-index здесь обязателен, и не ради красоты. `transform` создаёт свой
   контекст наложения, поэтому z-index выпадающего списка ВНУТРИ полосы
   действий наружу не действует: список ложился под следующие строки, сквозь
   него просвечивали их плашки, а клик в этой зоне попадал в строку под
   списком, а не в пункт списка. Улика — снимок владельца от 2026-09-07.
   Открытый список поднимается ещё выше: он должен лечь и поверх полосы
   пакетных действий, прижатой к низу экрана. */
.crow-acts:has(.dd.open) { z-index: 25; }
.crow:hover .crow-acts, .crow-acts:focus-within { opacity: 1; }
/* Без мыши наведения не бывает: на планшете действия встают отдельной строкой. */
@media (hover: none) {
  .crow-acts {
    position: static; transform: none; opacity: 1;
    grid-column: 1 / -1; padding-left: 0; background: none;
  }
}

/* Полоса пакетных действий прижата к нижнему краю ЭКРАНА: отметив сорок
   человек в развёрнутой группе, человек стоит в середине списка, и кнопка,
   уехавшая вниз на два экрана, означала бы, что пачками не пользуются.

   Липкость висит на ОБЁРТКЕ (#cand-bulk), а не на самой полосе, и это не
   придирка к месту правила. Ход sticky-элемента ограничен его контейнером, а
   контейнером полосы была обёртка ровно её высоты — ездить некуда, и полоса
   всё это время просто стояла под списком, хотя выглядела написанной как
   липкая. Замер 2026-09-07 при окне 720: низ полосы приходился на 885, то
   есть за краем экрана. Ровно это владелец и увидел. */
#cand-bulk { position: sticky; bottom: 0; z-index: 5; padding: 8px 0 12px; }
/* Без отметок обёртки нет вовсе. Отступы делают её полосой в 20 px, а липкая
   прозрачная полоса у нижнего края экрана перехватывает клики по строкам под
   собой: видно её не будет, а строка внизу списка перестанет нажиматься.
   Поймано замером сразу после правки 2026-09-07. */
#cand-bulk:empty { display: none; }

/* Полоса ТЁМНАЯ, а не светлая (замечание владельца 2026-09-07: «сливается с
   фоном»). Светлая полупрозрачная панель на светлом списке читалась как часть
   списка, хотя это режим: отмечено сорок человек, и следующее нажатие сделает
   что-то сразу со всеми. Цвет здесь — не украшение, а признак режима. */
.cand-bulk {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 8px 10px 8px 14px; border-radius: var(--r-xl);
  color: #fff;
  background: linear-gradient(120deg, var(--accent-dark), var(--accent));
  box-shadow: 0 18px 38px -18px rgba(11, 92, 86, 0.75), inset 0 1px 0 rgba(255, 255, 255, 0.18);
  animation: bulk-in 0.16s ease-out;
}
/* Полоса появляется по первой отметке — не выезжай она, на экране просто
   молча возникал бы новый блок поверх списка. */
@keyframes bulk-in { from { opacity: 0; transform: translateY(10px); } }
@media (prefers-reduced-motion: reduce) { .cand-bulk { animation: none; } }

/* Число отмеченных — значком, а не словом в ряду слов: это единственная цифра
   на полосе, и по ней сверяются перед действием сразу на сорок человек. */
.bulk-cnt {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 13px; font-weight: 700; color: #fff;
}
/* Значок вывернут: на тёмной полосе белый кружок с акцентным числом виден
   сразу, а акцентный на акцентном не читался бы вовсе. */
.bulk-n {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 25px; height: 25px; padding: 0 8px; border-radius: 999px;
  color: var(--accent-dark); background: #fff;
  font-size: 13px; font-weight: 800; font-variant-numeric: tabular-nums;
}

/* Кнопки и список внутри полосы — светлые контуром на тёмном. Обычные
   .btn-secondary и .dd-btn здесь белые на белом фоне: на тёмной полосе они
   выглядели бы наклейками, а не частью её. */
.cand-bulk .btn-secondary {
  color: #fff; border-color: rgba(255, 255, 255, 0.45); background: rgba(255, 255, 255, 0.1);
}
.cand-bulk .btn-secondary:hover:not(:disabled) {
  border-color: #fff; background: rgba(255, 255, 255, 0.2);
}
.cand-bulk .dd-btn {
  color: #fff; border-color: rgba(255, 255, 255, 0.45); background: rgba(255, 255, 255, 0.1);
}
.cand-bulk .dd-btn:hover { border-color: #fff; }
.cand-bulk .dd-val.ph { color: rgba(255, 255, 255, 0.75); }
.cand-bulk .dd-arrow { border-right-color: #fff; border-bottom-color: #fff; }
.cand-bulk .dd.open .dd-btn { border-color: #fff; box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.22); }
.cand-bulk .dd { margin-left: 6px; }
.cand-bulk .bulk-sp { margin-left: auto; }

/* Список этапов открывается ВВЕРХ: полоса стоит у нижнего края экрана, и
   выпадающий вниз список ушёл бы за него целиком. Главное действие полосы
   стало бы недоступным ровно из-за того, что она наконец прилипла. */
.cand-bulk .dd-pop { top: auto; bottom: calc(100% + 6px); }

.timeline { display: flex; flex-direction: column; gap: 0; }
.tl-row { display: grid; grid-template-columns: 1fr 118px; gap: 10px; padding: 9px 0; border-top: 1px solid var(--line); }
.tl-row:first-child { border-top: 0; }
.tl-text { font-size: 13px; }
.tl-actor { font-size: 11px; color: var(--muted-2); }
.tl-ts { font-size: 11px; color: var(--muted); text-align: right; }

/* ── переписка всплывающим окном ────────────────────────────────────────
   Замечание владельца 2026-09-03: «переписку лучше сделать справа кнопку или
   блок, и при нажатии всплывало окно, как во всех чатах поддержки на сайте».
   Раньше она стояла блоком в колонке карточки: место занимала как раздел, а
   нужна далеко не всегда — у большинства карточек диалога нет вовсе. */
/* Уровень 36, а не 45: кнопка обязана быть поверх страницы, но НИЖЕ
   окна письма (38) и модалок (40). На 45 она ложилась поверх всего —
   в том числе поверх полоски «отменить можно N сек.», и отменить
   отправку было нечем (замечание владельца 2026-09-22 со скриншотом). */
.chat-fab {
  position: fixed; right: 26px; bottom: 22px; z-index: 36;
  display: inline-flex; align-items: center; gap: 8px;
  height: 44px; padding: 0 18px; border: 0; border-radius: 999px;
  font: inherit; font-size: 14px; font-weight: 700; color: #fff;
  background: linear-gradient(170deg, #17a396, var(--accent));
  box-shadow: 0 16px 30px -14px rgba(12, 32, 39, 0.75); cursor: pointer;
}
.chat-fab:hover { filter: brightness(1.06); }
.chat-fab.on { background: linear-gradient(170deg, #143039, #0c2027); }
.chat-fab-ic { font-size: 16px; }
.chat-fab-n {
  min-width: 20px; padding: 1px 6px; border-radius: 999px;
  font-size: 12px; color: var(--accent-dark); background: #fff;
}

.chat-pop {
  position: fixed; right: 26px; bottom: 78px; z-index: 37;
  display: flex; flex-direction: column;
  width: 440px; max-width: calc(100vw - 52px); max-height: min(640px, 76vh);
  border-radius: var(--r-lg); background: var(--surface);
  box-shadow: 0 30px 60px -24px rgba(12, 32, 39, 0.55), var(--shadow-md);
  overflow: hidden;
}
.chat-pop-head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 13px 16px; border-bottom: 1px solid var(--line);
}
.chat-pop-head b { font-size: 14px; }
.chat-pop-body { flex: 1; min-height: 0; overflow-y: auto; padding: 14px 16px; }

/* Лента внутри окна тянется на всю его высоту, а не упирается в потолок,
   заданный для блока в карточке: окно и заводилось затем, чтобы переписку было
   видно целиком. */
/* Прокручивается САМА лента, а не обёртка вокруг неё. До 2026-09-07 было
   наоборот, и прокрутка «к последнему сообщению», которая ставит scrollTop
   ленте, в этом окне не работала вовсе: лента высоты не ограничивала, а
   крутилась обёртка, о которой код не знал. Кнопка «↓ N» тоже живёт у ленты. */
.chat-pop .tgc-feed { max-height: 46vh; }
.chat-pop .tgc-card-feed { max-height: none; overflow: visible; }

/* Поле ответа — обычной высоты, в один уровень с кнопкой отправки (замечание
   владельца 2026-09-03: «поле ввода текста можно сделать стандартным, а не
   таким большим»). В окне карточки высота на счёт: три строки поля отбирали её
   у самой переписки, а отвечают тут одной фразой. Тянуть больше — можно, за
   уголок: `resize: vertical` оставлен. */
.chat-pop .tgc-compose textarea { height: 40px; min-height: 40px; }

/* Лента истории на карточке колл-центра.
   Ограничена по высоте и прокручивается внутри себя: под ней ничего нет, но
   выше — исход звонка и скрипт, и лента лида с историей за год уводила бы их
   за верхний край ровно тогда, когда по ним и работают. */
/* Средняя колонка: высота ровно по экрану, и прокручивается ЛЕНТА, а не
   колонка целиком.

   Замечание владельца 2026-09-03: «центральная часть вся прокручивается
   теперь из-за истории; должна только внутри истории, остальным блокам
   незачем». Так и было: лента с потолком в 42vh делала содержимое колонки
   выше самой колонки, и вместе с историей уезжали скрипт и исход — то есть
   то, по чему работают ВО ВРЕМЯ разговора.

   Лента забирает остаток высоты (flex: 1) и прокручивается внутри себя. У
   `.calls .col > *` стоит `flex: none`, поэтому правило ниже обязано быть
   более частным — иначе остаток она не заберёт.

   min-height оставлен намеренно: на низком окне лента сожмётся до него, и
   дальше поедет уже колонка. Это хуже, но лучше, чем обрезать скрипт и исход
   без прокрутки вовсе. */
.calls .col.cc-main { height: calc(100vh - 100px); }
.calls .col.cc-main > .cc-hist {
  flex: 1 1 auto; min-height: 180px;
  display: flex; flex-direction: column; overflow: hidden;
}
.cc-hist #hst-slot { flex: 1; min-height: 0; overflow-y: auto; margin-top: 12px; }
.cc-hist .hst { padding: 8px 0; }

/* ── общая история карточки ─────────────────────────────────────────────
   Одна лента вместо списка звонков: звонки, правки полей, переходы этапов,
   задачи и заметки вперемешку, в порядке времени. Замечание владельца
   2026-09-03: «нет истории по лиду помимо звонков».

   Не таблица, потому что записи разного размера: звонок тянет проигрыватель
   и расшифровку на два экрана, смена этапа — полстроки. Столбцы по таким
   строкам не выравниваются. */
/* Лента — хронология, поэтому у неё есть НИТЬ: значки нанизаны на линию, и
   лента читается сверху вниз как одно, а не как стопка отдельных строк.
   Замечание владельца 2026-09-03: «историю можно сделать визуально получше».

   Линия рисуется фоном самой ленты, а не элементом в каждой строке: строк
   бывает двести, и лишний узел в каждой — это лишние двести. */
.hst-feed {
  position: relative;
  display: flex; flex-direction: column;
}
.hst-feed::before {
  content: ''; position: absolute; left: 13px; top: 10px; bottom: 10px;
  width: 2px; background: var(--line-2); border-radius: 2px;
}

.hst {
  position: relative;
  display: grid; grid-template-columns: 26px minmax(0, 1fr); gap: 12px;
  padding: 10px 0;
}
/* Разделителей между строками нет: их роль взяла нить. Две горизонтали на
   каждую запись — черта и рамка карточки — делали ленту решёткой. */

/* Канон значка ленты: белый круг 26px с серым кольцом, контурный глиф 14px по
   центру. Виды различаются ЦВЕТОМ глифа; заливка круга — только у следов
   живого действия (заметка, звонок). Глифы — свои SVG (см. HST_ICON в
   core.js): юникод-символы приезжали из разных запасных шрифтов и стояли
   вразнобой. */
.hst-ic {
  position: relative; z-index: 1;
  display: flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; border-radius: 999px;
  font-size: 12px; color: var(--muted);
  background: var(--surface); box-shadow: inset 0 0 0 2px var(--line-2);
}
.hst-ic svg { width: 14px; height: 14px; display: block; }
.hst-body { min-width: 0; padding-top: 3px; }
.hst-title { font-size: 13px; font-weight: 600; color: var(--text); line-height: 1.4; }
.hst-text { margin-top: 4px; font-size: 13px; line-height: 1.5; color: var(--text-3); white-space: pre-wrap; word-break: break-word; }
/* Свёрнутый текст. Тем же приёмом, что в ленте канала (.tg-text): четыре
   строки и кнопка. Кнопка — та же .tg-more, чтобы разворот в двух местах
   системы выглядел и вёл себя одинаково. */
.hst-text.clamp {
  display: -webkit-box; -webkit-box-orient: vertical;
  -webkit-line-clamp: 4; overflow: hidden;
}
.hst-body .tg-more { margin-top: 2px; }
.hst-meta { margin-top: 4px; font-size: 11px; color: var(--muted-2); }

/* Действие в строке ленты — пока только «снять задачу». Под мета-строкой, а не
   третьей колонкой справа: колонка отняла бы ширину у ВСЕХ записей ленты ради
   кнопки, которая бывает у одной из двадцати, а история читается текстом. */
.hst-act { margin-top: 8px; }

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

   Задача подложки НЕ получает: раньше получала, и вместе с ней подхватывала
   чужой класс `.task` — отсюда обрывки разной ширины. Задача остаётся строкой,
   как и прочий след действия. */
.hst-note .hst-body {
  padding: 10px 13px; border-radius: var(--r-md);
  background: #eef3f6;
}
.hst-note .hst-title { display: none; }
.hst-note .hst-ic { color: var(--accent-dark); background: #d9f2ef; box-shadow: inset 0 0 0 2px #bfe6e0; }
/* Своя заметка — другим фоном, как своё сообщение в переписке. */
.hst-note.hst-mine .hst-body { background: rgba(15, 118, 110, 0.1); }

/* Виды записей различаются ЗНАЧКОМ, а не фоном строки: фон на каждой второй
   записи превращает ленту в зебру и перестаёт что-либо значить. */
.hst-call .hst-ic { color: var(--accent-dark); background: #d9f2ef; box-shadow: inset 0 0 0 2px #bfe6e0; }
/* Три состояния задачи различаются значком И цветом. Раньше вид был один и
   значок один — галочка, — и заведённая минуту назад задача выглядела
   сделанной (замечание владельца 2026-09-05). Ждущая нарочно НЕ зелёная:
   зелёный в этой системе означает «готово», и им же красить незакрытое —
   значит врать боковым зрением, до чтения текста. */
.hst-task .hst-ic { color: var(--muted); }
.hst-taskdone .hst-ic { color: var(--accent-dark); }
.hst-taskdrop .hst-ic { color: var(--danger); }
/* Предупреждение — красный ГЛИФ и красный заголовок, круг остаётся белым с
   серым кольцом, как у всех. Красная заливка с красным кольцом делала значок
   чужим для ленты — «кружочек не по общим канонам» (владелец, 2026-09-05):
   тревогу несёт цвет и текст, а не второй канон геометрии. */
.hst-warn .hst-ic { color: var(--danger); }
.hst-warn .hst-title { color: var(--danger); }

/* Строка звонка приезжает готовой из истории звонков и рисует своё сама. */
.hst-call .tl-row { padding: 0; border-top: 0; }
.hst-call .hst-body { padding-top: 0; }

/* Маячок дорисовки ленты. Тем же приёмом, что у списка компаний и колонок
   воронки: показался — подгрузилась следующая страница. Цифра на нём
   обязательна: сорок записей без неё читаются как вся история, и человек
   делает вывод, что раньше ничего не было. */
.hst-more {
  margin-top: 6px; padding: 12px 0 4px;
  font-size: 12px; color: var(--muted); text-align: center;
}

/* Поле заметки — НАД лентой (замечание владельца 2026-09-03: «поле добавления
   лучше сверху сделать»). Свежее сверху, писать тоже сверху: иначе за полем
   ввода приходится пролистывать всю историю, а она у прожившего год лида в
   несколько экранов. */
.hst-compose {
  display: flex; gap: 8px; align-items: flex-end;
  margin-bottom: 12px; padding-bottom: 14px; border-bottom: 1px solid var(--line);
}
.hst-compose textarea { flex: 1; min-height: 44px; resize: vertical; }

/* ── мой день ───────────────────────────────────────────────────────────── */

.day-cols { display: grid; grid-template-columns: 1.75fr 1fr; gap: 18px; align-items: start; }
.group-t { margin: 18px 0 8px; font-size: 15px; font-weight: 800; letter-spacing: -0.02em; }
.group-t.late { color: var(--danger); }
.group-t:first-child { margin-top: 0; }

.task {
  display: flex; align-items: center; gap: 12px;
  background: #fff; border-radius: var(--r-md); box-shadow: var(--shadow-sm);
  padding: 13px 16px; margin-bottom: 8px;
}
.tick {
  width: 18px; height: 18px; min-width: 18px; border-radius: 999px;
  border: 1.5px solid var(--field); background: #fff; cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
}
.tick:hover { border-color: var(--accent); background: rgba(15, 118, 110, 0.08); }
.task .ttl { font-size: 14px; font-weight: 600; }
/* Заголовок-ссылка выглядит как заголовок, пока на него не навели: синее
   подчёркнутое в списке из двадцати строк превращает день в простыню ссылок.
   Тот же приём, что у названия компании на доске лидов (.lead .nm). */
a.ttl {
  display: block; color: var(--text); text-decoration: none;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
a.ttl:hover { color: var(--accent-dark); text-decoration: underline; }
/* Кликабельна вся строка — но только та, которой есть куда вести. */
.task.go { cursor: pointer; }
.task.go:hover { box-shadow: var(--shadow-md); }
.task .sub { font-size: 12px; color: var(--muted); }
.task .sp { margin-left: auto; display: flex; align-items: center; gap: 8px; }

.empty { padding: 34px 20px; text-align: center; color: var(--muted); }
.empty .ic {
  display: inline-flex; align-items: center; justify-content: center;
  width: 46px; height: 46px; margin-bottom: 10px;
  border-radius: var(--r-md); background: var(--soft); font-size: 20px;
}
.empty .h { font-size: 15px; font-weight: 700; color: var(--text); margin-bottom: 4px; }

/* ── модалка ────────────────────────────────────────────────────────────── */

/* Панель кандидата — поверх карточки вакансии.
   Выезжает справа, а не открывается по центру: под ней остаётся видна таблица
   вакансии, и понятно, откуда пришли и куда вернёмся.

   Ширина — под две колонки содержимого. Расширена 2026-09-01 по решению
   владельца: в письменных ответах теста строки по десять слов ломались
   посреди мысли, а правая колонка с действиями поджимала левую. Верхняя
   граница не убрана вовсе — на широком мониторе панель во весь экран
   перестаёт быть панелью и ничем не отличается от отдельной страницы. */
.panel-wrap {
  position: fixed; inset: 0; z-index: 35;
  display: flex; justify-content: flex-end;
  background: rgba(14, 36, 44, 0.42); backdrop-filter: blur(2px);
}
.panel {
  /* flex-basis вместо width: слева от карточки может встать вторая панель
     (резюме с hh.ru), и тогда место делят двое. Пока соседа нет, вид прежний:
     та же ширина и тот же предел. container-type — чтобы две колонки внутри
     считались по ширине САМОЙ панели, а не окна: окно широкое, а места у
     карточки может не быть. */
  flex: 0 1 min(1180px, 100%); min-width: 0; height: 100%;
  display: flex; flex-direction: column;
  background: var(--soft); container-type: inline-size;
  box-shadow: -28px 0 64px -30px rgba(14, 36, 44, 0.55);
}
@container (max-width: 900px) {
  .panel .cols { grid-template-columns: 1fr; }
}
.panel-head {
  flex: none; display: flex; align-items: flex-start; gap: 12px;
  padding: 18px 22px; background: #fff; border-bottom: 1px solid var(--line);
}
.panel-head h3 { margin: 2px 0 0; font-size: 21px; letter-spacing: -0.02em; }
.panel-head .x {
  flex: none; width: 30px; height: 30px; border: 0; border-radius: 9px;
  font-size: 20px; line-height: 1; color: var(--muted);
  background: var(--soft); cursor: pointer;
}
.panel-head .x:hover { background: #e6edf0; color: var(--text); }
/* Прокручивается содержимое, а не панель целиком: шапка с именем и этапом
   должна остаться на виду, иначе, уехав вверх, она перестаёт отвечать на
   вопрос «чью карточку я смотрю». */
.panel-body { flex: 1; min-height: 0; overflow-y: auto; padding: 18px 22px 40px; }

/* Имя кандидата — кнопка, а не ссылка: она открывает панель, а не переход.
   Выглядеть при этом должна как прежде. */
button.cand-name {
  padding: 0; border: 0; background: none; font: inherit; font-weight: 700;
  color: inherit; text-align: left; cursor: pointer;
}
button.cand-name:hover { color: var(--accent-dark); }

.overlay {
  position: fixed; inset: 0; z-index: 40;
  display: flex; align-items: center; justify-content: center; padding: 24px;
  background: rgba(14, 36, 44, 0.48); backdrop-filter: blur(2px);
}
.modal {
  width: min(560px, 100%); max-height: 88vh; overflow: auto;
  background: #fff; border-radius: var(--r-xl);
  box-shadow: 0 34px 64px -28px rgba(14, 36, 44, 0.55); padding: 22px;
}
.modal-head { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; }
.modal-head .x {
  margin-left: auto; width: 30px; height: 30px; border: 0; border-radius: 999px;
  background: var(--soft); color: var(--text-3); font-size: 16px; cursor: pointer;
}
.modal-body { display: flex; flex-direction: column; gap: 13px; }

/* Отказ с письмом: слева причина, справа переписка и текст (замечание
   владельца 2026-09-07). Модалка при этом шире обычной — решение об отправке
   принимают, глядя на разговор, а в узкую колонку он не читается. */
.rej-cols { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr); gap: 18px; }
/* :has поддерживают все нынешние браузеры; если бы не поддержали, модалка
   осталась бы узкой — колонки встали бы друг под другом, а не сломались. */
.modal:has(.rej-cols) { width: min(1180px, 100%); }
/* Переписка здесь — та же карточка tgc-card, что в панели кандидата: вид
   задаётся её правилами, а не своими. Отсюда только высота ленты: окно выше
   карточки, и обрезать разговор до трёхсот точек здесь незачем. */
.rej-chat { display: flex; flex-direction: column; gap: 13px; min-width: 0; }
.rej-chat .tgc-card { margin: 0; }
.rej-chat .tgc-feed { max-height: 42vh; }
@media (max-width: 860px) {
  .rej-cols { grid-template-columns: minmax(0, 1fr); }
}
.modal-foot { display: flex; justify-content: flex-end; gap: 8px; margin-top: 18px; }
.two { display: grid; grid-template-columns: 1fr 1fr; gap: 13px; }

/* Ряд полей разной ширины. Настройки заполняют раз в жизни, а поля во всю
   ширину растягивали форму на несколько экранов прокрутки — при том, что
   читать в ней нечего: половина строки под поле «Опрос, секунд». */
.fields-3 { display: grid; grid-template-columns: 2fr 1.3fr 0.7fr; gap: 13px; align-items: start; }
/* Пара полей поровну: ключ и его секрет, которые заполняют вместе и читают
   рядом. На узком экране — в столбик, иначе оба поля становятся нечитаемо
   короткими. */
.fields-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 13px; align-items: start; }
@media (max-width: 720px) { .fields-2 { grid-template-columns: 1fr; } }

/* Готовый адрес, который не правят, а копируют. Одной строкой с многоточием:
   развёрнутый на три строки он занимал больше места, чем всё остальное в
   карточке, а прочитать его целиком всё равно нельзя — там секрет. */
.urlbox {
  min-width: 0; padding: 9px 12px; border-radius: var(--r-md);
  border: 1.5px solid var(--line-2); background: var(--soft);
  font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 12px;
  color: var(--text-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* ── пояснения «?» ──────────────────────────────────────────────────────── */

/* Значок вместо абзаца. Справка «как это устроено» нужна один раз — когда
   человек настраивает или видит экран впервые. Дальше она каждый день занимает
   место и отодвигает вниз то, ради чего на экран пришли. Поэтому текст
   сворачивается в значок у заголовка или подписи поля.

   Значок — не декорация: он должен читаться как нажимаемый, иначе справку
   просто не найдут. Отсюда рамка, а не голая буква. */
.help {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 16px; height: 16px; padding: 0; vertical-align: middle;
  border: 1.5px solid var(--field); border-radius: 999px;
  font: inherit; font-size: 11px; font-weight: 800; line-height: 1;
  color: var(--muted); background: #fff; cursor: pointer;
  transition: color 0.15s, border-color 0.15s, background 0.15s;
}
.help:hover, .help.on { color: #fff; border-color: transparent; background: var(--accent); }

/* В мелких надзаголовках кружок нормального размера перевешивает сам текст:
   там подпись 10px, а значок 16. */
.card-t .help, .head-cap .help, .field label .help,
table.t th .help { width: 15px; height: 15px; font-size: 10px; }

/* Тёмная карточка — класс, а не наследование от `.card`: тёмный фон там задан
   инлайном, и правило «внутри карточки» перекрасило бы значки на всех светлых
   карточках тоже. Белый кружок на тёмном читался бы как кнопка действия, а
   справка кнопкой действия быть не должна. */
.help.on-dark {
  border-color: rgba(232, 241, 243, 0.32); color: #9db6bf; background: transparent;
}
.help.on-dark:hover, .help.on-dark.on {
  border-color: transparent; color: #0e242c; background: #9dd7cf;
}

/* Попап живёт в своём корне и позиционируется от окна, а не от значка.
   Значки стоят внутри карточек и прокручиваемых списков: обычный absolute
   обрезался бы по краю карточки ровно там, где текст длиннее двух строк. */
.help-pop {
  position: fixed; z-index: 50; width: min(340px, calc(100vw - 24px));
  padding: 13px 15px; border-radius: 14px;
  background: #fff; color: var(--text-3);
  font-size: 13px; font-weight: 500; line-height: 1.55;
  box-shadow: 0 24px 44px -22px rgba(14, 36, 44, 0.6), inset 0 0 0 1px #e4edf0;
}
.help-pop b { font-weight: 700; color: var(--text-2); }
.help-pop code {
  padding: 1px 5px; border-radius: 5px;
  font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 12px;
  background: var(--soft);
}
.help-pop p + p { margin-top: 8px; }
.help-pop a { color: var(--accent); }

.pills { display: flex; flex-wrap: wrap; gap: 6px; }
.pill {
  padding: 6px 12px; border: 1.5px solid var(--field); border-radius: 999px;
  font: inherit; font-size: 13px; font-weight: 600; color: var(--text-3);
  background: #fff; cursor: pointer; transition: all 0.15s;
}
.pill:hover { border-color: var(--accent); }
.pill.on { color: #fff; border-color: transparent; background: var(--accent); }

/* Недоступный этап — приглушённый контур без наведения.
   До этого он выглядел точно так же, как нажимаемый, и ряд читался как набор
   случайных обводок вокруг единственной цветной кнопки (замечание владельца
   2026-09-03). Текущий этап под это правило не попадает: он `.on`, он цветной
   и заблокирован по другой причине — на себя не переводят. */
.pill:disabled:not(.on) {
  color: var(--muted-2); border-color: var(--line-2);
  background: var(--soft); cursor: default;
}
.pill:disabled:not(.on):hover { border-color: var(--line-2); }
.pill.on:disabled { cursor: default; }

/* Мелкая плашка — для отметки состояния прямо на карточке в списке. Карточки
   и так под замечанием «вышли жирные», поэтому размер здесь меньше обычной
   плашки: пара кнопок в подвале не должна прибавлять карточке строку. */
.pill.sm { padding: 3px 9px; font-size: 11px; font-weight: 700; }
.work-sw { display: flex; gap: 4px; flex: none; }

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

.toast {
  position: fixed; left: 50%; bottom: 26px; z-index: 60; transform: translateX(-50%);
  max-width: 620px; padding: 11px 20px; border-radius: 999px;
  font-size: 13px; font-weight: 600; color: #e8f1f3;
  background: linear-gradient(170deg, #143039, #0c2027);
  box-shadow: 0 20px 38px -22px rgba(12, 32, 39, 0.9);
}
.toast.err { background: linear-gradient(170deg, #7c1d13, #5a140d); }

/* ── уведомления ────────────────────────────────────────────────────────── */

/* Стопка всплывашек в правом нижнем углу — там же, где их рисует Windows,
   поэтому взгляд ищет их в одном месте независимо от того, свёрнута вкладка
   или нет.

   Ширина ограничена: уведомление это заголовок и одна строка сути, а не
   письмо. Всё, что длиннее, читают на экране уведомлений. */
.ntf-stack {
  position: fixed; right: 22px; bottom: 22px; z-index: 70;
  display: flex; flex-direction: column-reverse; gap: 10px;
  width: min(360px, calc(100vw - 44px));
  pointer-events: none;
}
/* Стопка сквозная для нажатий, сами окна — нет: иначе невидимый край стопки
   перехватывал бы клики по интерфейсу под ней. */
.ntf {
  pointer-events: auto;
  padding: 13px 15px; border-radius: var(--r-md);
  color: #e8f1f3; background: linear-gradient(170deg, #143039, #0c2027);
  box-shadow: 0 20px 38px -22px rgba(12, 32, 39, 0.9);
  animation: ntf-in 160ms ease-out;
}
.ntf.warn { background: linear-gradient(170deg, #7a3b0c, #55290a); }
.ntf.go { cursor: pointer; }
.ntf.go:hover { filter: brightness(1.08); }
.ntf-head { display: flex; align-items: start; gap: 10px; }
.ntf-title { flex: 1; font-size: 13px; font-weight: 700; }
.ntf-x {
  flex: none; width: 20px; height: 20px; padding: 0; line-height: 1;
  border: 0; border-radius: 999px; cursor: pointer;
  font-size: 15px; color: #cfe0e4; background: rgba(255, 255, 255, 0.08);
}
.ntf-x:hover { background: rgba(255, 255, 255, 0.18); }
/* Перенос по строкам сохраняется: подпись собирается на сервере как
   «имя
вакансия», и без этого обе части слипаются в одну строку. */
.ntf-body { margin-top: 5px; font-size: 12.5px; line-height: 1.45; white-space: pre-line; }
.ntf-foot { margin-top: 7px; font-size: 11px; color: #9db8c0; }
.ntf.more .ntf-body { margin-top: 0; font-weight: 600; }

/* Анимация только сдвигает и НЕ трогает непрозрачность.
   Причина: если анимация почему-то не доиграет — вкладка в фоне, браузер
   придушил отрисовку, — элемент с opacity в кадрах остаётся невидимым. То есть
   уведомление, ради которого всё и делалось, не показывается. Сдвиг в такой
   ситуации в худшем случае оставит окно на восемь точек ниже места. */
@keyframes ntf-in {
  from { transform: translateY(8px); }
  to   { transform: translateY(0); }
}

/* ── колокольчик и его панель ───────────────────────────────────────────── */

/* Колокольчик стоит в шапке сайдбара, а не пунктом меню: уведомление это не
   раздел работы, а то, что отвлекает от текущего дела. */
.bell {
  position: relative; margin-left: auto;
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; padding: 0;
  border: 0; border-radius: 999px; cursor: pointer;
  color: #9db6bf; background: rgba(255, 255, 255, 0.06);
  transition: background 0.15s, color 0.15s;
}
.bell:hover, .bell.on { color: #e8f1f3; background: rgba(255, 255, 255, 0.16); }
.bell svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 1.7;
  stroke-linecap: round; stroke-linejoin: round; }
.bell.has { color: #bcdcda; }
/* Счётчик — единственное, что должно бросаться в глаза в тёмном сайдбаре. */
.bell-count {
  position: absolute; top: -3px; right: -3px; min-width: 16px; height: 16px;
  padding: 0 4px; border-radius: 999px;
  font-size: 10px; font-weight: 800; line-height: 16px; text-align: center;
  color: #0b1d24; background: #5eead4;
}

/* Панель висит поверх рабочей области рядом с сайдбаром: внутри сайдбара она
   обрезалась бы его собственной прокруткой. */
.bell-panel {
  position: fixed; left: 274px; top: 12px; z-index: 65;
  width: min(380px, calc(100vw - 290px));
  display: flex; flex-direction: column; max-height: calc(100vh - 24px);
  background: var(--surface); border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);
  animation: ntf-in 140ms ease-out;
}
.bell-head {
  display: flex; align-items: baseline; gap: 8px;
  padding: 14px 16px 10px; border-bottom: 1px solid var(--line);
}
.bell-head b { font-size: 15px; }
.bell-head-sub { margin-left: auto; font-size: 12px; color: var(--muted); }
/* Чья это лента. Вопрос владельца 2026-09-03: «не пойму, уведомления общие что
   ли, а не отдельные по пользователям». Лента и была личной — но об этом нигде
   не говорилось, а два человека в одной роли видели одно и то же. */
.bell-who {
  padding: 8px 14px 10px; border-bottom: 1px solid var(--line);
  font-size: 11px; line-height: 1.4; color: var(--muted);
}
.bell-list { overflow-y: auto; }
.bell-empty { padding: 22px 16px; font-size: 13px; color: var(--muted); }
.bell-empty b { display: block; margin-bottom: 6px; font-size: 14px; color: var(--text-2); }

/* Непрочитанное помечено полосой слева, а не цветом фона: фоном уже помечают
   просрочки, и два смысла одним приёмом читаются как один. */
.bell-row {
  display: block; padding: 11px 16px 12px;
  border-left: 3px solid transparent; border-bottom: 1px solid var(--line);
  color: inherit; text-decoration: none;
}
.bell-row:hover { background: var(--soft); }
.bell-row.new { border-left-color: var(--accent); }
.bell-row.warn.new { border-left-color: var(--warn); }
.bell-row-cap { font-size: 11px; color: var(--muted); }
.bell-row-title { margin-top: 2px; font-size: 14px; font-weight: 700; }
.bell-row-body { margin-top: 2px; font-size: 12.5px; color: var(--text-2); white-space: pre-line; }

/* Хвост списка: сколько непрочитанного не поместилось в панель. Он не строка
   уведомления и не должен на неё походить — иначе его пробуют нажать. */
.bell-more {
  padding: 10px 16px; font-size: 12px; color: var(--muted);
  border-bottom: 1px solid var(--line); background: var(--soft);
}

.bell-foot {
  display: flex; gap: 8px; align-items: center;
  padding: 11px 16px; border-top: 1px solid var(--line);
}
.bell-note { padding: 11px 16px; font-size: 12px; line-height: 1.45; color: var(--text-2); background: var(--soft); }
.bell-note.warn { color: var(--warn); background: var(--warn-bg); }
.bell-note.ask { display: flex; align-items: center; gap: 10px; }
.bell-note.ask > div { flex: 1; }

/* ── профиль в сайдбаре и на своём экране ───────────────────────────────── */

.me {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px; margin-bottom: 4px; border-radius: var(--r-md);
  color: #cfe0e4; text-decoration: none;
  transition: background 0.15s;
}
.me:hover, .me.on { background: rgba(255, 255, 255, 0.07); }
.me-txt { min-width: 0; display: flex; flex-direction: column; line-height: 1.25; }
.me-txt b { font-size: 13px; font-weight: 700; color: #e8f1f3;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.me-txt span { font-size: 11px; color: #8aa9b3; }
.me-gear { margin-left: auto; font-size: 13px; color: #7f9ca6; }

/* Кружок: инициалы либо картинка. Размеры общие, чтобы подмена одного другим
   не двигала соседние элементы. */
.me-ava, .me-big {
  display: inline-flex; align-items: center; justify-content: center;
  flex: none; border-radius: 999px; object-fit: cover;
  font-weight: 800; letter-spacing: -0.02em;
  color: var(--accent-dark); background: linear-gradient(120deg, #d9f2ef, #c3e9e3);
}
.me-ava { width: 32px; height: 32px; font-size: 12px; }
.me-big { width: 84px; height: 84px; font-size: 26px; }

.me-row { display: flex; align-items: flex-start; gap: 18px; }

/* ── пометка гипотезы ───────────────────────────────────────────────────── */

/* Нормативы не подтверждены замером (решение владельца 2026-08-30). Пометка
   обязана быть видимой: иначе выдуманная просрочка читается как настоящая. */
.hypo {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 8px; border-radius: 999px;
  font-size: 10px; font-weight: 700; color: var(--warn); background: var(--warn-bg);
}
/* Обычный блок, а не флекс: внутри только текст, и <b> в нём должен оставаться
   частью строки. Во флексе каждый вложенный тег становится отдельным элементом
   с отступом — строка рвётся, а выделенное слово повисает в стороне. */
.hypo-bar {
  margin-bottom: 16px; padding: 9px 14px; border-radius: var(--r-md);
  font-size: 12px; line-height: 1.5; color: var(--warn); background: var(--warn-bg);
}
.hypo-bar b { font-weight: 700; }
.hypo-bar a { color: var(--warn); text-decoration: underline; }

/* ── вкладки ────────────────────────────────────────────────────────────── */

/* Полоса вкладок должна читаться как ОДИН переключатель, а не как строчка
   отдельных надписей. Держится это на двух вещах: подложке заметно темнее
   страницы и выбранной вкладке заметно светлее подложки.
   Замечание владельца 2026-09-03: «табы в настройках были покрасивее задуманы,
   вроде не хватает каких-то цветов на фоне». Так и было: подложка #eaf0f3
   отличалась от фона страницы #eff3f6 на пару процентов — на трёх вкладках это
   ещё угадывалось, а на восьми полоса растянулась и слилась с фоном совсем. */
.tabs {
  display: inline-flex; gap: 3px; padding: 3px;
  border-radius: 999px; background: var(--line-2);
}
/* Вкладка бывает и ссылкой: там, где выбранная вкладка должна пережить
   перезагрузку, она живёт в адресе (`#/settings/<вкладка>`) и рисуется <a>.
   Вид у обеих один — полоса не должна выдавать, чем вкладка сделана. */
.tabs button, .tabs a {
  padding: 7px 15px; border: 0; border-radius: 999px;
  font: inherit; font-size: 13px; font-weight: 600; color: var(--text-3);
  background: transparent; cursor: pointer; transition: background 0.15s, color 0.15s;
  text-decoration: none; white-space: nowrap;
}
.tabs button:hover, .tabs a:hover { color: var(--text); background: rgba(255, 255, 255, 0.5); }
.tabs button.on, .tabs a.on {
  color: var(--text); background: #fff;
  box-shadow: 0 6px 14px -8px rgba(22, 48, 58, 0.75);
}
.tabs .n { opacity: 0.6; margin-left: 5px; }

/* Приглушённая вкладка: архив отвалившихся. Замечание владельца 2026-09-03 —
   «доступ к ним непримечательный». Отделена чертой и приглушена: это не ещё
   один разрез живой базы, а другое место, куда заходят по поводу. Выбранной
   она выглядит как все — раз уж зашли, список должен читаться нормально. */
/* Отделяется отступом, а НЕ внутренней тенью-чертой.
   Замечание владельца 2026-09-03 («странные обводки, как битые пиксели»):
   inset-тень на кнопке со скруглением 999px рисуется не чертой, а
   полумесяцем вдоль всей дуги — и выглядит именно как грязь на границе. */
.tabs button.quiet { margin-left: 10px; color: var(--muted-2); }

/* ── доска воронки продаж ───────────────────────────────────────────────── */

/* Карточки прокручиваются ВНУТРИ колонки, а не страницей (решение владельца
   2026-09-02). До этого колонки росли на всю высоту: после выгрузки amoCRM
   «Новый лид» стал в три экрана, и единственная полоса горизонтальной
   прокрутки доски уехала под него — доску нельзя было пролистнуть вбок, не
   долистав страницу до самого низа. Потолок в 330px — прикидка на случай
   выключенного JS; рабочую высоту колонкам ставит sizeLanes в
   screen-leads.js, по замеру фактического верха доски: контент над ней
   переменной высоты, и жёсткая константа оставляла бегунок за краем окна. */
.board { display: flex; gap: 14px; align-items: flex-start; overflow-x: auto; padding-bottom: 12px; }
.board .lane { flex: 0 0 268px; display: flex; flex-direction: column; gap: 9px; }
.board .lane-body { max-height: calc(100vh - 330px); overflow-y: auto; }
/* flex: none обязателен: lane-body — flex-колонка, и без него ограниченная
   высота не прокручивает карточки, а УЖИМАЕТ их — они наезжают друг на друга.
   То же правило и по той же причине стоит у .calls .col выше. */
.board .lane-body > * { flex: none; }
.lane-head { background: #fff; border-radius: var(--r-md); box-shadow: var(--shadow-sm); padding: 13px 15px; }
.lane-head.last { color: #e8f1f3; background: linear-gradient(120deg, var(--accent), var(--accent-500)); }
.lane-head.last .cap, .lane-head.last .sub { color: rgba(255, 255, 255, 0.8); }
.lane-head .cap { font-size: 10px; font-weight: 700; letter-spacing: 0.09em; text-transform: uppercase; color: var(--muted); }
.lane-head .ttl { display: flex; align-items: baseline; gap: 7px; margin-top: 3px; }
.lane-head .ttl b { font-size: 15px; font-weight: 800; letter-spacing: -0.02em; }
.lane-head .ttl span { font-size: 13px; font-weight: 700; opacity: 0.7; }
.lane-head .sub { margin-top: 4px; font-size: 11px; color: var(--muted); }

.lane-body { display: flex; flex-direction: column; gap: 8px; min-height: 60px; padding: 4px; border-radius: var(--r-md); transition: background 0.15s, box-shadow 0.15s; }
.lane-body.over { background: rgba(15, 118, 110, 0.07); box-shadow: inset 0 0 0 1.5px var(--accent); }

.lead {
  position: relative; overflow: hidden;
  background: #fff; border-radius: var(--r-md); box-shadow: var(--shadow-sm);
  padding: 9px 11px 9px 14px; cursor: grab;
}
.lead-top { display: flex; gap: 8px; align-items: flex-start; }
.lead:active { cursor: grabbing; }
.lead.dragging { opacity: 0.4; }
.lead::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 4px; background: var(--accent-700); }
.lead.late::before { background: var(--danger); }
/* Заголовок карточки сам работает ссылкой: отдельная кнопка «Открыть» стоила
   целой строки на каждой карточке, а их на доске тысячи. */
.lead .nm {
  display: block; font-size: 13px; font-weight: 700; line-height: 1.3;
  color: var(--text); text-decoration: none;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.lead .nm:hover { color: var(--accent-dark); text-decoration: underline; }
.lead .ct {
  margin-top: 1px; font-size: 11px; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.lead .row { display: flex; align-items: center; gap: 6px; margin-top: 6px; flex-wrap: wrap; }
.lead .row .ct { margin-top: 0; }
.lead .amt { font-size: 12px; font-weight: 700; color: var(--text-2); white-space: nowrap; }

.ini {
  display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; min-width: 38px; border-radius: var(--r-md);
  font-size: 13px; font-weight: 800; letter-spacing: -0.02em;
  color: var(--accent-dark); background: linear-gradient(120deg, #d9f2ef, #c3e9e3);
}
.ini.sm { width: 26px; height: 26px; min-width: 26px; font-size: 10px; border-radius: var(--r-sm); }

/* ── колл-центр ─────────────────────────────────────────────────────────── */

.calls { display: grid; grid-template-columns: 292px minmax(420px, 1fr) 288px; gap: 16px; align-items: start; }
/* Вычитаемое — это то, что стоит НАД колонками: отступ рабочей области плюс
   шапка экрана. Замерено 2026-09-03 в обеих ролях: колонки начинаются на 84-й
   точке, 16 остаётся зазором снизу.

   Было 210 — число от прежней раскладки, когда над колонками стояло больше.
   После того как строка поиска переехала в шапку нулевой высоты, а отступ
   рабочей области сжался, колонки стали обрываться на 126 точек выше нижнего
   края окна: замечание владельца «страница колл-центра не до конца экрана
   добегает, как будто обрезана».

   Число проверяется замером, а не на глаз: если над колонками что-то добавят,
   оно снова разъедется — но уже в другую сторону, и страница начнёт
   прокручиваться вместо того, чтобы помещаться. */
.calls .col { display: flex; flex-direction: column; gap: 9px; max-height: calc(100vh - 100px); overflow-y: auto; }
.calls .col > * { flex: none; }

.qcard { background: #fff; border-radius: var(--r-md); box-shadow: var(--shadow-sm); padding: 12px 14px; cursor: pointer; position: relative; overflow: hidden; }
.qcard.on { box-shadow: 0 18px 34px -18px rgba(15, 118, 110, 0.55), inset 0 0 0 1.5px var(--accent); }
.qcard.on::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 4px; background: linear-gradient(180deg, var(--accent), var(--accent-500)); }
.qcard .nm { font-size: 14px; font-weight: 700; padding-right: 62px; }
.qcard .ct, .qcard .ph { font-size: 12px; color: var(--muted); }

/* Действия над тестом — при наведении на карточку. Держатся поверх правого
   верхнего угла, поэтому у .nm справа отступ: длинное название иначе уезжало
   бы под кнопки. */
.qcard-acts {
  position: absolute; top: 8px; right: 8px; display: flex; gap: 4px;
  opacity: 0; transition: opacity 0.12s;
}
.qcard:hover .qcard-acts, .qcard-acts:focus-within { opacity: 1; }
.qcard-acts .icon-btn {
  width: 26px; height: 26px; min-width: 26px;
  display: inline-flex; align-items: center; justify-content: center;
}
/* Без мыши наведения не бывает: на планшете кнопки должны быть видны сразу. */
@media (hover: none) { .qcard-acts { opacity: 1; } }

.hero {
  color: #e8f1f3; border-radius: var(--r-xl); padding: 20px 22px;
  background: linear-gradient(122deg, #123742 0%, #0f5b58 52%, #0f766e 100%);
  box-shadow: 0 20px 38px -24px rgba(12, 32, 39, 0.85), inset 0 1px 0 rgba(255, 255, 255, 0.12);
}
.hero .cap { display: flex; align-items: center; gap: 7px; font-size: 10px; font-weight: 700; letter-spacing: 0.09em; text-transform: uppercase; color: #bcdcda; }
.hero h3 { margin-top: 9px; font-size: 26px; color: #fff; }
.hero .sub { margin-top: 4px; font-size: 13px; color: #bcdcda; }

/* Правка названия прямо в шапке разговора.
 *
 * Карандашик приглушён и проявляется при наведении: он рядом с именем клиента,
 * на которое смотрят весь разговор, и яркая кнопка там мозолила бы глаза ради
 * действия, которое случается раз в неделю. Совсем прятать нельзя — тогда о
 * возможности узна́ют только те, кому про неё расскажут. */
.hero h3.cc-name { display: flex; align-items: center; gap: 8px; }
.hero h3.cc-name.cc-name-edit { display: block; }
.cc-pen {
  border: 0; background: rgba(255, 255, 255, 0.12); color: #d7efec;
  width: 26px; height: 26px; min-width: 26px; border-radius: 999px;
  font-size: 13px; line-height: 1; cursor: pointer; opacity: 0.55;
  transition: opacity 0.15s ease, background 0.15s ease;
}
.hero:hover .cc-pen { opacity: 1; }
.cc-pen:hover { background: rgba(255, 255, 255, 0.24); }
.cc-pen:focus-visible { opacity: 1; outline: 2px solid #5eead4; outline-offset: 2px; }
/* Без мыши наведения не бывает — на планшете кнопка видна сразу. */
@media (hover: none) { .cc-pen { opacity: 1; } }

.cc-name-input {
  width: 100%; font: inherit; color: #fff;
  background: rgba(0, 0, 0, 0.22); border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: var(--r-sm); padding: 2px 8px;
}
.cc-name-input:focus { outline: 2px solid #5eead4; outline-offset: 1px; }
.cc-name-hint { margin-top: 4px; font-size: 11px; font-weight: 400; color: #bcdcda; }
.hero .meta { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 13px; }
.hero .tag { color: #d7efec; background: rgba(255, 255, 255, 0.12); }
.hero .tag-danger { color: #ffd9d3; background: rgba(255, 120, 100, 0.2); }
.dot-live { width: 9px; height: 9px; border-radius: 999px; background: #5eead4; animation: pulse 1.7s ease-in-out infinite; }

.wave { display: flex; align-items: flex-end; gap: 2px; height: 26px; }
.wave span { width: 3px; border-radius: 2px; background: rgba(94, 234, 212, 0.55); }

.step-list { display: flex; flex-direction: column; }
.step { display: flex; gap: 11px; padding: 7px 0; }
.step .n {
  display: flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; min-width: 24px; border-radius: 999px;
  font-size: 12px; font-weight: 700; color: var(--muted); background: var(--soft);
}
.step.on .n { color: #fff; background: var(--accent); }
.step.done .n { color: var(--accent-dark); background: #c3e9e3; }
.step .t { font-size: 13px; font-weight: 600; color: var(--text-3); padding-top: 3px; }
.step.on .t { color: var(--text); }

/* Ответы шага. Высота не меньше двух рядов кнопок: на одних шагах три ответа
   влезают в строку, на других переносятся — и карточка «Итог звонка» прыгала
   на сорок точек между шагами. Ряд — это кнопка 35px плюс отбивка 8px. */
.script-opts { margin-top: 14px; min-height: calc((35px + 8px) * 2); }

/* Реплика шага скрипта.
   Высота не меньше трёх строк: у шагов реплики разной длины, и без этого
   переход на следующий шаг двигал карточку «Итог звонка» вверх на семьдесят
   точек — ровно тогда, когда оператор в неё целится. Три строки покрывают все
   реплики наших скриптов (самая длинная — 112 знаков при этой ширине).
   Число складывается из 3 × line-height (27px) и вертикальных полей (32px);
   поменяете шрифт или поля — пересчитайте. */
.line {
  padding: 16px 18px; border-radius: var(--r-md); background: var(--soft);
  font-size: 18px; font-weight: 500; letter-spacing: -0.015em; line-height: 1.5;
  min-height: calc(27px * 3 + 32px);
}

/* ── редакторы: скрипты, тест, шаблон брифа ─────────────────────────────── */

.three { display: grid; grid-template-columns: 280px 260px 1fr; gap: 16px; align-items: start; }

/* Конструктор теста: середина — вопросы, им нужно место. У `.three` середина
   узкая (она рассчитана на список шагов скрипта), и поле вопроса схлопывалось
   до пары сантиметров. */
.tests-cols { display: grid; grid-template-columns: 264px 1fr 300px; gap: 16px; align-items: start; }

/* Карточка вопроса: текст на своей строке во всю ширину, под ним — вид и
   удаление. Пока всё лежало в одной строке, текст делил ширину с выпадающим
   списком и проигрывал. */
.q-card { margin-bottom: 12px; }
.q-card .q-head { display: flex; gap: 10px; align-items: center; margin-top: 10px; }
.q-card .q-head .kind { width: 210px; flex: none; }
.q-card textarea { min-height: 58px; }

/* Категория: название во всю ширину, код — второй строкой мелким полем.
   Раньше они делили одну строку, и на название оставалось 90px. */
.cat-row { padding: 9px 0; border-top: 1px solid var(--line); }
.cat-row:first-child { border-top: 0; padding-top: 0; }
.cat-row .top { display: flex; gap: 8px; align-items: center; }

/* Строка поля брифа — одной линией: название, подсказка, обязательность и две
   кнопки. Раньше на поле уходило три строки, и одиннадцать полей занимали
   полтора экрана при том, что правят их раз в жизни шаблона. */
.brief-row, .brief-cap {
  display: grid;
  grid-template-columns: minmax(120px, 1fr) minmax(120px, 1.05fr) 172px 92px 92px 30px 30px;
  gap: 8px; align-items: center;
}
.brief-row { padding: 7px 0; }
/* Шапка колонок: настроек у поля стало пять, и без подписей «⅓ ½ 1» читается
   как ребус. */
.brief-cap {
  padding-bottom: 7px;
  font-size: 10px; font-weight: 700; letter-spacing: 0.09em;
  text-transform: uppercase; color: var(--muted);
}

/* Переключатель ширины: три доли строки. */
.wsel { display: flex; gap: 3px; }
.wsel button {
  flex: 1; padding: 6px 0; border: 0; border-radius: var(--r-sm);
  font: inherit; font-size: 12px; font-weight: 700;
  color: var(--text-3); background: var(--soft); cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
.wsel button:hover { color: var(--accent-dark); background: #d9f2ef; }
.wsel button.on { color: #fff; background: var(--accent-700); }
.brief-row input { padding: 7px 11px; font-size: 13px; }
.brief-row .pill { justify-content: center; font-size: 11px; padding: 6px 10px; }

/* Поле шаблона целиком: строка настроек плюс — у списков — варианты ответа.
   Линия рисуется здесь, а не на строке, иначе она отрезала бы варианты от
   поля, к которому они относятся. */
.brief-item { border-top: 1px solid var(--line); }
.brief-item:first-child { border-top: 0; }

/* Варианты списка свёрнуты в сводку и разворачиваются для правки.
   Раньше каждый вариант был строкой во всю ширину: поле с пятью вариантами
   занимало пол-экрана, и шаблон из двенадцати полей приходилось настраивать,
   прокручивая мимо того, что править не собирался. */
.brief-opts {
  margin: 2px 0 12px; padding: 10px 12px;
  border-radius: var(--r-md); background: var(--soft);
}
.brief-opts > summary {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px;
  cursor: pointer;
  /* Системный маркер убран: он разный в разных браузерах и ломает
     выравнивание первой строки. Своя стрелка ниже. */
  list-style: none;
}
.brief-opts > summary::-webkit-details-marker { display: none; }
.brief-opts > summary::before {
  content: "▸"; flex: none; font-size: 11px; color: var(--muted);
}
.brief-opts[open] > summary::before { content: "▾"; }
.brief-opts > summary:hover .cap { color: var(--text-3); }
.brief-opts .cap { flex: none; font-size: 11px; color: var(--muted); }
/* Плашки — только сводка, править их нельзя: правят в развёрнутом виде.
   Перенос обязателен, иначе длинный список уводит строку за край карточки. */
.opt-tags { display: flex; flex-wrap: wrap; gap: 5px; min-width: 0; }
/* «и ещё N» — счётчик, а не вариант с таким названием: без отличия его
   читают как седьмой вариант списка. */
.opt-tags .tag.more { color: var(--muted); background: transparent; box-shadow: inset 0 0 0 1px var(--line-2); }
.opt-edit { display: flex; flex-direction: column; gap: 6px; margin-top: 9px; }
.brief-opts .opt { display: flex; gap: 8px; align-items: center; }
.brief-opts .opt input { padding: 6px 10px; font-size: 13px; }
.brief-opts .btn { align-self: flex-start; }

/* Памятка по типам полей в боковой карточке: строка на тип. */
.kind-help div { font-size: 12px; line-height: 1.6; color: var(--text-3); }
.kind-help div + div { margin-top: 6px; }
.kind-help b { color: var(--text); }
/* Перенос обязателен: в строке рядом с подписью может стоять набор плашек
   (роли, исходы), который в узкой колонке не помещается. Без переноса он
   наезжает на текст, и подпись становится нечитаемой. */
.editrow {
  display: flex; align-items: center; flex-wrap: wrap; gap: 9px;
  padding: 10px 0; border-top: 1px solid var(--line);
}
.editrow .pills { margin-left: auto; justify-content: flex-end; }
.editrow:first-child { border-top: 0; }
.editrow .grow { flex: 1; min-width: 0; }

/* ── настройка воронки вакансии (2026-09-07) ─────────────────────────────
   Строка этапа: номер, поле подписи, число кандидатов, стрелки, крестик.
   Поле подписи растягивается, остальное — по содержимому: правят подпись, а
   не порядок, и ширина нужна ей. Строка не переносится: стрелки под полем
   читались бы как действия над следующим этапом. */
.stg-row { flex-wrap: nowrap; }
.stg-n { flex: none; width: 18px; font-size: 12px; font-weight: 700; color: var(--muted); text-align: right; }
.stg-label { flex: 1; min-width: 0; width: auto; }
.stg-cnt { flex: none; min-width: 92px; text-align: right; white-space: nowrap; }

/* ── номера компании ─────────────────────────────────────────────────────
   У карточки их несколько: приёмная, мобильный директора, номер из выгрузки,
   номер, с которого позвонили сами. Строка держит четыре вещи в одном ряду —
   набор, сам номер, чей он, разбор, — и набор стоит ПЕРВЫМ: из всего, что с
   номером делают, звонят по нему в сотню раз чаще, чем правят.

   Основной подсвечен фоном, а не только плашкой: в списке из пяти номеров
   плашку надо искать глазами, а фон виден боковым зрением. */
.ph-row {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px; margin: 0 -10px; border-radius: var(--r-md);
}
.ph-row + .ph-row { margin-top: 2px; }
.ph-row.on { background: var(--soft); }
.ph-row .grow { flex: 1; min-width: 0; }
.ph-num {
  display: flex; align-items: center; gap: 7px;
  font-size: 14px; font-weight: 700; letter-spacing: 0.01em;
}
.ph-row .ph-dial { color: var(--accent-dark); background: #d9f2ef; }
.ph-row .ph-dial:hover { background: #c3e9e3; }
/* Кнопки разбора проявляются по наведению на строку: их две на каждый номер,
   и постоянно видимыми они превращают список номеров в панель управления. На
   узком экране (сенсор, где наведения нет) остаются видимыми всегда. */
.ph-row .ph-main, .ph-row .ph-drop { opacity: 0; transition: opacity 0.12s; }
.ph-row:hover .ph-main, .ph-row:hover .ph-drop { opacity: 1; }
.ph-row .ph-main:focus-visible, .ph-row .ph-drop:focus-visible { opacity: 1; }
@media (hover: none) {
  .ph-row .ph-main, .ph-row .ph-drop { opacity: 1; }
}
/* Выбор часового пояса карточки. Стоит под списком номеров, а не в форме
   правки: пояс узнают в разговоре, и открывать ради него режим правки карточки
   значит не записать его вовсе. В колл-центре (.compact) — та же строка, но
   без пояснения: там панель узкая и тёмная. */
.ph-tz-row {
  margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--line);
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
}
.ph-tz-lbl { font-size: 12px; color: var(--muted); }
.ph-tz-row select.ph-tz {
  flex: 1; min-width: 150px; width: auto;
  padding: 5px 8px; font-size: 13px; border-radius: var(--r-sm);
  border: 1px solid var(--line); background: var(--surface); color: var(--text);
}
.ph-tz-row .hint { flex-basis: 100%; margin: 0; }
/* Короткий вид — в шапке разговора: строка без пояснения и без разделителя,
   она стоит вплотную к плашкам номеров. */
.ph-tz-row.compact { margin-top: 8px; padding-top: 0; border-top: 0; }
.ph-tz-row.compact select.ph-tz { flex: 0 0 auto; min-width: 0; max-width: 230px; }
/* Тёмный вид — шапка разговора и панель телефонии: там тёмный фон, и подпись
   обычного приглушённого цвета на нём не читается. */
.ph-tz-row.dark { border-top: 0; padding-top: 0; }
.ph-tz-row.dark .ph-tz-lbl { color: #9db6bf; }
.ph-tz-row.dark select.ph-tz {
  background: rgba(255, 255, 255, 0.06); color: #eaf4f7;
  border-color: rgba(255, 255, 255, 0.18);
}

/* Флажок в форме. Общее правило растягивает ЛЮБОЙ input на всю ширину — оно
   написано под текстовые поля, и без этой строки квадратик флажка вырастает в
   полосу на 394px, а подпись уезжает к правому краю. Проверено в браузере
   2026-09-04. */
/* Плашка объединённой карточки. Стоит первой строкой под шапкой: пока её не
   было, объединённая карточка выглядела обычной — открывается, история на
   месте, — и было непонятно, почему её нет ни в очереди, ни на доске. */
.mg-banner {
  display: flex; align-items: center; gap: 14px;
  border-left: 3px solid var(--accent); margin-bottom: 16px;
}
.mg-banner .grow { flex: 1; min-width: 0; }
.mg-t { font-size: 14px; font-weight: 700; margin-bottom: 3px; }

/* Подсказка «этот номер уже в базе» под полем ввода. Появляется по ходу
   набора, а не после нажатия: решение принимается глядя на ту карточку. */
.ph-hint {
  margin-top: 10px; padding: 10px 12px; border-radius: var(--r-md);
  background: var(--soft); font-size: 13px; line-height: 1.5;
}
.ph-hint.warn { background: var(--warn-bg, #fdf3e3); }
.ph-hint-sub { margin-top: 2px; font-size: 11px; color: var(--muted); }
.ph-hint-go {
  display: inline-block; margin-top: 6px; font-size: 12px; font-weight: 700;
  color: var(--accent-dark); text-decoration: none;
}
.ph-hint-go:hover { text-decoration: underline; }

/* «+ номер» плашкой в шапке разговора: тот же размер, что у соседних плашек,
   но с рамкой — иначе кнопка читается как ещё один факт о лиде. */
.ph-tag-add {
  border: 1px dashed #c4d3d9; background: transparent;
  color: var(--text-3); cursor: pointer; font-weight: 700;
}
.ph-tag-add:hover { color: var(--accent-dark); border-color: var(--accent); background: #d9f2ef; }

.ph-check { display: flex; align-items: center; gap: 8px; font-size: 13px; cursor: pointer; }
.ph-check input[type="checkbox"] { width: 16px; height: 16px; min-width: 16px; margin: 0; padding: 0; }

/* Те же номера в панели набора колл-центра. Панель тёмная, и светлые строки
   карточки там читались бы как чужой блок, поэтому у неё свой набор правил, а
   не переопределение цветов у .ph-row. */
.tel-more { margin-top: 10px; display: flex; flex-direction: column; gap: 4px; }
.tel-ph { display: flex; align-items: center; gap: 6px; }
.tel-ph-dial {
  flex: 1; min-width: 0; display: flex; align-items: baseline; gap: 8px;
  padding: 6px 10px; border: 0; border-radius: var(--r-sm);
  font: inherit; text-align: left; color: #d7e7ec; cursor: pointer;
  background: rgba(255, 255, 255, 0.06);
}
.tel-ph-dial:hover { background: rgba(255, 255, 255, 0.13); }
.tel-ph-dial .n { font-size: 13px; font-weight: 700; letter-spacing: 0.01em; }
.tel-ph-dial .l { font-size: 11px; color: #8aa9b3; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tel-ph-main {
  width: 28px; height: 28px; min-width: 28px; border: 0; border-radius: var(--r-sm);
  font: inherit; font-size: 13px; color: #8aa9b3; cursor: pointer;
  background: rgba(255, 255, 255, 0.06);
}
.tel-ph-main:hover { color: #d7e7ec; background: rgba(255, 255, 255, 0.13); }
.tel-ph-add {
  align-self: flex-start; padding: 5px 0; border: 0; background: none;
  font: inherit; font-size: 12px; color: #8aa9b3; cursor: pointer;
}
.tel-ph-add:hover { color: #d7e7ec; text-decoration: underline; }
/* Предложение прикрепить набранный номер. Заметное, но не модальное: человек в
   этот момент говорит по телефону, и окно поверх экрана было бы помехой. */
.tel-attach { margin-top: 8px; font-size: 12px; color: #9db6bf; line-height: 1.5; }
.tel-attach-go {
  margin-left: 6px; padding: 3px 9px; border: 0; border-radius: 999px;
  font: inherit; font-size: 12px; font-weight: 700; color: #0c2027;
  background: #5eead4; cursor: pointer;
}
.tel-attach-go:hover { background: #7ef2de; }

/* Справочники в настройках — в несколько колонок (замечание владельца
   2026-09-04: «сделать в несколько блоков рядом, чтобы было компактнее»).
   Причин отказа восемнадцать, источников шестнадцать; одним столбцом это три
   экрана прокрутки при пустующей правой половине карточки.

   Колонки, а не сетка: у групп причин («кандидат», «клиент», «мы») разная
   высота, и в сетке короткая группа оставляла бы под собой дыру до низа
   строки. Колонки же браузер уравнивает сам.

   Ширина колонки задана в px, а количество ограничено тремя: на широком
   мониторе иначе получилось бы пять колонок по узкой полоске, где подпись
   причины переносится в три строки — и «компактнее» превращается в «выше». */
.dict-cols { columns: 320px 3; column-gap: 30px; }
.dict-cols > * { break-inside: avoid; }
/* Черта снизу, а не сверху: в колонках «первой строки» столько же, сколько
   колонок, и верхняя граница висела бы обрубком у каждой из них. */
.dict-cols .editrow { padding: 8px 0; border-top: 0; border-bottom: 1px solid var(--line); }
.dict-col { margin-bottom: 10px; }
.dict-col-t {
  margin-bottom: 2px; font-size: 11px; font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--muted);
}
/* Значок — по центру плашки у КАЖДОЙ кнопки, а не у тех экранов, что
   дописали центровку себе сами. Без этого svg в кнопке с display:block
   прижимался к левому краю: в шапке блока «Документы кандидата» значок
   стоял со сдвигом 7px из 30 (замечание владельца 2026-09-23 «обводка
   кривая, проверь на всём проекте»). */
.icon-btn {
  display: inline-flex; align-items: center; justify-content: center; flex: none; padding: 0;
  width: 28px; height: 28px; min-width: 28px; border: 0; border-radius: var(--r-sm);
  font: inherit; font-size: 14px; color: var(--text-3); background: var(--soft); cursor: pointer;
}
.icon-btn > svg { flex: none; }
a.icon-btn { text-decoration: none; }
.icon-btn:hover { color: var(--accent-dark); background: #d9f2ef; }
/* Красный сразу, а не только по наведению (решение владельца 2026-09-03:
   «иконку наверное красного цвета, в цветовой политике»). Действие убирает
   строку из работы, и узнаваться оно должно до наведения. Фон — по наведению:
   красная плашка в каждой строке списка читалась бы как список ошибок. */
.icon-btn.danger { color: var(--danger); }
.icon-btn.danger:hover { color: var(--danger); background: var(--danger-bg); }
/* «Написать письмо» в шапке блока «Почта» карточки — главное действие блока,
   поэтому залито цветом; «Вся переписка» рядом — обычным значком (2026-09-23). */
.icon-btn.mail-card-new { background: var(--accent); color: #fff; }
.icon-btn.mail-card-new:hover { background: var(--accent-dark); color: #fff; }
.icon-btn.mail-card-new:disabled { opacity: .45; cursor: default; }

.bar { height: 8px; border-radius: 4px; background: rgba(22, 48, 58, 0.07); overflow: hidden; }
.bar i { display: block; height: 100%; background: var(--accent-700); }
.bar.bad i { background: var(--danger); }

.switch {
  position: relative; width: 38px; height: 22px; border: 0; border-radius: 999px;
  background: #cdd9de; cursor: pointer; transition: background 0.15s;
}
.switch::after {
  content: ""; position: absolute; top: 3px; left: 3px; width: 16px; height: 16px;
  border-radius: 999px; background: #fff; transition: transform 0.15s;
}
.switch.on { background: var(--accent); }
.switch.on::after { transform: translateX(16px); }

/* ── доступ клиента ──────────────────────────────────────────────────────── */

/* Раньше доступ был строкой .editrow: имя, мелким шрифтом логин с заходами,
   тег и четыре кнопки. Всё одного веса, и главное — заходил ли клиент —
   терялось между логином и датой. */

.acc + .acc { margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--line); }
.acc-top { display: flex; align-items: flex-start; gap: 10px; }
.acc-top .nm { font-size: 13px; font-weight: 700; }
.acc-top .sub { margin-top: 2px; font-size: 12px; color: var(--muted); }
.acc-top .sub b { font-weight: 700; color: var(--text-3); }
.acc-top .tag { flex: none; }

/* Полоса заходов — отдельная плашка, и цветом отличается только тогда, когда
   заходили. Серое «ни разу» и зелёное «заходил» различимы боковым зрением. */
.acc-seen {
  margin-top: 9px; padding: 7px 11px; border-radius: var(--r-sm);
  font-size: 12px; font-weight: 600; color: var(--muted); background: var(--soft);
}
.acc-seen.on { color: var(--accent-dark); background: rgba(15, 118, 110, 0.09); }

.acc-btns { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }

/* ── тест кандидата в панели ─────────────────────────────────────────────── */

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

.test-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
/* Значки анкеты — у правого края шапки, там же, где значки резюме на hh:
   действия по блоку человек ищет в одном месте, а не под каждым заголовком
   по-своему. */
.test-acts { margin-left: auto; display: flex; gap: 4px; }

/* Попытки теста переключателем. Мелко и в одну строку на попытку: их две-три,
   и ряд не должен спорить за внимание с самим прохождением под ним. */
.test-tabs { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; }
.test-tab {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 10px; border: 1px solid var(--line); border-radius: 999px;
  background: var(--card, #fff); cursor: pointer; font-size: 11px; color: var(--muted);
}
.test-tab:hover { border-color: var(--accent); }
.test-tab.on { border-color: var(--accent); background: var(--soft); }
.test-tab .n { font-weight: 700; color: var(--text-2); }
.test-tab.on .n { color: var(--accent-dark); }
/* Откуда попытка — приглушённо: это уточнение к номеру, а не отдельный факт. */
.test-tab .src { color: var(--muted-2); }
.test-tab .res { font-weight: 700; }
.test-tab .res.wait { color: var(--warn); }
.test-tab .res.done { color: var(--accent-dark); }
.test-head .nm { font-size: 13px; font-weight: 700; color: var(--text-2); }
.test-head .att {
  padding: 2px 8px; border-radius: 999px;
  font-size: 11px; font-weight: 700; color: var(--warn); background: var(--warn-bg);
}

/* Метаданные — парами «что : когда». Пара не разрывается переносом: «выслан»
   без даты и дата без подписи по отдельности не значат ничего. */
.test-meta { display: flex; flex-wrap: wrap; gap: 8px 22px; margin-top: 12px; }
.test-meta > div { display: flex; align-items: baseline; gap: 7px; }
.test-meta span { font-size: 11px; color: var(--muted); }
.test-meta b { font-size: 13px; font-weight: 700; color: var(--text-2); }

.test-blocks { margin-top: 14px; }
/* Три колонки, а не флекс с фиксированной шириной: названия разделов разной
   длины, и при флексе полосы начинались в разных местах — глазу не за что
   зацепиться, чтобы сравнить разделы между собой. */
.test-row {
  display: grid; grid-template-columns: minmax(120px, 1fr) minmax(90px, 240px) 42px;
  gap: 14px; align-items: center;
  padding: 10px 0; border-top: 1px solid var(--line);
}
.test-row:first-child { border-top: 0; padding-top: 0; }
.test-row .nm { font-size: 13px; font-weight: 600; color: var(--text-2); }
.test-row .nm .kind { display: block; font-size: 11px; font-weight: 500; color: var(--muted-2); }
.test-row .pct { text-align: right; font-size: 14px; font-weight: 800; }

/* Сводка теста в свёрнутом виде: проценты по разделам чипами и число письменных
   ответов. Ответы целиком — под <details>, свёрнуты по умолчанию (замечание
   владельца 2026-09-07: «на постоянку его ответы не нужны»). */
.test-sum { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; }
.test-sum .chip {
  padding: 3px 9px; border-radius: 999px;
  font-size: 12px; font-weight: 600; color: var(--text-2); background: rgba(22, 48, 58, 0.06);
}
/* Отметки отбора. Цвет здесь несёт смысл, а не украшает: «не подходит» и
   «устранимо» ведут к разным письмам кандидату, и различать их по тексту
   мелкой пилюли — значит читать девятнадцать штук подряд. */
.test-sum .chip-stop { color: var(--danger); background: var(--danger-bg); }
.test-sum .chip-hold,
.test-sum .chip-warn { color: var(--warn); background: var(--warn-bg); }
.test-sum .chip-ask { color: var(--text-2); background: rgba(22, 48, 58, 0.06); border: 1px dashed rgba(22, 48, 58, 0.22); }
.test-sum .chip-old { color: var(--text-3); background: rgba(22, 48, 58, 0.09); }
.test-sum .chip-ok { color: var(--accent-dark); background: rgba(22, 48, 58, 0.05); }

.test-fold { margin-top: 12px; }
/* Прошлые попытки теста отделены чертой: без неё «Попытка 1» читается как
   продолжение последнего прохождения, а это разные ответы разных дней. */
.test-past { border-top: 1px solid var(--line, rgba(22, 48, 58, 0.12)); margin-top: 14px; }
.test-fold > summary {
  display: flex; align-items: center; gap: 6px; list-style: none;
  font-size: 13px; font-weight: 700; color: var(--accent-dark); cursor: pointer;
}
.test-fold > summary::-webkit-details-marker { display: none; }
.test-fold > summary::before { content: '▸'; font-size: 11px; }
.test-fold[open] > summary::before { content: '▾'; }

/* Значок Telegram у человека: заполненный — диалог привязан, контурный — ник
   указан, а диалога нет. В списке кандидатов вакансии это единственный способ
   увидеть, кто на связи, не открывая панель (замечание владельца 2026-09-07). */
.cname-row { display: flex; align-items: center; min-width: 0; }
.tg-mark {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; margin-left: 6px; border-radius: 999px; vertical-align: -4px;
}
.tg-mark svg { width: 11px; height: 11px; }
.tg-mark.on { color: #fff; background: var(--accent); }
.tg-mark.nick { color: var(--muted); background: rgba(22, 48, 58, 0.08); }
/* Заблокировал бота (2026-09-14): значок перечёркнут — связи нет, переписка есть. */
.tg-mark.blocked { position: relative; color: var(--danger); background: var(--danger-bg); }
.tg-mark.blocked::after {
  content: ''; position: absolute; left: 3px; right: 3px; top: 50%;
  height: 1.5px; background: currentColor; transform: rotate(-45deg);
}

/* Значок-ссылка: он ведёт в переписку, и это должно быть видно до нажатия.
   Значок-подпись рядом с ним остаётся прежним — на карточке кандидата
   переписка уже открыта, и вести оттуда некуда. */
a.tg-mark.go { text-decoration: none; transition: transform 0.12s, background 0.12s, color 0.12s; }
a.tg-mark.go:hover { transform: translateY(-1px); }
a.tg-mark.go.on:hover { background: var(--accent-dark); }
a.tg-mark.go.nick:hover { color: #fff; background: var(--accent); }
a.tg-mark.go.blocked:hover { color: #fff; background: var(--danger); }

/* Переписка слева под свёрнутыми ответами, когда диалог привязан: лента
   растёт в освободившееся место, а не упирается в потолок карточки. */
.tgc-card.tgc-tall .tgc-feed { max-height: calc(100vh - 470px); min-height: 280px; }

/* Фото собеседника из Telegram (2026-09-07): в списке диалогов, в шапке
   переписки, в карточке собеседника и у привязанного кандидата вместо
   инициалов. Приносит мост, отдаётся за входом. */
.tgc-ava { width: 28px; height: 28px; border-radius: 999px; object-fit: cover; flex: none; background: #e6edf0; }
.tgc-ava.lg { width: 40px; height: 40px; }
.tgc-item-who { display: flex; align-items: center; gap: 8px; min-width: 0; }
.tgc-head-l { display: flex; align-items: center; gap: 10px; min-width: 0; }
.ini.pic { object-fit: cover; padding: 0; }

.test-written { margin-top: 18px; }
.test-written .w {
  margin-top: 10px; padding: 14px 16px;
  border-radius: var(--r-md); background: var(--soft);
}
/* Название раздела над парами: их в разделе бывает несколько, и без подписи
   непонятно, к чему относится ответ. */
.test-written .cap {
  margin-bottom: 11px;
  font-size: 10px; font-weight: 700; letter-spacing: 0.09em;
  text-transform: uppercase; color: var(--muted);
}
/* Вопрос и ответ различаются насыщенностью и отбивкой слева, а не отступом:
   одинаково набранные, они читались сплошным текстом, и проверяющий каждый раз
   искал глазами, где кончился вопрос. Черта между парами — чтобы длинный ответ
   не сливался со следующим вопросом. */
.test-written .qa + .qa {
  margin-top: 13px; padding-top: 13px; border-top: 1px solid rgba(22, 48, 58, 0.08);
}
.test-written .q { font-size: 13px; font-weight: 700; line-height: 1.45; color: var(--text-2); }
.test-written .a {
  margin-top: 7px; padding-left: 12px; border-left: 2px solid var(--accent-700);
  font-size: 13px; line-height: 1.6; color: var(--text-3); white-space: pre-wrap;
}

.test-none { padding: 4px 0; font-size: 12px; color: var(--muted); }
.test-none .h { margin-bottom: 3px; font-size: 14px; font-weight: 700; color: var(--text-2); }

/* Свободный текст о кандидате: единственное, что осталось от снятого блока
   профиля, — его вводят руками, и потерять его нельзя. */
.note + .note { margin-top: 10px; }
.note .k { font-size: 11px; color: var(--muted); margin-bottom: 3px; }
.note .v { font-size: 13px; line-height: 1.55; color: var(--text-3); white-space: pre-wrap; }

/* ── оценка по критериям ────────────────────────────────────────────────── */

/* Панель кандидата этими классами больше не пользуется: блок оценки снят
   2026-09-01 по решению владельца. Стили оставлены — маршрут и обработчик
   оценки на сервере живы, и возвращать её, если понадобится, придётся сюда. */

.crit { display: flex; align-items: center; gap: 12px; padding: 9px 0; border-top: 1px solid var(--line); }
.crit:first-child { border-top: 0; }
.crit .lb { flex: 1; }
.crit .lb b { font-size: 13px; font-weight: 700; }
.crit .lb span { display: block; font-size: 11px; color: var(--muted-2); }
.dots { display: flex; gap: 4px; }
.dots button {
  width: 26px; height: 6px; border: 0; border-radius: 3px;
  background: rgba(22, 48, 58, 0.12); cursor: pointer; padding: 0;
}
.dots button.on { background: var(--accent-700); }

/* ── страницы по ссылке ─────────────────────────────────────────────────── */

.pub { max-width: 940px; margin: 0 auto; padding: 30px 24px 60px; }

/* Страница клиента шире остальных страниц по ссылке: на ней таблица откликов и
   раскрытая анкета, а не текст для чтения. На 940 точках этап и дата ломались
   в две строки, а раскрытая анкета вставала узким столбиком. Тест и анкета
   кандидата остаются узкими намеренно — там читают сплошной текст. */
.pub-wide { max-width: 1240px; }

/* Колонка входа: шапка и карточка одной ширины, с воздухом сверху. Разная
   ширина у соседних блоков читается как съехавшая вёрстка, даже когда каждый
   блок сам по себе стоит правильно. */
.pub-auth { max-width: 460px; padding-top: 72px; }

/* Кнопка во всю ширину родителя.
   Класс `btn-block` стоял в десятке мест (вход клиента и партнёра, панель
   кандидата, панель резюме), а правила для него не было вовсе — кнопка
   «Войти» шириной 76 px стояла в углу карточки на 420 px. Ширину задаём
   здесь, а не стилем у каждой кнопки: иначе следующая копия снова разойдётся
   с остальными. */
.btn-block { display: flex; width: 100%; }

/* Факты о кандидате в раскрытой анкете. Сетка, а не столбик: плашки .next
   стояли вплотную без зазора и читались одним серым пятном. Минимум 210px —
   ниже этого «Тип продаж» с длинным значением рвётся на три строки. */
.facts { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 10px; }
/* «О себе» — свободный текст, а не короткое значение: в ячейке обычной ширины
   он рвётся на три строки и перетягивает высоту всего ряда. */
.facts .wide { grid-column: span 2; }
.facts .next { align-items: flex-start; }

/* Карточки страницы клиента стояли встык: у .card нет собственных полей, а на
   рабочих экранах зазор даёт .stack, которого здесь нет. Воронка и таблица
   склеивались в одну плашку с швом посередине. Только прямые дети .pub-wide —
   внутри раскрытой анкеты карточка одна, и лишний отступ там не нужен. */
.pub-wide > .card + .card { margin-top: 14px; }

/* Поиск и фильтры в кабинете заказчика ────────────────────────────────────
   Замечание владельца 2026-09-22: «в кабинете заказчика не очевидна работа
   фильтров, так же нужно наверное сделать поиск по данным».

   Полоса липкая по той же причине, что и строка поиска в системе: искать
   начинают, дочитав список до середины, — а строка к этому времени уехала
   вверх вместе со страницей.

   Фон полупрозрачный с размытием, а не сплошной: под полосой градиент body,
   и плашка сплошного цвета висела бы на нём заметным прямоугольником. */
/* Поля и центрирование повторяют .pub: полоса стоит над той же колонкой, что
   и содержимое. Задано здесь явно, а не унаследовано, — у .pub снизу 60 px
   воздуха под страницу, и в липкой полосе это была бы прозрачная пустота
   поверх таблицы. */
.pub-search {
  position: sticky; top: 0; z-index: 30;
  margin: 0 auto 14px; padding: 12px 24px 10px;
  background: rgba(239, 243, 246, 0.86);
  backdrop-filter: blur(8px);
}
.pub-search .gs { max-width: none; height: 40px; margin: 0; }
.pub-search .gs input { height: 40px; }

/* Крестик очистки встаёт на место подсказки «/», когда в поле что-то набрано:
   два значка подряд в одном углу читаются как один сломанный. */
.gs-clear {
  position: absolute; right: 8px; top: 50%; transform: translateY(-50%);
  width: 24px; height: 24px; padding: 0; border: 0; border-radius: 50%;
  font: inherit; font-size: 15px; line-height: 1; color: var(--muted);
  background: var(--soft); cursor: pointer;
}
.gs-clear:hover { color: var(--text); }

/* Ответ поиска строкой под полем: сколько нашлось и из скольких. Без «из N»
   три находки читаются как «всего три кандидата», а не как «три из сорока
   восьми» — ровно та же ловушка, что и в выпадающем списке системы. */
.pub-found {
  display: flex; align-items: center; gap: 10px;
  margin-top: 8px; padding: 0 4px;
  font-size: 12px; color: var(--muted);
}
.pub-found b { color: var(--text); }

/* Ряд фильтров по этапам — над таблицей, а не только столбиками воронки.
   Воронка читается как отчёт, и то, что по ней можно нажать, заказчик не
   угадывал: фильтр обязан выглядеть фильтром. */
.pub-filters { display: flex; flex-wrap: wrap; gap: 6px; margin: 12px 0 4px; }
.pub-filters .pill { font-size: 12px; padding: 5px 11px; }
.pub-filters .pill .n { margin-left: 5px; opacity: 0.6; font-weight: 700; }

/* Где нашлось — подписью в строке таблицы. Совпадение в резюме или в ответах
   из строки не видно вовсе, и без подписи находка выглядит случайной. */
/* Время у кандидата в кабинете заказчика: ночь у него — видно сразу. */
.cl-tz.quiet { color: var(--warn); font-weight: 600; }
.hit-where {
  display: inline-block; margin-top: 3px;
  font-size: 11px; color: var(--accent-700);
}

/* Кнопка «наверх» ─────────────────────────────────────────────────────────
   Замечание владельца 2026-09-22: «нужно сделать стрелочку которая подымает
   вверх». Список откликов длинный, а действия (поиск, фильтры, воронка) стоят
   в его начале — возвращаться к ним прокруткой через сотню строк.

   Появляется не сразу: пока страница не прокручена, кнопка вела бы туда, где
   заказчик и так стоит. */
.to-top {
  position: fixed; right: 24px; bottom: 24px; z-index: 45;
  display: flex; align-items: center; justify-content: center;
  width: 46px; height: 46px; padding: 0;
  border: 0; border-radius: 50%;
  font: inherit; font-size: 19px; line-height: 1; color: #fff;
  background: var(--accent); box-shadow: var(--shadow-lg); cursor: pointer;
  opacity: 0; transform: translateY(10px); pointer-events: none;
  transition: opacity 0.18s, transform 0.18s;
}
.to-top.on { opacity: 1; transform: none; pointer-events: auto; }
.to-top:hover { background: var(--accent-700); }

/* Черта между контактами и этапами внутри одной карточки: они про одно дело —
   посмотреть, кто это, и передвинуть, — но это всё же два разных действия. */
.sheet-split { margin: 18px 0 16px; border-top: 1px solid var(--line); }

/* Подпись и кнопки в одной строке: кнопка отказа во всю ширину карточки на
   широком экране выглядела главным действием страницы, хотя это крайний шаг. */
.sheet-foot {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 14px;
}
.sheet-foot .hint { flex: 1; min-width: 260px; font-size: 11px; color: var(--muted-2); }
.sheet-foot .btn { flex: none; }

/* Описание вакансии на странице по ссылке: длинный текст, который человек
   читает целиком. Ширина строки ограничена — сплошная простыня в 900px не
   читается, глаз теряет строку на возврате.

   С 2026-09-05 внутри разметка, а не простой текст, поэтому `white-space:
   pre-wrap` убран: с ним переносы и отступы между тегами превращались бы в
   пустые строки прямо посреди абзаца. */
/* Последний экран анкеты: призыв перейти в Telegram.

   Не сноска, а блок с рамкой и кнопкой. Улика 2026-09-08: экран говорил
   «Спасибо, с вами свяжутся», и человек закрывал страницу — из восьми
   анкет до переписки дошли двое. Призыв обязан выглядеть как следующее
   действие, а не как примечание внизу. */
.pub-next {
  margin-top: 18px; padding: 16px 18px; border-radius: var(--r-md);
  border: 2px solid var(--accent); background: var(--soft);
  text-align: center;
}
.pub-next-h { font-size: 15px; font-weight: 800; margin-bottom: 6px; }
.pub-next-t { font-size: 14px; line-height: 1.5; color: var(--text-2); }
.pub-next-b { margin: 14px 0 10px; display: inline-block; font-size: 15px; padding: 12px 22px; }

.pub-descr {
  max-width: 62ch; font-size: 15px; line-height: 1.65; color: var(--text-2);
  word-break: break-word;
}
/* Вид описания задаётся здесь, а не в редакторе. Оттуда приходит смысл — «это
   заголовок», «это список», — а размеры и отступы обязаны быть теми же, что на
   остальной странице. Иначе объявление выглядит вставкой из чужого документа. */
.pub-descr > :first-child { margin-top: 0; }
.pub-descr > :last-child { margin-bottom: 0; }
.pub-descr p { margin: 0 0 12px; }
.pub-descr h3 {
  margin: 22px 0 8px; font-size: 17px; font-weight: 800;
  letter-spacing: -0.02em; color: var(--text);
}
.pub-descr h4 {
  margin: 18px 0 6px; font-size: 15px; font-weight: 700; color: var(--text);
}
.pub-descr ul, .pub-descr ol { margin: 0 0 12px; padding-left: 22px; }
.pub-descr li { margin-bottom: 5px; }
.pub-descr strong { font-weight: 700; color: var(--text); }
.pub-descr a { color: var(--accent-dark); }
.pub-descr blockquote {
  margin: 0 0 12px; padding: 2px 0 2px 14px;
  border-left: 3px solid var(--field); color: var(--muted);
}
/* Последний экран анкеты — тот же вид, что у описания, но внутри центрированной
   карточки «Ответы отправлены». Колонка ставится по центру, а списки и
   заголовки выключаются влево: центрированный список не читается, а текст
   задаётся на вакансии, и «что дальше» там вполне может оказаться списком. */
.pub-done { max-width: 52ch; margin: 0 auto; font-size: 14px; }
.pub-done ul, .pub-done ol, .pub-done h3, .pub-done h4, .pub-done blockquote {
  text-align: left;
}

.pub-head { margin-bottom: 20px; }

/* ── редактор описания вакансии ────────────────────────────────────────────
   Панель инструментов и поле собраны в одну рамку: два соседних прямоугольника
   читались бы как два разных поля, а это одно. */
.rte-box {
  border: 1.5px solid var(--field); border-radius: var(--r-md);
  background: #fff; overflow: hidden;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.rte-box:focus-within {
  border-color: var(--accent); box-shadow: 0 0 0 3px rgba(15, 118, 110, 0.14);
}
.rte-tools {
  display: flex; align-items: center; gap: 3px; flex-wrap: wrap;
  padding: 6px 8px; border-bottom: 1px solid var(--line-2); background: var(--soft);
}
.rte-b {
  padding: 5px 9px; border: 0; border-radius: var(--r-sm);
  background: transparent; color: var(--text-3);
  font: inherit; font-size: 12px; font-weight: 600; line-height: 1.2;
  cursor: pointer; transition: background 0.12s, color 0.12s;
}
.rte-b:hover { background: rgba(22, 48, 58, 0.07); color: var(--text); }
/* Включённое оформление — заливкой, а не рамкой: рамка на кнопке высотой в
   двадцать пикселей неразличима, а по этой подсветке человек понимает, что
   получится, ещё до нажатия. */
.rte-b.on { background: var(--accent); color: #fff; }
.rte-b.rte-bold { font-weight: 800; }
.rte-b.rte-ital { font-style: italic; }
.rte-sep { width: 1px; height: 16px; margin: 0 4px; background: var(--field); }

.rte-link {
  display: flex; gap: 6px; align-items: center;
  padding: 8px; border-bottom: 1px solid var(--line-2); background: #fff;
}
.rte-link input { flex: 1; min-width: 0; font-size: 13px; padding: 7px 10px; }

/* Поле высокое и широкое намеренно (решение владельца 2026-09-05: «раз мы
   добавили туда форматирование — сделай побольше»). Пока это было голое поле
   ввода, размер значения не имел: текст всё равно шёл сплошняком. С
   заголовками и списками важно другое — видеть структуру целиком, а не через
   щель в шесть строк: иначе разметку правят вслепую и прокруткой. */
.rte {
  min-height: 440px; max-height: 64vh; overflow-y: auto;
  padding: 14px 16px; font-size: 15px; line-height: 1.6; color: var(--text);
  outline: none; word-break: break-word;
}
/* Подсказка в пустом поле. Через `::before`, а не placeholder: у
   contenteditable его нет, а пустое поле без подсказки выглядит сломанным. */
.rte.rte-empty::before {
  content: attr(data-ph); color: var(--muted-2); pointer-events: none;
}
/* Внутри редактора текст показывается так же, как потом на странице кандидата.
   Это не косметика: расхождение между «как выглядело при наборе» и «как вышло»
   — единственная причина, по которой редактором перестают пользоваться. */
.rte > :first-child { margin-top: 0; }
.rte p { margin: 0 0 10px; }
.rte h3 { margin: 16px 0 6px; font-size: 16px; font-weight: 800; letter-spacing: -0.02em; }
.rte h4 { margin: 14px 0 5px; font-size: 14px; font-weight: 700; }
.rte ul, .rte ol { margin: 0 0 10px; padding-left: 22px; }
.rte li { margin-bottom: 4px; }
.rte a { color: var(--accent-dark); }
.rte blockquote {
  margin: 0 0 10px; padding: 2px 0 2px 12px;
  border-left: 3px solid var(--field); color: var(--muted);
}
/* Картинки (2026-09-17) — по ширине колонки и не шире своего размера: схему
   рабочего места кандидат смотрит с телефона, и картинка шире экрана — это
   горизонтальная прокрутка посреди анкеты. */
.rte img, .pub-descr img {
  display: block; max-width: 100%; height: auto;
  margin: 8px 0; border-radius: var(--r-md);
}
.rte img { max-height: 320px; }
/* Оформление под вопросом теста: колонка карточки анкеты, а не узкая 62ch
   описания, — картинка под вопросом должна быть видна целиком. */
.pub-descr.q-descr { max-width: none; margin-bottom: 16px; }
/* Редактор внутри карточки вопроса: высота описания вакансии (440) превратила
   бы список вопросов в стену пустых полей. */
.q-card .rte { min-height: 110px; max-height: 50vh; }

.q-progress { height: 5px; border-radius: 3px; background: rgba(22, 48, 58, 0.09); overflow: hidden; margin: 14px 0 22px; }
.q-progress i { display: block; height: 100%; background: linear-gradient(90deg, var(--accent), var(--accent-500)); transition: width 0.2s; }
.q-opt {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 13px 15px; margin-bottom: 8px; border-radius: var(--r-md);
  border: 1.5px solid var(--field); background: #fff; cursor: pointer;
  font: inherit; font-size: 14px; text-align: left; width: 100%;
}
.q-opt:hover { border-color: var(--accent); }
.q-opt.on { border-color: var(--accent); background: rgba(15, 118, 110, 0.06); }

/* ── диалоги Telegram ───────────────────────────────────────────────────────
   Две колонки: слева поток, справа переписка. Высота считается от окна, а не
   от содержимого: список диалогов и лента сообщений прокручиваются каждый
   сам по себе, иначе при длинной переписке уезжает вообще всё, включая поле
   ответа — а оно должно быть под рукой всегда. */

/* Три колонки: список, переписка, карточка собеседника.
 *
 * Переписка держит среднюю и намеренно не растягивается: строка в сотню знаков
 * читается заметно хуже, чем в мессенджере, где ширина ограничена. Правая
 * колонка отвечает на вопрос «кто это», не уводя с экрана переписки. */
.tgc {
  display: grid; grid-template-columns: 380px minmax(0, 1fr) 380px;
  gap: 14px; align-items: stretch;
}
.tgc-card-col { display: flex; flex-direction: column; gap: 10px; overflow-y: auto;
  height: calc(100vh - 250px); min-height: 380px; }
.tgc-card-acts { display: flex; flex-direction: column; gap: 6px; margin-top: 14px; }
.tgc-card-acts .btn { width: 100%; }
.tgc-card-name { font-size: 16px; font-weight: 700; margin-bottom: 10px; }
/* Строка «поле — значение»: подпись слева узкой колонкой, значение переносится.
   Через .editrow это не выразить — там значение прижато вправо и в одну
   строку, а «Опыт и чеки» у кандидата занимает две. */
.tgc-row {
  display: grid; grid-template-columns: 104px minmax(0, 1fr);
  gap: 8px; padding: 5px 0; border-top: 1px solid var(--line); font-size: 13px;
}
.tgc-row-k { color: var(--muted); }
.tgc-row-v { color: var(--text); word-break: break-word; }
.tgc-score {
  margin: 2px 0 10px; padding: 6px 10px; border-radius: var(--r-sm);
  font-size: 12px; font-weight: 700;
}
.tgc-score.ok { color: var(--accent-dark); background: linear-gradient(120deg, #d9f2ef, #c3e9e3); }
.tgc-score.no { color: var(--warn); background: var(--warn-bg); }
/* Найденная по нику строка в окне привязки: видно, почему она нашлась. */
.tgc-hit.same { box-shadow: inset 0 0 0 1.5px var(--accent); }
.tgc-hit b { display: flex; align-items: center; gap: 8px; }
.tgc-found { margin: 4px 0 10px; font-size: 13px; line-height: 1.45; color: var(--text-3); }
/* Подсказка под кнопками поля ответа: набирается на клавиатуре, и правило
   «Enter отправляет» должно быть видно до первого нажатия, а не после. */
.tgc-hint { font-size: 11px; line-height: 1.35; color: var(--muted); }

/* Новое входящее: короткая вспышка. Отмечает момент, а не состояние, — поэтому
   гаснет сама. До 2026-09-03 сообщение просто возникало в переписке, и понять,
   что тебе ответили, было нечем. */
@keyframes tgc-fresh {
  0%   { background: var(--accent); color: #fff; transform: translateY(2px); }
  35%  { background: var(--accent); color: #fff; transform: translateY(0); }
  100% { background: inherit; color: inherit; }
}
.tgc-msg.fresh { animation: tgc-fresh 1.4s ease-out; }

/* Узкое окно: карточка уходит под переписку, а не жмёт её. */
@media (max-width: 1500px) {
  .tgc { grid-template-columns: 380px minmax(0, 1fr); }
  .tgc-card-col { grid-column: 1 / -1; height: auto; min-height: 0; }
}
/* Фильтры над списком диалогов — слева, как и были. Не .head-actions: тот
   ряд живёт в шапке экрана и прижат к правому краю. */
.tgc-filters {
  display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
  justify-content: flex-start; margin-bottom: 10px;
}
.tgc-list {
  display: flex; flex-direction: column; gap: 6px; overflow-y: auto;
  height: calc(100vh - 250px); min-height: 380px; padding-right: 4px;
}
/* Хвост списка диалогов: «Показать ещё · 60 из 734» (2026-09-16). Список едет
   страницами, и без этой строки конец страницы читался бы как конец списка. */
.tgc-more { padding: 8px 2px 4px; text-align: center; }
.tgc-more .btn { width: 100%; }
.tgc-item {
  display: block; padding: 11px 13px; border-radius: var(--r-md);
  background: var(--surface); box-shadow: var(--shadow-sm);
  text-decoration: none; color: var(--text); cursor: pointer;
}
.tgc-item:hover { box-shadow: var(--shadow-md); }
.tgc-item.on { box-shadow: var(--shadow-sm), inset 0 0 0 1.5px var(--accent); }
.tgc-item-top { display: flex; justify-content: space-between; gap: 8px; font-size: 14px; }
.tgc-item-top b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tgc-time { color: var(--muted); font-size: 12px; flex: 0 0 auto; }
.tgc-last {
  margin: 4px 0 7px; font-size: 13px; color: var(--text-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Плашки строки переносятся, а не режутся (замечание владельца 2026-09-07:
   «не влазит»): их бывает три сразу — привязка, «ждёт человека», цепочка, — и
   обрезанная «цепочка ид…» не значит ничего. Счётчик непрочитанных прижат
   вправо сам, а не распоркой space-between: с переносом она разгоняла бы
   плашки по краям пустой строки. */
.tgc-item-foot { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
.tgc-item-foot .tgc-wait { margin-left: auto; }
/* Исход отбора и этап кандидата под именем (замечание владельца 2026-09-14).
   Одной строкой и мелко: строка списка отвечает на «кому отвечать первым», и
   этап с исходом — часть ответа, а не заголовок. */
.tgc-cand {
  display: flex; align-items: center; gap: 8px; min-width: 0; margin-top: 3px;
  font-size: 12px; font-weight: 700; white-space: nowrap; overflow: hidden;
}
.tgc-cand .vd-word { flex: none; }
.tgc-novd { flex: none; color: var(--muted-2); font-weight: 600; }
.tgc-stage {
  display: inline-flex; align-items: center; gap: 5px; min-width: 0;
  color: var(--text-2); overflow: hidden; text-overflow: ellipsis;
}
.tgc-stage.out { color: var(--danger); }
.tgc-stbar { flex: none; display: inline-flex; gap: 2px; }
.tgc-stbar i { width: 4px; height: 9px; border-radius: 2px; background: #d9e3e8; }
.tgc-stbar i.f { background: var(--accent-500); }
/* Автор последнего сообщения: «Вы:», «Бот:», «нажал:». Приглушённо, чтобы
   сам текст оставался главным. */
.tgc-by { color: var(--muted); font-weight: 700; }
.tgc-by.press { color: var(--accent-dark); }
/* «⏱ 2 ч» — сколько диалог ждёт ответа человека. Прижата вправо, как и число
   новых; если есть оба, число встаёт вплотную за ней. Красная — после
   TGC_WAIT_LATE_MIN. */
.tgc-waitfor {
  flex: 0 0 auto; margin-left: auto; padding: 2px 7px; border-radius: 999px; white-space: nowrap;
  font-size: 11px; font-weight: 800; color: #b54708; background: #fdead7;
}
.tgc-waitfor.late { color: var(--danger); background: var(--danger-bg); }
.tgc-item-foot .tgc-waitfor + .tgc-wait { margin-left: 0; }
/* Ряды «Этапы» и «Отбор» под фильтрами (2026-09-14): те же кнопки, что у
   фильтров, с числом диалогов; выбывший этап — красной подписью. */
.tgc-funnel { margin-top: -4px; }
.tgc-funnel > .cand-sub { font-weight: 700; margin-right: 2px; }
.tgc-chip-n { margin-left: 6px; font-weight: 800; opacity: 0.7; }
.tgc-chip-out.btn-secondary { color: var(--danger); }
/* Папки диалогов (2026-09-14): цветная точка — на кнопке, в метке строки и в
   окнах; цвет по месту папки в списке. */
.tgc-fdot { display: inline-block; flex: none; width: 8px; height: 8px; margin-right: 6px; border-radius: 3px; vertical-align: middle; }
.tgc-ftag {
  display: inline-flex; align-items: center; padding: 1px 7px; border-radius: 999px; white-space: nowrap;
  font-size: 11px; font-weight: 700; color: var(--text-3); background: var(--soft);
}
.tgc-ftag .tgc-fdot { width: 7px; height: 7px; margin-right: 4px; }
.tgc-fcheck { display: flex; align-items: center; gap: 8px; padding: 6px 0; font-size: 14px; cursor: pointer; }
/* Доска по этапам (2026-09-14): столбцы воронки вакансии прокручиваются
   вбок, каждый — вниз. Выбывшие — розоватым фоном, как «вышли из воронки». */
.tgc-board { display: flex; gap: 10px; overflow-x: auto; height: calc(100vh - 290px); min-height: 380px; padding-bottom: 6px; }
/* Столбец — шириной с колонку списка, карточка в нём — та же строка диалога
   (замечание владельца 2026-09-14: «по размеру и формату как диалоги в
   списке»). min-width: 0 обязателен: у элемента flex-ряда минимальная ширина по
   умолчанию — ширина содержимого, и длинное последнее сообщение без переноса
   растягивало столбец на весь экран (на бою — столбец «Время предложено»). */
.tgc-bcol { flex: 0 0 392px; min-width: 0; display: flex; flex-direction: column; min-height: 0; padding: 8px; border-radius: var(--r-md); background: var(--soft); }
.tgc-bcol.out { background: rgba(180, 35, 24, 0.05); }
.tgc-bcol.drop { box-shadow: inset 0 0 0 2px var(--accent); }
.tgc-bcol-h { display: flex; align-items: center; justify-content: space-between; gap: 6px; padding: 2px 4px 8px; font-size: 13px; }
.tgc-bcol.out .tgc-bcol-h b { color: var(--danger); }
.tgc-bcol-b { flex: 1; display: flex; flex-direction: column; gap: 6px; overflow-y: auto; }
.tgc-bempty { padding: 6px 4px; }
/* Карточка доски — это .tgc-item целиком. Свои отступы и шрифт здесь стояли бы
   в файле ниже строки списка и перебивали бы её. Своё — только курсор. */
.tgc-bcard { cursor: grab; }
.tgc-bcard:active { cursor: grabbing; }
/* Доска по этапам в карточке вакансии (2026-09-14): те же столбцы, что у доски
   «Диалогов», но уже — карточка кандидата короче строки диалога, а вакансия
   делит ширину с правой колонкой. Высота — по экрану, столбцы листаются сами. */
.vb-board { height: min(72vh, 760px); }
.vb-board .tgc-bcol { flex-basis: 300px; }
.vb-card {
  display: grid; gap: 3px; min-width: 0; padding: 10px 12px; border-radius: var(--r-md);
  background: var(--surface); box-shadow: var(--shadow-sm); cursor: grab;
}
.vb-card:hover { box-shadow: var(--shadow-md); }
.vb-card:active { cursor: grabbing; }
.vb-top { display: flex; align-items: center; gap: 8px; min-width: 0; font-size: 14px; }
.vb-top b { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vb-sub { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vb-foot { display: flex; align-items: center; gap: 8px; min-height: 20px; }
.vb-when { margin-left: auto; flex: 0 0 auto; }
.vb-card.gone .vb-top b, .vb-card.gone .ini { opacity: 0.62; }
.vb-hint { margin-top: 6px; }
/* Доску ограничивает ширина колонки вакансии, а не её содержимое. Колонка сетки
   .cols (1fr) не бывает уже своего содержимого: она растягивалась под все
   столбцы доски, у самой доски полоса прокрутки не появлялась, а правая колонка
   уезжала за край (владелец 2026-09-14, бой: «внутри вакансии нету прокрутки при
   отображении в виде доски»; стенд — колонка 3126px при доске 3090px).
   Только когда доска на экране: у списка и других страниц на .cols всё прежнее. */
.cols > .stack:has(.vb-board) { min-width: 0; }
.tgc-stuck {
  padding: 2px 7px; border-radius: 999px; white-space: nowrap;
  font-size: 10.5px; font-weight: 800; color: var(--danger); background: var(--danger-bg);
}

/* «Новое» — точка у имени и более плотное начертание строки.
 *
 * Отдельно от числа «ждут ответа» справа, потому что это разные вопросы:
 * точка отвечает «я это видел?», число — «я на это ответил?». Прочитал и не
 * ответил — точка гаснет, число остаётся. Один значок на оба вопроса означал
 * бы, что один из них перестанут задавать. */
.tgc-item.unread .tgc-last { color: var(--text); font-weight: 600; }
.tgc-new {
  display: inline-block; width: 7px; height: 7px; margin-right: 6px;
  border-radius: 999px; background: var(--accent); vertical-align: middle;
}
.tgc-free { color: var(--warn); background: var(--warn-bg); }
.tgc-wait {
  flex: 0 0 auto; min-width: 20px; height: 20px; padding: 0 6px; border-radius: 999px;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 700; color: #fff; background: var(--accent);
}

.tgc-view { display: flex; flex-direction: column; height: calc(100vh - 250px); min-height: 380px; padding: 0; }
.tgc-head {
  display: flex; justify-content: space-between; align-items: flex-start; gap: 12px;
  padding: 16px 18px; border-bottom: 1px solid var(--line-2);
}
.tgc-who { font-size: 15px; font-weight: 700; }

/* Обёртка ленты: держит кнопку «вниз» на месте, пока сама лента прокручивается.
   Внутри ленты кнопка уезжала бы вместе с содержимым — то есть исчезала бы
   ровно тогда, когда нужна. */
.tgc-feed-wrap { position: relative; flex: 1; min-height: 0; display: flex; }
.tgc-feed { flex: 1; overflow-y: auto; display: flex; flex-direction: column; gap: 8px; padding: 18px; }

/* Кнопка «к последнему сообщению» со счётчиком накопившегося. Показывается
   только когда человек читает выше: подматывать его к низу нельзя — он читает,
   — но и оставить в неведении, сколько пришло, тоже. */
.tgc-jump {
  position: absolute; right: 16px; bottom: 14px; z-index: 2;
  display: none; align-items: center; gap: 4px;
  min-width: 34px; height: 34px; padding: 0 11px; border: 0; border-radius: 999px;
  font-size: 13px; font-weight: 700; color: #fff; background: var(--accent);
  box-shadow: var(--shadow-md); cursor: pointer;
}
.tgc-jump.on { display: inline-flex; }
.tgc-jump:hover { filter: brightness(1.08); }

/* Черта «непрочитанные» — место, с которого читать. */
.tgc-unread-line { display: flex; align-items: center; gap: 10px; margin: 8px 0 2px; color: var(--accent); }
.tgc-unread-line::before, .tgc-unread-line::after {
  content: ''; flex: 1; height: 1px; background: var(--accent); opacity: 0.45;
}
.tgc-unread-line span { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; }
.tgc-day { text-align: center; margin: 6px 0; }
.tgc-day span {
  font-size: 12px; color: var(--muted); background: var(--soft);
  padding: 3px 10px; border-radius: 999px;
}
.tgc-msg {
  align-self: flex-start; max-width: 76%; padding: 9px 13px;
  border-radius: 14px 14px 14px 4px; background: #eef3f6;
}
.tgc-msg.out {
  align-self: flex-end; border-radius: 14px 14px 4px 14px;
  background: rgba(15, 118, 110, 0.1);
}
.tgc-msg.bad { background: var(--danger-bg); }
.tgc-text { font-size: 14px; white-space: pre-wrap; word-break: break-word; }
.tgc-meta { margin-top: 4px; font-size: 11px; color: var(--muted); }
.tgc-media {
  margin-top: 6px; padding: 7px 10px; border-radius: var(--r-sm);
  background: rgba(22, 48, 58, 0.06); font-size: 13px;
}
.tgc-media-note { display: block; font-size: 11px; color: var(--muted); }
.tgc-deleted { margin-top: 5px; font-size: 11px; color: var(--danger); }

/* Галочки доставки. Одна — ушло, две — прочитано. Вторая заметно ярче:
   разница между «доставлено» и «прочитано» — это и есть то, ради чего на них
   смотрят, и она должна быть видна боковым зрением, без вчитывания. */
.tgc-tick { margin-left: 4px; font-size: 12px; letter-spacing: -2px; color: var(--muted-2); }
.tgc-tick.read { color: var(--accent); font-weight: 700; }
.tgc-retry {
  margin-left: 8px; padding: 0; border: 0; background: none; cursor: pointer;
  font: inherit; font-size: 11px; font-weight: 700; color: var(--danger);
  text-decoration: underline;
}
.tgc-retry[disabled] { opacity: 0.5; cursor: default; }

.tgc-compose {
  display: flex; gap: 10px; align-items: flex-end;
  padding: 12px 14px; border-top: 1px solid var(--line-2);
}
.tgc-compose .btn { flex: 0 0 auto; }
.tgc-compose-side { display: flex; flex-direction: column; gap: 6px; flex: 0 0 auto; }

/* Выбор вакансии в модалке анкеты: те же строки, что и в поиске, плюс
   отметка выбранной и глушение тех, где анкеты нет. */
.tgc-vac { flex-direction: column; align-items: flex-start; gap: 2px; }
.tgc-vac.on { border-color: var(--accent); background: rgba(15, 118, 110, 0.06); }
.tgc-vac[disabled] { opacity: 0.55; cursor: not-allowed; }
#modal-root textarea {
  width: 100%; padding: 10px 12px; border-radius: var(--r-md);
  border: 1.5px solid var(--field); background: #fff; font: inherit; font-size: 14px; resize: vertical;
}
/* Ряд заготовок над полем ответа. Пустой не занимает ничего: gap у пустого
   flex-контейнера не считается, а padding снят вместе с содержимым — диалог
   без заготовок выглядит ровно как прежде. */
/* Ряд заготовок и значок «все заготовки» в одной строке: значок про этот ряд
   и открывает его целиком, отдельной кнопкой ему быть незачем (решение
   владельца 2026-09-03). */
.tgc-chiprow { display: flex; align-items: flex-start; gap: 6px; padding: 10px 14px 0; }
.tgc-chiprow .tgc-chips { flex: 1; padding: 0; }
.tgc-chips { display: flex; flex-wrap: wrap; gap: 6px; padding: 10px 14px 0; }
.tgc-chips:empty { display: none; }

/* Отправка значком, как в мессенджерах. Слово «Ответить» вместе с «Шаблонами»
   отъедало половину ширины формы, и поле ответа оставалось узкой полоской. */
.tgc-send {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; padding: 0; border: 0; border-radius: 999px;
  color: #fff; background: linear-gradient(120deg, var(--accent), var(--accent-500));
  box-shadow: 0 12px 22px -12px rgba(15, 118, 110, 0.9);
  cursor: pointer; transition: filter 0.15s, opacity 0.15s;
}
.tgc-send:hover:not(:disabled) { filter: brightness(1.08); }
.tgc-send:disabled { opacity: 0.45; cursor: default; box-shadow: none; }
.tgc-send svg { width: 18px; height: 18px; fill: currentColor; }

.tgc-compose textarea {
  flex: 1; resize: vertical; padding: 10px 12px; border-radius: var(--r-md);
  border: 1.5px solid var(--field); background: #fff; font: inherit; font-size: 14px;
}
.tgc-compose textarea:focus { outline: none; border-color: var(--accent); }

/* Закрытый ввод объясняет причину прямо на месте кнопки. Пустое место вместо
   поля читалось бы как поломка, а не как запрет. */
.tgc-blocked {
  margin: 12px 14px; padding: 12px 14px; border-radius: var(--r-md);
  font-size: 13px; color: var(--warn); background: var(--warn-bg);
}

/* Предупреждение перед первым сообщением незнакомому. Цвет тот же, что у
   запрета: это не подсказка «как пользоваться», а единственное действие,
   способное стоить рабочего аккаунта целиком. */
.tgc-first {
  margin: 12px 14px 0; padding: 12px 14px; border-radius: var(--r-md);
  font-size: 13px; line-height: 1.5; color: var(--warn); background: var(--warn-bg);
}

/* Подключение аккаунта: код и шаги. Код держим крупным и по центру — его
   ловят камерой телефона, а не разглядывают. */
/* Содержимое окна подключения — своя колонка с отступами. Отступ у
   .modal-body между СВОИМИ детьми, а здесь всё лежит одним ребёнком, и без
   этого поле ввода и кнопки под ним слипаются. */
#tga-body { display: flex; flex-direction: column; gap: 12px; }
#tga-body .field { margin-bottom: 0; }
#tga-body .head-actions { flex-wrap: wrap; }

.tga-qr {
  display: flex; justify-content: center; align-items: center;
  padding: 14px; background: #fff; border-radius: var(--r-md);
}
.tga-qr svg, .tga-qr img { width: 220px; height: 220px; max-width: 100%; display: block; }
.tga-steps { margin: 14px 0 12px; padding-left: 20px; font-size: 13px; color: var(--text-3); }
.tga-steps li { margin-bottom: 5px; }

.tgc-media-get {
  margin-left: 6px; font-size: 12px; font-weight: 600; color: var(--accent);
  text-decoration: none; border-bottom: 1px dashed var(--accent);
}
.tgc-media-get:hover { border-bottom-style: solid; }

/* Выбор сообщений в окне «Переслать».
   Вид повторяет саму переписку — свои пузыри справа, чужие слева: выбирают
   глазами, по знакомой картинке, а в списке одинаковых серых строк приходится
   вчитываться в каждую, чтобы понять, чьё сообщение. */
.fwd-list {
  display: flex; flex-direction: column; gap: 6px;
  max-height: 320px; overflow: auto; padding: 8px;
  border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--soft);
}
.fwd-row { display: flex; align-items: flex-start; gap: 8px; cursor: pointer; }
.fwd-row.out { flex-direction: row-reverse; }
.fwd-row input { margin-top: 10px; flex: none; }
.fwd-bub {
  max-width: 82%; padding: 7px 11px; border-radius: 12px 12px 12px 4px;
  background: #eef3f6; font-size: 13px; word-break: break-word;
}
.fwd-row.out .fwd-bub { border-radius: 12px 12px 4px 12px; background: rgba(15, 118, 110, 0.1); }
/* Отмеченное видно и без взгляда на сам флажок: рамка идёт по пузырю, потому
   что глаз при выборе держится на тексте, а не на квадратике слева. */
.fwd-row input:checked + .fwd-bub { box-shadow: 0 0 0 2px var(--accent); }
.fwd-text { display: block; white-space: pre-wrap; }
.fwd-file { display: block; font-weight: 600; }
.fwd-when { display: block; margin-top: 3px; font-size: 11px; color: var(--muted); }
.fwd-count { font-weight: 400; color: var(--muted); }

/* Списки в подсказке «как работает запись». Отступ слева, чтобы номера и
   точки не наезжали на край окна, и межстрочный воздух: это текст, который
   читают целиком, а не проглядывают. */
.tgc-help { margin: 6px 0 0; padding-left: 20px; font-size: 13px; line-height: 1.5; color: var(--text-2); }
.tgc-help li { margin-bottom: 6px; }
.tgc-help b { color: var(--text); }

/* Состояние записи на собеседование в карточке диалога.
   Цветом, а не подписью: «выбрал, но не внесён» — состояние, в котором кандидат
   уверен, что записан, а его нигде не ждут. Оно должно бросаться в глаза
   раньше, чем оператор закроет диалог. */
.tgc-meet { margin: 10px 0; padding: 9px 11px; border-radius: var(--r-sm); font-size: 13px; line-height: 1.45; }
.tgc-meet.ok { background: rgba(15, 118, 110, 0.08); color: var(--text-2); }
.tgc-meet.no { background: rgba(180, 83, 9, 0.10); color: var(--text); box-shadow: inset 0 0 0 1.5px rgba(180, 83, 9, 0.35); }

/* Полоса ожидания в окне «Время собеседования». Поход в чужую систему длится
   секунды, и всё это время окно пустое: без движущейся полосы человек решает,
   что нажатие не сработало, и жмёт второй раз. */
.tgc-slotwait {
  height: 3px; margin-top: 14px; border-radius: 999px;
  background: var(--field, #e6ecec); overflow: hidden; position: relative;
}
.tgc-slotwait::after {
  content: ""; position: absolute; inset: 0; width: 40%;
  border-radius: 999px; background: var(--accent);
  animation: tgc-slotwait 1.1s ease-in-out infinite;
}
@keyframes tgc-slotwait {
  0% { transform: translateX(-100%); }
  100% { transform: translateX(250%); }
}
@media (prefers-reduced-motion: reduce) {
  .tgc-slotwait::after { animation: none; width: 100%; opacity: 0.5; }
}

/* Свободное время внешней системы: сетка часов в окне «Время собеседования».
   Часы, а не строки списка: их два десятка на два дня, и списком окно
   становится длиннее экрана — оператор выбирает вслепую, прокручивая. */
.tgc-slotrow { display: flex; flex-wrap: wrap; gap: 6px; }
.tgc-slot {
  padding: 7px 12px; border-radius: var(--r-sm); border: 1.5px solid var(--field);
  background: #fff; font: inherit; font-size: 14px; cursor: pointer;
  transition: border-color 0.15s, background 0.15s, color 0.15s;
}
.tgc-slot:hover { border-color: var(--accent); }
/* Выбранное видно цветом, а не галочкой: кнопки идут плотным рядом, и галочка
   в них не помещается, не сломав ширину. */
.tgc-slot.on { border-color: var(--accent); background: var(--accent); color: #fff; }
/* Категория под часом — когда категорий несколько: одно время бывает свободно в обеих. */
.tgc-slot-cat { display: block; font-size: 11px; font-weight: 500; opacity: 0.75; line-height: 1.2; }

.tgc-hits { max-height: 260px; overflow-y: auto; display: flex; flex-direction: column; gap: 6px; }
.tgc-hit {
  display: flex; justify-content: space-between; align-items: center; gap: 10px;
  padding: 9px 12px; border-radius: var(--r-sm); border: 1.5px solid var(--field);
  background: #fff; font: inherit; font-size: 14px; text-align: left; cursor: pointer;
}
.tgc-hit:hover { border-color: var(--accent); }

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

/* Шапка блока — столбцом, а не в строку: карточка живёт в узкой колонке
   панели, и в строку имя с двумя кнопками разваливается на три яруса. */
.tgc-card .tgc-card-head {
  display: flex; flex-direction: column; align-items: stretch;
  gap: 8px; margin-bottom: 10px;
}
.tgc-card .tgc-card-head b { margin-right: 6px; }
.tgc-card .tgc-feed { max-height: 300px; padding: 0; }
.tgc-card .tgc-msg { max-width: 88%; }
.tgc-card .tgc-compose { padding: 12px 0 0; border-top: 1px solid var(--line); }
.tgc-card .tgc-blocked { margin: 12px 0 0; }

/* Узкое окно: колонки складываются в одну. Список при этом укорачивается —
   на телефоне важнее видеть саму переписку, а не двадцать её соседей. */
@media (max-width: 900px) {
  .tgc { grid-template-columns: 1fr; }
  .tgc-list { height: auto; max-height: 260px; min-height: 0; }
  .tgc-view { height: auto; min-height: 420px; }
}

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

/* Пост читают по диагонали: решают «наше или нет». Поэтому карточка узкая и с
   обрезанным текстом, а не полотно во всю ширину — иначе на экран влезает
   полтора поста и очередь перестаёт быть обозримой. Полный текст всегда под
   рукой: разворот на месте, без ухода со страницы. */
.tg-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
  gap: 16px;
  align-items: stretch;
}
.tg-card { display: flex; flex-direction: column; gap: 12px; height: 100%; }
.tg-text {
  white-space: pre-wrap;
  font-size: 14px;
  line-height: 1.55;
  overflow: hidden;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 7;
}
.tg-text.open { -webkit-line-clamp: unset; display: block; }
.tg-more {
  align-self: flex-start;
  background: none; border: 0; padding: 0;
  color: var(--accent); font: inherit; font-size: 13px; cursor: pointer;
}
.tg-more:hover { text-decoration: underline; }
/* Кнопки решения прижаты к низу: в ряду карточки разной высоты, и без этого
   «Не наше» у соседей оказывается на разных уровнях — глаз каждый раз ищет. */
.tg-foot { margin-top: auto; }

/* Подсказки поста: телефон и @имя. Обе кликабельны — телефон набирает, @имя
   открывает переписку, — и выглядеть должны одинаково действующими. */
.tg-hints { display: flex; flex-wrap: wrap; gap: 6px; }
.tg-write {
  cursor: pointer; text-decoration: none;
  color: var(--accent-dark); background: linear-gradient(120deg, #d9f2ef, #c3e9e3);
}
.tg-write:hover { text-decoration: underline; }

/* Кнопки под сообщением: в узле сценария и в редакторе шага.
   Показаны столбиком, как их увидит собеседник в Telegram, — иначе
   «сообщение с кнопками» и обычное на экране неотличимы. */

.fl-btn-row { display: flex; gap: 6px; align-items: center; margin-bottom: 6px; }
.fl-btn-row .fl-btn-l { flex: 1; }

.fl-btn-row input { padding: 7px 10px; border: 1px solid var(--field); border-radius: 9px; background: #fbfdfd; }

/* Строка выбора флажком: вакансии и этапы в области применения. Своё
   оформление, а не инлайн в разметке: строк этих три вида в двух экранах, и
   разъезжались они каждый раз по-своему. */
.fl-vac { display: flex; gap: 9px; align-items: center; padding: 6px 8px;
  border-radius: var(--r-sm); cursor: pointer; font-size: 13px; color: var(--text-2);
  transition: background 0.12s; }
.fl-vac:hover { background: var(--soft); }
.fl-vac.on { color: var(--text); font-weight: 600; }

/* Правка кнопки: подпись и выбор ответа в одну строку. Ключ здесь не
   показывается — его придумывает система: человек связывает кнопку с ответом
   выбором, а не выдумыванием технического имени. */
.fl-btn-row { display: flex; gap: 8px; align-items: center; margin-bottom: 8px; }
.fl-btn-row .fl-btn-l { flex: 1 1 44%; min-width: 0; }
.fl-btn-row .fl-btn-goes { flex: 1 1 56%; min-width: 0; }
.fl-btn-row .fl-btn-goes .dd { width: 100%; }

/* ── экран «Воронки в диалогах» ─────────────────────────────────────────
   Второй взгляд на те же сценарии: слева воронки и этапы, посередине правка,
   справа проверка. Свои классы с приставкой fn-, и это не вкусовщина: голые
   имена вроде .btn и .media уже заняты общими стилями, и блок с таким классом
   превращался бы в кнопку. */
.fn-cols { display: grid; grid-template-columns: 300px minmax(0, 1fr) 348px; gap: 12px; align-items: start; }
/* Телефон проверки едет за экраном: перелёт по карандашу уводит вниз, на
   двадцатый шаг, и проверка, ради которой перелёт и делается, оставалась
   вверху за краем экрана (замечание владельца 2026-09-10). */
.fn-cols > :last-child { position: sticky; top: 12px; max-height: calc(100vh - 24px);
  overflow: auto; }
.fn-cols .card { padding: 13px 14px; }
.fn-cols .stack { gap: 12px; }

/* Строка списка: воронка или этап. Одинаковые намеренно — это один и тот же
   способ выбрать, и разный вид заставлял бы разбираться дважды. */
.fn-row { display: flex; align-items: center; gap: 9px; width: 100%;
  padding: 8px 10px; border-radius: 10px; background: var(--surface);
  border: 1.5px solid transparent; text-align: left; cursor: pointer;
  transition: border-color 0.12s, background 0.12s; }
.fn-row:hover { background: var(--soft); }
.fn-row.on { border-color: var(--accent); background: #fff; box-shadow: var(--shadow-sm); }
.fn-row.off { opacity: 0.62; }
.fn-n { flex: none; align-self: flex-start; width: 22px; height: 22px; border-radius: 999px;
  display: grid; place-items: center; background: #eef2f4; color: var(--text-3);
  font-size: 11px; font-weight: 800; }
.fn-row.on .fn-n { background: var(--accent); color: #fff; }
.fn-b { min-width: 0; flex: 1; }
.fn-t { display: block; font-size: 13px; font-weight: 700; color: var(--text); line-height: 1.3; }
/* Условие входа — не больше двух строк: длинное иначе распухает и хоронит
   соседние воронки. Полностью оно видно в карточке «Кому эта воронка». */
.fn-s { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; font-size: 11px; color: var(--muted); line-height: 1.35; margin-top: 2px; }
.fn-off, .fn-cnt { flex: none; align-self: flex-start; font-size: 9.5px; font-weight: 800;
  letter-spacing: 0.05em; text-transform: uppercase; padding: 2px 6px; border-radius: 999px;
  background: #eef2f4; color: var(--muted); }
.fn-cnt { background: var(--accent-soft); color: var(--accent-dark); }
/* Стрелки порядка — по наведению и у выбранной, как у этапов. */
.fn-ord { display: flex; gap: 2px; opacity: 0; transition: opacity 0.12s; }
.fn-row:hover .fn-ord, .fn-row.on .fn-ord { opacity: 1; }

/* «Кому эта воронка» и «Кандидат для проверки» — свёрнуты по умолчанию:
   задают их один раз, а этапы правят постоянно. */
.fn-who-h { display: flex; align-items: center; gap: 10px; }
.fn-who-b { min-width: 0; flex: 1; }
.fn-who-s { font-size: 12.5px; font-weight: 600; color: var(--text-2); line-height: 1.35; margin-top: 3px; }
.fn-state { flex: none; font-size: 9.5px; font-weight: 800; letter-spacing: 0.05em;
  text-transform: uppercase; padding: 3px 8px; border-radius: 999px; background: #eef2f4; color: var(--muted); }
.fn-state.on { background: var(--accent-soft); color: var(--accent-dark); }
.fn-who.open { border-left: 3px solid var(--accent); }

/* Ответ кандидата. Полоса слева по виду: без неё пять одинаковых
   прямоугольников подряд, и глазом не найти, где кнопка, а где вложение. */
.fn-ans { position: relative; overflow: hidden; padding: 0 0 12px; border-radius: 13px;
  border: 1px solid var(--line-2); background: var(--surface); margin-bottom: 12px;
  box-shadow: 0 1px 3px rgba(16, 40, 52, 0.05); }
/* Полоса слева во всю высоту карточки: по ней ветку находят глазами среди
   пяти одинаковых — где кнопка, где вложение, где «любое входящее». */
.fn-ans::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: var(--line-2); }
.fn-ans.k-btn::before { background: var(--accent-500); }
.fn-ans.k-media::before { background: #4f46e5; }
.fn-ans.k-any::before { background: var(--muted-2); }
/* Шапка ветки — своей полосой с подложкой: «на что отвечаем» и «куда после
   этого переводим» отвечают на другой вопрос, чем тексты под ними, и мешать
   их в один столбец значит заставлять перечитывать. */
.fn-ans-h { display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
  padding: 10px 12px 10px 15px; background: #fafcfd;
  border-bottom: 1px solid var(--line-2); }
.fn-ans-k { flex: none; display: inline-flex; align-items: center; padding: 4px 9px;
  border-radius: 999px; font-size: 12px; font-weight: 700; background: #eef2f4; color: var(--text-2); }
.fn-ans-k.k-btn { background: var(--accent-soft); color: var(--accent-dark); }
.fn-ans-k.k-media { background: #eceefc; color: #4f46e5; }
.fn-ans-go { margin-left: auto; display: flex; align-items: center; gap: 6px; }
.fn-ans-go select { max-width: 200px; }
.fn-cond { margin-top: 10px; padding: 9px 10px; border-radius: 9px; background: #f7fafb; }

/* Шаги ветки — столбиком с направляющей слева: она отвечает на вопрос, чьи
   это шаги. Без неё сообщение соседней ветки читалось как продолжение этой. */
.fn-steps { padding: 0 12px 0 15px; }

/* Списки выбора в настройках воронки: вакансии, исходы отбора. Рамка с
   прокруткой вместо россыпи галочек по карточке — строк бывает десяток, и
   без рамки они сливаются с остальной формой. */
.fn-pick { max-height: 168px; overflow: auto; border: 1px solid var(--line-2);
  border-radius: var(--r-sm); padding: 3px 6px; background: #fbfdfd; }
.fn-pick .fl-vac { padding: 5px 4px; }
.fn-pick .fl-vac + .fl-vac { border-top: 1px solid var(--line); }

/* Действия над воронкой: копия и снятие. Внизу карточки настроек, а не в
   шапке экрана: там они соседствовали бы с «Сохранить» и жались по ошибке. */
.fn-who-acts { display: flex; gap: 8px; margin-top: 14px;
  padding-top: 12px; border-top: 1px solid var(--line); }
.fn-who-acts .danger { color: var(--danger); }
.fn-who-acts .danger:hover { background: var(--danger-bg); color: var(--danger); }

/* Выбранная воронка в свёрнутом виде: название крупно, условие мелко. */
.fn-cur-t { font-size: 14px; font-weight: 700; color: var(--text); line-height: 1.3; margin-top: 2px; }
/* Метка и «Сменить» — своей строкой под названием: в колонке 300px они,
   стоя рядом, сжимали название до многоточия. */
.fn-cur-r { display: flex; align-items: center; gap: 8px; margin-top: 10px; }
.fn-cur-r .btn { margin-left: auto; }

/* Шаг — РАЗДЕЛ ветки, а не коробка в коробке.

   Рамка здесь была четвёртым уровнем вложенности: ветка → столбик шагов →
   сообщение → «текст сообщения», и до самого текста человек продирался через
   четыре края (владелец 2026-09-10, снимок боевого экрана). Разделяет теперь
   ЧЕРТА, а глубина держится одна: единственная рамка — сама ветка.
   Сообщение при этом остаётся ПУЗЫРЁМ — тем же, каким его увидит собеседник. */
.fn-step { padding: 12px 0 2px; }
.fn-step + .fn-step { border-top: 1px solid var(--line); }
.fn-step.rem .fn-part { background: rgba(254, 240, 199, 0.4); border-color: rgba(208, 162, 21, 0.3); }
/* Выбытие: тот же приём, что у напоминания, но цветом опасного действия —
   после этого шага кандидат из воронки уходит. */
.fn-step.out .fn-part { background: var(--danger-bg); border-color: rgba(180, 35, 24, 0.25); }
.fn-step.out .fn-step-k { color: var(--danger); background: var(--danger-bg); }
.fn-step-h { display: flex; align-items: center; gap: 8px; margin-bottom: 7px; }
/* Номер шага внутри ветки: порядок здесь — это и есть смысл, а пять одинаковых
   пузырей подряд его не показывают. */
.fn-step-n { flex: none; width: 19px; height: 19px; display: grid; place-items: center;
  border-radius: 999px; background: var(--line); color: var(--text-3);
  font-size: 11px; font-weight: 800; }
.fn-step.rem .fn-step-n { background: var(--warn-bg); color: var(--warn); }
.fn-step-k { display: inline-flex; align-items: center; gap: 5px;
  font-size: 10px; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--accent-dark); background: var(--accent-soft); padding: 3px 8px; border-radius: 999px; }
.fn-step.rem .fn-step-k { color: var(--warn); background: var(--warn-bg); }
/* Подпись подблока — просто подпись: рамку она больше не заводит. */
.fn-kb .fn-part-c { margin-top: 11px; }
.fn-wait { margin-left: auto; display: flex; align-items: center; gap: 5px;
  font-size: 11.5px; color: var(--muted); }
.fn-wait input { width: 58px; padding: 4px 7px; font-size: 12px; text-align: right; }
/* Текст сообщения. Рамку держит подблок, поэтому у самого поля её нет: две
   рамки в двух миллиметрах друг от друга — та самая «вложенность». Скруглено
   с трёх углов, как исходящее в переписке. */
.fn-step textarea { min-height: 58px; border-radius: 12px; border-bottom-left-radius: 5px;
  background: transparent; border-color: transparent; padding: 0; }
.fn-step textarea:focus { background: transparent; border-color: transparent; }
.fn-part:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(23, 163, 150, 0.1); }

.fn-kb { margin-top: 9px; }
.fn-kb .fl-btn-row { margin-bottom: 5px; }
/* Кнопки добавления — подвал СВОЕЙ ветки, отчёркнутый пунктиром. Раньше они
   висели между последним шагом и следующей веткой, и было неясно, к какой из
   двух добавится сообщение. */
.fn-add { display: flex; gap: 6px; margin: 11px 12px 0 15px; padding-top: 10px;
  border-top: 1px dashed var(--line-2); }

/* Выбор нескольких значений тегами: вакансии и исходы отбора. Выбранное
   стоит чипами, остальное лежит в списке — видно результат, а не справочник. */
.fn-tags { display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  min-height: 38px; padding: 5px 7px; border: 1.5px solid var(--field);
  border-radius: var(--r-md); background: #fff; }
.fn-tag { display: inline-flex; align-items: center; gap: 5px; padding: 3px 5px 3px 10px;
  border-radius: 999px; background: var(--accent-soft); color: var(--accent-dark);
  font-size: 12.5px; font-weight: 700; }
.fn-tag-x { border: 0; background: none; cursor: pointer; color: var(--accent-dark);
  font-size: 14px; line-height: 1; padding: 0 3px; border-radius: 999px; opacity: 0.6; }
.fn-tag-x:hover { opacity: 1; background: rgba(11, 92, 86, 0.12); }
.fn-tag-none { font-size: 12.5px; color: var(--muted-2); padding: 0 4px; }
/* Добавление — обычный список, но без рамки: рамка внутри рамки читается как
   вторая форма. */
.fn-tag-add { width: auto; min-width: 116px; padding: 4px 8px; font-size: 12.5px;
  border: 1px dashed var(--field); background: transparent; color: var(--text-3);
  margin-left: auto; }
.fn-tag-add:focus { border-style: solid; }

/* Условие по ответу в анкете: вопрос сверху, выбранные варианты тегами под
   ним. Рамкой, потому что условий бывает несколько и без границы они читаются
   как один длинный список полей.

   Имена НЕ .fn-ans: так называется ветка ответа внутри этапа, и совпадение
   перебивало ей отступ под цветную полоску и добавляло чужую рамку — из-за
   чего блоки этапа и «слипались в один див» (замечание владельца 2026-09-10). */
.fn-flt { padding: 9px 10px; border: 1px solid var(--line); border-radius: 10px;
  background: rgba(255, 255, 255, 0.75); }
.fn-flt-h { display: flex; align-items: center; gap: 8px; }
.fn-flt-h .dd { flex: 1; min-width: 0; }

/* Условие запуска в «Кому эта воронка» — тот же вид строки, что у условия по
   анкете, но СВОИ имена: общие имена у разных вещей уже стоили ветке ответа
   рамки и отступа (Р42). */
.fn-trg { padding: 9px 10px; border: 1px solid var(--line); border-radius: 10px;
  background: rgba(255, 255, 255, 0.75); }
.fn-trg-h { display: flex; align-items: center; gap: 8px; }
.fn-trg-h .dd { flex: 1; min-width: 0; }

/* Выбор воронки для ручного запуска в карточке диалога. Узкий, рядом с
   кнопкой: обычно его не трогают — по умолчанию подбор идёт по этапу. */
.tgc-flow-pick { max-width: 190px; padding: 5px 8px; font-size: 12.5px;
  border: 1px solid var(--field); border-radius: var(--r-sm); background: #fbfdfd; }

/* Название открытой воронки в шапке. Крупно и рядом с заголовком: правки
   ложатся именно в неё, и вопрос «а что я сейчас правлю» не должен требовать
   разворачивать карточку. */
.fn-head-n { margin-top: 3px; font-size: 13.5px; font-weight: 700; color: var(--accent-dark); }

/* Время у кнопки: нажатие записывает кандидата на собеседование. Узкое поле
   между подписью и «ведёт к», подсвечено, когда заполнено, — иначе кнопку,
   которая записывает, не отличить от обычной. */
.fl-btn-slot { width: 68px; flex: none; text-align: center; padding: 7px 6px;
  border: 1px solid var(--field); border-radius: 9px; background: #fbfdfd; font-size: 12.5px; }
.fl-btn-slot.on { border-color: var(--accent); background: var(--accent-soft);
  color: var(--accent-dark); font-weight: 700; }

/* Якорь шага в его шапке: «через паузу» / «до встречи» / «в день встречи». */
.fn-wait .dd.fn-when { width: 150px; flex: none; }
.fn-wait .dd.fn-when .dd-btn { padding: 4px 8px; font-size: 11.5px; }
.fn-wait input[type="time"] { width: 92px; padding: 4px 7px; font-size: 12px; }

/* Перенос блока в другую ветку: строка над текстом, раскрывается значком.
   Над текстом, а не в шапке шага: в шапке уже четыре элемента, и пятый
   выпадающий список сжал бы поля паузы до нечитаемых. */
.fn-move { display: flex; align-items: center; gap: 8px; margin-top: 9px;
  padding: 8px 10px; border-radius: 10px; background: var(--accent-soft);
  border: 1px solid rgba(23, 163, 150, 0.25); }
.fn-move .dd { flex: 1; min-width: 0; }

/* Подблоки внутри шага: текст сообщения и кнопки под ним.

   Рамки ВЕРНУЛИСЬ (владелец 2026-09-10: «вот эти линии ты потерял»). Жалоба на
   вложенность была про наружный уровень — ветки на одном белом листе; её
   лечит разрыв между карточками. Внутри рамка уместна: поле ввода и группа
   кнопок — разные сущности, и линия отвечает, где кончается одна.
   Рамок при этом ДВЕ, а не три: коробка вокруг самого шага не вернулась. */
.fn-part { margin-top: 9px; padding: 10px 12px; border-radius: 10px;
  background: var(--surface); border: 1px solid var(--line-2); }
.fn-part-c { font-size: 10px; font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--muted-2); margin-bottom: 7px; }
.fn-kb .fl-btn-row:last-of-type { margin-bottom: 8px; }
.fn-kb { background: #fbfdfd; }
/* Запись на собеседование у сообщения — строкой состояния, поля под «Настроить»
   (владелец 2026-09-15: «так не нужно видеть постоянно настройки»). */
.fn-sb-h { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.fn-sb-h .fn-part-c { margin: 0; }
.fn-sb-s { flex: 1; min-width: 0; font-size: 12px; color: var(--muted); }
.fn-sb-s.on { color: var(--accent-dark); font-weight: 600; }
.fn-sb-b { margin-top: 10px; }

/* Пауза в проверке: «прошло столько-то». Двумя сообщениями подряд лента врёт —
   второе ждёт сутки, и на этом ожидании держится весь догрев. */
.fn-gap { display: flex; align-items: center; gap: 9px; margin: 9px 2px; color: var(--muted-2);
  font-size: 11px; }
.fn-gap::before, .fn-gap::after { content: ""; flex: 1; height: 1px; background: var(--line-2); }
.fn-gap span { flex: none; }

/* Стрелка правки у нашего сообщения в проверке: увидев не тот текст, человек
   попадает в него одним нажатием. */
.fn-msg.we { position: relative; }
.fn-edit { position: absolute; top: 5px; right: 5px; width: 22px; height: 22px;
  display: grid; place-items: center; border: 1px solid var(--line-2); border-radius: 7px;
  background: #fff; color: var(--muted); font-size: 12px; cursor: pointer; opacity: 0;
  transition: opacity 0.12s, color 0.12s, border-color 0.12s; }
.fn-msg.we:hover .fn-edit { opacity: 1; }
.fn-edit:hover { color: var(--accent); border-color: var(--accent); }

/* Куда прыгнули — подсвечивается на секунду, иначе после перелёта неясно,
   какой из похожих блоков открылся. */
.fn-step.flash { animation: fnflash 1.4s ease-out; }
@keyframes fnflash {
  0%, 40% { box-shadow: 0 0 0 3px rgba(23, 163, 150, 0.35); border-color: var(--accent); }
  100% { box-shadow: none; }
}

/* Телефон проверки. Кнопки жмутся В СООБЩЕНИИ, как в Telegram, а не
   выбираются снизу: снизу они читались бы как меню, и правило «кнопки
   прошлого сообщения гаснут» проверить было бы нечем. */
.fn-ph { position: sticky; top: 14px; display: flex; flex-direction: column;
  border-radius: 24px; border: 9px solid #16242b; background: #f2f6f8; overflow: hidden;
  box-shadow: var(--shadow-md); height: calc(100vh - 320px); min-height: 380px; }
.fn-ph-h { padding: 10px 13px; background: #fff; border-bottom: 1px solid var(--line-2); }
.fn-ph-w { font-size: 10px; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }
.fn-ph-s { font-size: 13.5px; font-weight: 700; color: var(--text); }
.fn-log { flex: 1; overflow: auto; padding: 14px 12px; display: flex; flex-direction: column; gap: 9px; }
.fn-msg { max-width: 88%; padding: 9px 12px; border-radius: 14px; font-size: 13px;
  line-height: 1.45; white-space: pre-wrap; }
.fn-msg.we { align-self: flex-start; background: #fff; border-bottom-left-radius: 6px; box-shadow: var(--shadow-sm); }
.fn-msg.they { align-self: flex-end; background: var(--accent-soft); border-bottom-right-radius: 6px; }
.fn-sys { align-self: center; max-width: 92%; text-align: center; font-size: 11.5px; color: var(--muted); }
.fn-sys.rem { color: var(--warn); }
.fn-sys.out { color: var(--danger); }
.fn-mkb { display: flex; flex-direction: column; gap: 4px; margin-top: 8px; }
.fn-mb { display: block; width: 100%; padding: 6px 10px; border-radius: 9px;
  border: 1px solid #bfe3dd; background: #fff; color: var(--accent-dark);
  font-size: 12.5px; font-weight: 700; text-align: center; cursor: pointer; }
.fn-mb:hover { background: var(--accent-soft); }
/* Погашенная кнопка прошлого сообщения: видно, что она была, и что нажать её
   уже нельзя. */
.fn-mb.off { opacity: 0.42; cursor: default; border-color: var(--line-2); background: var(--soft); }
.fn-start { margin: auto; display: flex; flex-direction: column; align-items: center;
  gap: 14px; padding: 20px; text-align: center; }
.fn-start p { font-size: 12.5px; color: var(--muted); line-height: 1.45; }
.fn-tools { display: flex; flex-wrap: wrap; gap: 6px; padding: 9px 11px; background: #fff;
  border-top: 1px solid var(--line-2); }
.fn-tool { padding: 5px 10px; border-radius: 999px; background: #eef2f4; border: 0;
  font: inherit; font-size: 12px; font-weight: 600; color: var(--text-2); cursor: pointer; }
.fn-tool:hover { background: #e2eaee; }
.fn-tool.m { background: #eceefc; color: #4f46e5; }

/* Кнопки в переписке: то, что собеседник видит под нашим сообщением, и его
   нажатие. Без этого по ленте не отличить выбор из предложенного от того,
   что человек написал сам, — а это и есть разница между веткой и текстом. */
.tgc-btns { display: flex; flex-direction: column; gap: 4px; margin-top: 8px; }
.tgc-btn { padding: 6px 10px; border-radius: 9px; text-align: center; font-size: 12.5px;
  font-weight: 700; background: rgba(255,255,255,.55); color: var(--accent-dark, #0b5c56); }
.tgc-msg:not(.out) .tgc-btn { background: var(--accent-soft, #e6f4f2); }
.tgc-press { font-size: 13px; color: var(--text-2); }
.tgc-press b { font-weight: 700; color: var(--accent-dark, #0b5c56); }
l-ico.sm { width: 28px; height: 28px; border-radius: 9px; }

/* ── заготовка автоответа в переписке (#/tg/chats) ─────────────────────────
 *
 * Живёт в поле ответа, а не на отдельном экране: решение принимают, глядя на
 * переписку, а не на список. Пунктирная рамка отличает подготовленное системой
 * от написанного человеком — иначе через день не вспомнить, кто это писал. */
.fl-draft { padding: 10px 14px 0; }
.fl-draft-head { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; font-size: 12px; font-weight: 700; color: var(--accent-dark); }
.fl-draft-head .fl-stale { color: var(--warn); }
.fl-draft-box {
  width: 100%; padding: 11px 12px; border-radius: 12px;
  border: 1px dashed var(--accent); background: rgba(15, 118, 110, 0.03);
  font: inherit; font-size: 13px; line-height: 1.5; color: var(--text-2); resize: vertical;
}
.fl-draft-acts { display: flex; gap: 8px; align-items: center; margin-top: 10px; }
.fl-draft-note { margin-right: auto; font-size: 12px; color: var(--muted); }

/* Пометка в списке диалогов: по этому диалогу готова заготовка. */
.fl-mark {
  font-size: 10.5px; font-weight: 800; padding: 2px 7px; border-radius: 999px; white-space: nowrap;
  background: rgba(15, 118, 110, 0.12); color: var(--accent-dark);
}
.fl-mark.wait { background: var(--warn-bg); color: var(--warn); }

/* ── Правила автоматики (#/rules) ──────────────────────────────────────────
 *
 * Экран собран по утверждённому прототипу design/rules-constructor.html.
 * Главный вид — карта: событие слева, правило в центре, действие справа, между
 * ними линии. Список правил отвечал на вопрос «какие правила есть», а нужен
 * ответ на другой — «что происходит с событием, пока оно идёт по системе».
 *
 * Наведение гасит всё, кроме одной цепочки (.is-dim): схема из тридцати линий
 * иначе не читается вовсе.
 */
.rl-switcher { display: flex; gap: 2px; background: var(--soft); border-radius: 10px; padding: 2px; }
.rl-tab {
  border: 0; background: transparent; cursor: pointer; border-radius: 8px;
  font: 700 12px/1 Manrope, sans-serif; color: var(--text-3); padding: 8px 12px;
}
.rl-tab.on { background: var(--surface); color: var(--text); box-shadow: var(--shadow-sm); }

.rl-chips { display: flex; flex-wrap: wrap; gap: 6px; margin: 14px 0; }
.rl-chip {
  border: 1px solid var(--line-2); background: var(--surface); color: var(--text-3);
  font: 700 12px/1 Manrope, sans-serif; padding: 8px 12px; border-radius: 999px; cursor: pointer;
}
.rl-chip:hover { border-color: var(--accent-500); color: var(--accent-dark); }
.rl-chip.on { background: var(--accent); border-color: var(--accent); color: #fff; }
.rl-chip span { opacity: .6; margin-left: 5px; }

/* minmax(0, …) и min-width:0 обязательны: по умолчанию элемент сетки не
 * сжимается меньше своего содержимого, и длинная подпись правила распирала
 * карту шире окна. Рабочая область при этом не прокручивается (у оболочки
 * overflow: hidden), поэтому третья колонка просто уезжала за край — молча. */
.rl-map {
  position: relative; display: grid; align-items: start;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.5fr) minmax(0, 1fr) 280px;
  gap: clamp(20px, 2.4vw, 44px);
  /* Полка разбора пустует, пока цепочку не закрепили, — а в разделе из одного
   * правила карта оказалась бы ниже карточки разбора, и та вылезла бы на
   * пояснение под картой. Нижний предел держит место под неё заранее. */
  min-height: 320px;
}
.rl-links { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 0; overflow: visible; }
.rl-col { position: relative; z-index: 1; min-width: 0; display: flex; flex-direction: column; gap: 8px; }
.rl-cap {
  font: 700 11px/1 Manrope, sans-serif; letter-spacing: .08em; text-transform: uppercase;
  color: var(--muted); padding: 0 2px 4px;
}
.rl-node, .rl-rule {
  background: var(--surface); border: 1px solid var(--line-2); border-radius: var(--r-md);
  padding: 9px 11px; box-shadow: var(--shadow-sm); transition: .15s;
}
.rl-ev { border-left: 3px solid var(--accent-500); }
/* Класс действия — цветом. Внутреннее остаётся в системе, «через человека»
 * ждёт нажатия, «наружу само» уходит без спроса. Разница видна с одного
 * взгляда, а не при разборе каждого правила. */
.rl-ac { border-left: 3px solid #7aa7b5; }
.rl-ac.is-draft { border-left-color: #d9b23c; }
.rl-ac.is-out { border-left-color: var(--danger); }
.rl-rule { cursor: pointer; }
.rl-rule.is-off { background: #f8fbfb; border-style: dashed; box-shadow: none; }
.rl-rule.is-off .rl-rt { color: var(--muted); }
.rl-nt, .rl-rt { font-weight: 700; font-size: 13px; line-height: 1.3; overflow-wrap: anywhere; }
.rl-rt { font-weight: 800; }
.rl-nd, .rl-rd { font-size: 11.5px; color: var(--muted); margin-top: 2px; }
.rl-node:hover, .rl-rule:hover { border-color: var(--accent-500); transform: translateY(-1px); }
.is-dim { opacity: .16 !important; filter: saturate(.3); }

/* Каталог без правил на карте: видно, что оно ЕСТЬ, и видно, что не в работе.
 * Бледность своя, а не .is-dim подсветки: у той полупрозрачность гашения при
 * наведении, и узел «пока не используется» тонул бы вместе с погашенными. */
.rl-node.rl-dim { opacity: .5; filter: saturate(.4); }
.rl-node.rl-dim .rl-nd { color: var(--muted-2); font-style: italic; }
.rl-chipgap { flex: 1; }

/* ── Закреплённая цепочка и разбор справа ──────────────────────────────────
 *
 * Подсветка держалась на наведении и слетала от любого движения курсора:
 * чтобы прочитать цепочку из трёх узлов, приходилось замирать мышью, а стоило
 * перевести взгляд — карта «прыгала». Клик закрепляет цепочку, и она стоит.
 *
 * Полка разбора занимает место ВСЕГДА, даже пустая. Если бы она появлялась
 * вместе с закреплением, карта пересобиралась бы ровно в момент клика — то же
 * дёрганье, только по другой причине.
 */
.rl-mapside { position: relative; z-index: 2; min-width: 0; align-self: stretch; }
.rl-pinhint {
  border: 1px dashed var(--line-2); border-radius: var(--r-md); padding: 10px 12px;
  font-size: 12px; color: var(--muted); line-height: 1.5;
}
.rl-node.is-pin, .rl-rule.is-pin {
  border-color: var(--accent); box-shadow: 0 0 0 3px rgba(23, 163, 150, .18);
  /* Закреплённый узел не гаснет и не бледнеет, даже когда правил на нём нет:
   * иначе клик по незадействованному действию гасил бы и его самого, и было
   * бы не видно, что вообще закреплено. */
  opacity: 1 !important; filter: none !important;
}
.rl-pincard {
  position: absolute; left: 0; right: 0; overflow: auto;
  background: var(--surface); border: 1px solid var(--accent-500);
  border-radius: var(--r-md); box-shadow: var(--shadow-md); padding: 11px 12px;
  transition: top .12s;
}
.rl-pinh { font-weight: 800; font-size: 13px; line-height: 1.3; }
.rl-pink { font-size: 11.5px; color: var(--muted); margin-top: 2px; }
.rl-pink.is-draft { color: var(--warn); }
.rl-pink.is-out { color: var(--danger); }
.rl-pintags { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 5px; }
.rl-pinr { border-top: 1px solid var(--line-2); margin-top: 9px; padding-top: 8px; }
.rl-pinrt { font-weight: 700; font-size: 12.5px; line-height: 1.35; }
.rl-pinl { font-size: 12px; color: var(--text-3); line-height: 1.5; margin-top: 3px; }
.rl-pinl b { color: var(--text-2); font-weight: 700; }
.rl-pinstep { display: flex; gap: 8px; margin-top: 6px; }
.rl-pinw { flex: none; width: 58px; font-size: 11.5px; color: var(--muted); line-height: 1.5; }
.rl-pinlim, .rl-pinrun { color: var(--muted); font-size: 11.5px; margin-top: 4px; line-height: 1.45; }
.rl-pinoff { color: var(--muted); font-size: 12px; line-height: 1.5; }
.rl-pinalso {
  border-top: 1px solid var(--line-2); margin-top: 9px; padding-top: 7px;
  font-size: 11.5px; color: var(--muted); line-height: 1.5;
}
.rl-pincard .btn { margin-top: 9px; }
.rl-pincard /* Блок «Что не сходится» в правой колонке карты.
 *
 * Отделён от разбора рамкой сверху, а не карточкой: это не ещё одна сущность
 * на экране, а продолжение той же полки. Жёлтый — потому что находка тут не
 * поломка, а вопрос: система работает, но связи между правилами разъехались.
 */
.rl-audit { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line-2); }
.rl-audit-h { font-weight: 700; font-size: 13px; margin-bottom: 8px; }
.rl-audit.is-ok .rl-audit-h { color: var(--accent); }
.rl-audit-i {
  margin: 10px 0; padding: 9px 11px; border-radius: var(--r-md);
  background: var(--warn-bg); border: 1px solid #f2dfa0;
}
.rl-audit-t { font-weight: 600; font-size: 12.5px; margin: 5px 0 3px; color: #553d05; }
.rl-audit-i .rl-sub { color: #6b4d06; }

.rl-note { margin: 8px 0 0; padding: 8px 10px; font-size: 11.5px; }

/* Погашенный узел под курсором не подпрыгивает: пока цепочка закреплена, мышь
 * идёт по карте насквозь, и каждый встречный узел дёргался на пиксель — тот
 * самый шум, ради которого всё и затевалось. */
.is-dim:hover { transform: none !important; border-color: var(--line-2) !important; }

/* Медиазапроса по ширине ОКНА здесь намеренно нет, хотя в прототипе он был.
 *
 * В прототипе страница действительно сжималась, и на узком экране четвёртая
 * колонка съедала карту. В системе так не бывает: .wrap держит min-width
 * 1280px, а .main прокручивается вбок (см. «Рабочая область» выше). Полотно
 * карты — 1180px при любом окне до ~1550px, и четыре колонки в него влезают
 * всегда: 230 / 345 / 230 / 280 при зазорах.
 *
 * Запрос по окну сложил бы карту там, где в системе не складывается больше
 * ничего: на 1280 третья колонка у остальных экранов просто уезжает под
 * горизонтальную прокрутку. Разное поведение одного и того же окна на соседних
 * экранах читается как поломка, а не как забота. Проверено на стенде
 * 2026-09-05: при окне 1440 у .main уже есть боковая прокрутка, а карта всё
 * та же 1180. */

.rl-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); gap: 10px; }
.rl-tile {
  background: var(--surface); border: 1px solid var(--line-2); border-radius: var(--r-md);
  padding: 12px 14px; box-shadow: var(--shadow-sm); display: flex; flex-direction: column; gap: 8px;
}
.rl-tile.is-off { background: #f8fbfb; border-style: dashed; box-shadow: none; }
.rl-tile-head { display: flex; align-items: flex-start; gap: 8px; }
.rl-tile-name { font-weight: 800; font-size: 13.5px; flex: 1; line-height: 1.3; }
.rl-tile-body { font-size: 12.5px; color: var(--text-3); line-height: 1.5; }
.rl-tile-tags { display: flex; gap: 5px; flex-wrap: wrap; }
.rl-tile-foot {
  display: flex; align-items: center; gap: 8px; margin-top: auto;
  padding-top: 8px; border-top: 1px solid var(--line);
}
.rl-load { font-size: 12px; color: var(--muted); margin-right: auto; }
.rl-lab {
  display: inline-block; min-width: 46px; font: 700 11px/1 Manrope, sans-serif;
  text-transform: uppercase; letter-spacing: .05em; color: var(--muted-2);
}

.rl-two { display: grid; grid-template-columns: minmax(0, 1fr) 340px; gap: 18px; align-items: start; }
.rl-side { position: sticky; top: 0; }
.rl-sec { margin: 16px 0 8px; font-size: 13px; font-weight: 800; display: flex; gap: 7px; align-items: center; }
.rl-cond { display: grid; grid-template-columns: 1fr 130px 1fr auto; gap: 6px; margin-bottom: 6px; }
/* Шаг — карточка с колонкой «когда» слева, как в утверждённом прототипе.
 * Колонка нужна не для красоты: она держит взгляд на порядке и на классе
 * действия, а не на подписях полей. */
.rl-step {
  display: grid; grid-template-columns: 96px minmax(0, 1fr) auto; gap: 12px; align-items: start;
  border: 1px solid var(--line-2); border-radius: var(--r-md);
  padding: 10px 12px; margin-bottom: 8px; background: #fbfdfd;
}
.rl-step-body { min-width: 0; }
.rl-when {
  font: 800 11px/1.3 Manrope, sans-serif; color: var(--accent-dark);
  background: rgba(15, 118, 110, 0.08); border-radius: 8px; padding: 8px 6px; text-align: center;
}
.rl-when small { display: block; margin-top: 3px; font-weight: 600; opacity: 0.75; }
.rl-step.is-draft .rl-when { color: #6b4d06; background: var(--warn-bg); }
.rl-step.is-out .rl-when { color: var(--danger); background: var(--danger-bg); }

/* Нить между шагами предпросмотра: цепочка читается как одно, а не как стопка
 * отдельных строк. */
.rl-fline { height: 12px; border-left: 2px dotted var(--line-2); margin-left: 14px; }

.rl-bars { display: flex; align-items: flex-end; gap: 2px; height: 40px; margin: 10px 0 2px; }
.rl-bars i {
  flex: 1; min-height: 2px; border-radius: 2px 2px 0 0;
  background: var(--accent-500); opacity: 0.75;
}
.rl-bars i.hot { background: var(--danger); opacity: 0.85; }
.rl-nobars { margin: 8px 0 2px; font-size: 12px; color: var(--muted); }
.rl-read { font-size: 13px; color: var(--text-3); line-height: 1.6; }
.rl-flow { margin-top: 8px; display: flex; flex-direction: column; gap: 6px; }
.rl-fstep {
  font-size: 12.5px; line-height: 1.45; padding: 8px 10px;
  background: rgba(15, 118, 110, .06); border-radius: var(--r-sm);
}
.rl-kpi { font: 800 22px/1.2 Manrope, sans-serif; letter-spacing: -.02em; }
.rl-kpi span { color: var(--accent); }

.rl-hit {
  display: grid; grid-template-columns: 26px 1fr; gap: 10px; align-items: start;
  border: 1px solid var(--line-2); border-radius: var(--r-md); padding: 9px 11px; margin-bottom: 6px;
}
.rl-hit.is-win { border-color: var(--accent-500); background: rgba(23, 163, 150, .05); }
.rl-no { font: 800 12px/1.6 Manrope, sans-serif; color: var(--muted-2); text-align: center; }
.rl-hit-name { font-weight: 700; font-size: 13px; display: flex; gap: 7px; align-items: center; }
.rl-act { font-size: 12.5px; color: var(--text-2); margin-top: 3px; }

/* Редактор правила — окно шире обычного: слева сборка, справа предпросмотр.
 * В 560 пикселях две колонки превращаются в две узкие полосы, и предпросмотр
 * перестаёт быть читаемым — то есть перестаёт делать то, ради чего он есть. */
.modal-wide { width: min(980px, 100%); }

/* ── разделы «Журнал», «Справочник», «Как устроено» ──────────────────────
 *
 * Собраны по утверждённому прототипу (design/rules-constructor.html) на
 * токенах панели, а не на его собственных: прототип свои токены оттуда и брал,
 * и вторая копия палитры разъехалась бы с первой на первой же правке темы.
 *
 * .rl-note — то, что в прототипе называется .note: рамка с подписью «вот цена
 * этого решения». До 2026-09-05 экран правил печатал такие блоки классом
 * .note, у которого в панели НЕТ оформления вовсе (есть только .note .k / .v
 * от заметки в карточке кандидата). Двенадцать предупреждений на экране
 * рисовались голым текстом и читались как продолжение абзаца — то есть не
 * читались. Класс здесь свой, а не дописанный к .note, чтобы не задеть
 * карточку кандидата: у неё .note значит другое.
 */
.rl-note {
  margin: 12px 0; padding: 11px 14px; border-radius: var(--r-md);
  background: var(--warn-bg); border: 1px solid #f2dfa0; color: #6b4d06;
  font-size: 12.5px; line-height: 1.55;
}
.rl-note b { color: #553d05; }
.rl-note.is-bad {
  background: var(--danger-bg); border-color: rgba(180, 35, 24, .25); color: var(--danger);
}
.rl-note.is-bad b { color: var(--danger); }

/* Переключатель на шесть разделов: в узком окне переносится строкой, а не
 * сжимает подписи до нечитаемых огрызков. */
.rl-switcher { flex-wrap: wrap; margin-bottom: 14px; }

/* Таблицы справочника и журнала. Отдельно от table.t: там строки-карточки с
 * крупным шрифтом под списки людей, здесь плотная таблица под справочные
 * данные, которые читают глазами по колонкам. */
.rl-tbl { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.rl-tbl th {
  text-align: left; padding: 0 10px 8px 0; border-bottom: 1px solid var(--line-2);
  font: 700 10px/1.3 Manrope, sans-serif; letter-spacing: .07em;
  text-transform: uppercase; color: var(--muted); white-space: nowrap;
}
.rl-tbl td {
  padding: 9px 10px 9px 0; border-bottom: 1px solid var(--line);
  vertical-align: top; line-height: 1.45;
}
.rl-tbl tr:last-child td { border-bottom: 0; }
.rl-tbl tr:hover td { background: #f5f9fa; }
/* Числа в колонку: цифры разной ширины мешают сравнивать столбец глазами,
   ради чего столбец и существует. */
.rl-tbl td.num, .rl-tbl th.num {
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.rl-tbl .rl-hint { margin-top: 2px; }
.rl-tbl .tag { margin-right: 4px; }
/* Таблица шире окна прокручивается внутри карточки, а не растягивает экран:
   рабочая область панели не прокручивается вбок, и колонка просто уезжала бы
   за край — молча. */
.rl-tblwrap { overflow-x: auto; }

/* Ссылка на правило внутри таблицы: кнопка по разметке (открывает редактор),
   ссылка по виду. */
.rl-link {
  border: 0; background: 0; padding: 0; cursor: pointer; text-align: left;
  font: 700 12.5px/1.45 Manrope, sans-serif; color: var(--accent-dark);
}
.rl-link:hover { text-decoration: underline; }

/* Карточка решений владельца — единственная выделенная цветом на «Как
   устроено»: это не рассуждение автора, а зафиксированное решение, и отличать
   их надо с одного взгляда. */
.rl-owner { background: rgba(15, 118, 110, .05); box-shadow: inset 0 0 0 1px rgba(15, 118, 110, .2); }
.rl-cost { margin-top: 6px; padding-top: 6px; border-top: 1px solid var(--line); }

/* Срок возврата в очередь: число и единица одной строкой. */
.rl-after { display: flex; gap: 8px; }
.rl-after input { width: 90px; flex: none; }

/* Поля редактора и проверки — размечены как формы системы (.field: подпись
   сверху, поле, подсказка), а не строками с выдуманной подписью слева. До
   2026-09-05 здесь стоял класс .lbl, которого в панели нет: подписи были без
   ширины и веса, колонка не строилась, поля стояли рвано. Списки — dropdown
   из core.js, поэтому .dd внутри поля растягивается на его ширину. */
.rl-form { display: grid; gap: 12px; }
.rl-form + .rl-form { margin-top: 12px; }
.rl-form .field .dd { width: 100%; }
/* Подсказка под списком действия и под событием — с отступом до полей ниже,
   иначе она прилипает к подписи следующего поля и читается как его часть. */
.rl-step-body > .rl-hint { margin: 4px 0 10px; }
.rl-form > .field > .dd + .rl-hint { margin-top: 2px; }
.rl-check-form { max-width: 620px; margin-bottom: 4px; }

/* Подсказка со своим именем. .hint в панели оформлен только внутри .field и
   .sheet-foot; вне их он рисовался обычным текстом в 14px — подсказки этого
   экрана читались как продолжение абзаца. */
.rl-hint { font-size: 11.5px; line-height: 1.45; color: var(--muted-2); }
.rl-lbl { font-size: 13px; font-weight: 600; color: var(--text-2); }

/* Условие: поле · оператор · значение · убрать. Списки системы в ячейках
   сетки, ширина у них от ячейки. */
.rl-cond .dd { min-width: 0; }
.rl-after { display: flex; gap: 8px; align-items: center; }
.rl-after input { width: 90px; flex: none; }
.rl-after .dd { flex: 1; max-width: 180px; }

/* ── экран правил — вид по утверждённому прототипу ───────────────────────
   design/rules-constructor.html — образец, значения оттуда один в один.
   Потолок ширины 1180px тоже его: у .wrap панели есть min-width и нет max,
   и на широком мониторе колонки уезжали в бесконечность. */
.rl-wrap { max-width: 1180px; }
.rl-views { margin-bottom: 14px; }

/* Карточка прототипа: рамка, радиус 16, заголовок 15/800 — а не «card»
   панели с капителью. Владелец сверяет экран с прототипом глазами. */
.rl-card {
  background: var(--surface); border: 1px solid var(--line-2); border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm); padding: 16px 18px; margin-bottom: 12px;
}
.rl-card-t { font-weight: 800; font-size: 15px; margin-bottom: 6px; display: flex; align-items: center; gap: 8px; }

/* Искра срабатываний в плитке — прототипный .spark. */
.rl-tile-body b { color: var(--text-2); }
.rl-spark { display: flex; align-items: flex-end; gap: 1px; height: 22px; flex: 1; min-width: 60px; }
.rl-spark i { flex: 1; background: var(--accent-500); opacity: .5; border-radius: 1px; min-height: 1px; }
.rl-spark i.hot { background: var(--danger); opacity: .75; }

/* Дорожка разбора — прототипный .track/.trk: номер, имя, причина, вердикт. */
.rl-track { display: flex; flex-direction: column; gap: 6px; }
.rl-trk {
  display: grid; grid-template-columns: 26px 1fr auto; gap: 10px; align-items: center;
  padding: 9px 12px; border-radius: var(--r-md); border: 1px solid var(--line-2); background: var(--surface);
}
.rl-trk .rl-no { font: 800 12px/1 Manrope, sans-serif; color: var(--muted-2); text-align: center; }
.rl-trk-n { font-weight: 700; font-size: 13px; }
.rl-trk-w { font-size: 11.5px; color: var(--muted); margin-top: 2px; }
.rl-trk.is-win { border-color: var(--accent-500); background: rgba(23, 163, 150, .05); }
.rl-trk.is-win .rl-no { color: var(--accent); }
.rl-trk.is-skip { opacity: .62; }
.rl-trk.is-late { border-style: dashed; border-color: #d9b23c; }

/* Поля проверки — в строку, как в прототипе. */
.rl-chk-fields { display: flex; gap: 12px; flex-wrap: wrap; }
.rl-chk-f { min-width: 190px; }
.rl-chk-f.is-ev { min-width: 300px; }
.rl-chk-f.is-wide { flex: 1; min-width: 240px; }
.rl-chk-f .rl-sub { margin-bottom: 3px; }
.rl-chk-f input[type=text] {
  font: 400 13px/1.4 Manrope, sans-serif; color: var(--text); background: var(--surface);
  border: 1px solid var(--field); border-radius: 9px; padding: 7px 9px; width: 100%;
}
.rl-chk-f .dd { width: 100%; }

/* ── редактор правила — по утверждённому прототипу ───────────────────────
   Значения взяты из design/rules-constructor.html (viewEdit) один в один:
   владелец сверяет экран с прототипом глазами. Классы со своим префиксом,
   чтобы не задеть карточки и формы остальной панели. Потолок ширины 1180px —
   тоже оттуда: у .wrap в панели есть min-width и нет max, и правая колонка
   на широких экранах уезжала за край. */
.rl-edit { max-width: 1180px; }
.rl-two { display: grid; grid-template-columns: minmax(0, 1fr) 380px; gap: 14px; align-items: start; }
.rl-side { position: sticky; top: 0; }
.rl-card {
  background: var(--surface); border: 1px solid var(--line-2); border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm); padding: 16px 18px; margin-bottom: 12px;
}
.rl-card-t { font-weight: 800; font-size: 15px; margin-bottom: 6px; display: flex; align-items: center; gap: 8px; }
.rl-sub { color: var(--muted); font-size: 12.5px; line-height: 1.5; }
.rl-empty { margin-bottom: 8px; }
.rl-editrow { display: flex; align-items: center; gap: 12px; padding: 9px 0; border-bottom: 1px solid var(--line); }
.rl-editrow:last-child { border-bottom: 0; }
.rl-lbl { font-weight: 700; font-size: 12.5px; min-width: 150px; color: var(--text); }
.rl-f { flex: 1; min-width: 0; }
.rl-rowsub { flex: 1; }
.rl-edit input[type=text], .rl-edit input[type=number], .rl-edit input[type=time], .rl-edit textarea {
  font: 400 13px/1.4 Manrope, sans-serif; color: var(--text); background: var(--surface);
  border: 1px solid var(--field); border-radius: 9px; padding: 7px 9px; width: 100%;
}
.rl-edit textarea { min-height: 58px; resize: vertical; }
.rl-edit .dd { width: 100%; }
.rl-edit .rl-f .dd, .rl-edit .rl-step-body > .dd { width: 100%; }
.rl-plbl { margin: 5px 0 2px; }
.rl-step {
  display: grid; grid-template-columns: 96px 1fr auto; gap: 10px; align-items: start;
  padding: 10px; border: 1px solid var(--line-2); border-radius: var(--r-md);
  margin-bottom: 8px; background: #fbfdfd;
}
.rl-step-body { min-width: 0; }
.rl-step-body > .dd { margin-bottom: 6px; }
.rl-step-body > .rl-hint { margin: 0 0 4px; }
.rl-step-acts { display: flex; flex-direction: column; gap: 5px; }
.rl-when {
  font: 800 11px/1.3 Manrope, sans-serif; color: var(--accent-dark);
  background: rgba(15, 118, 110, .08); border-radius: 8px; padding: 7px; text-align: center;
}
.rl-cond { display: grid; grid-template-columns: 1fr 120px 1fr auto; gap: 6px; align-items: center; margin-bottom: 6px; }
.rl-after { display: flex; gap: 8px; align-items: center; }
.rl-after input { width: 84px; flex: none; }
.rl-after .dd { flex: 1; max-width: 160px; }
/* Пауза шага правила: три числа с подписями единиц. Узкие поля и перенос —
   иначе «дн ч мин» на узком экране вылезают за карточку. Вес селектора не
   меньше, чем у `.rl-edit input[type=number]` выше: тот растягивает любое
   числовое поле редактора на всю ширину, и «дн» уезжало строкой ниже
   (сверено на странице проверки 2026-09-15: поле 947px). */
.rl-pause { flex-wrap: wrap; gap: 6px; }
.rl-edit .rl-pause input[type=number] { width: 64px; flex: none; }
.rl-pause span { font-size: 13px; color: var(--text-3); margin-right: 6px; }
.rl-read { font-size: 13px; color: var(--text-3); line-height: 1.5; }
.rl-flow { display: flex; flex-direction: column; gap: 0; margin-top: 8px; }
.rl-fstep { display: grid; grid-template-columns: 92px 1fr; gap: 12px; align-items: flex-start; padding: 9px 0; }
.rl-fw {
  font: 800 11px/1.3 Manrope, sans-serif; color: var(--accent-dark);
  background: rgba(15, 118, 110, .08); border-radius: 7px; padding: 6px; text-align: center;
}
.rl-fb { font-size: 13px; line-height: 1.45; padding-top: 3px; }
.rl-fd { font-size: 11.5px; color: var(--muted); margin-top: 2px; }
.rl-fline { height: 14px; border-left: 2px dotted var(--line-2); margin-left: 45px; }
.rl-kpi { display: flex; gap: 24px; margin: 10px 0 2px; font: inherit; letter-spacing: 0; }
.rl-kpi div span { display: block; font: 800 21px/1.1 Manrope, sans-serif; letter-spacing: -.02em; color: var(--text); }
.rl-kpi div small { font-size: 11.5px; color: var(--muted); }
.rl-bars { height: 44px; margin: 10px 0 4px; }
.rl-onrow { display: flex; gap: 8px; align-items: center; margin-top: 10px; }

@media (max-width: 1100px) {
  .rl-two { grid-template-columns: 1fr; }
  .rl-side { position: static; }
}

/* ── Лента «Что система сделала сама» (#/rulefeed) ──────────────────────────
 *
 * Экран строится вокруг ЧИСЛА ПОВТОРА: «47 раз» — главный довод в разговоре
 * владельца с собственной автоматикой, и набрано оно крупно намеренно. Всё
 * остальное в строке — подпись к нему.
 *
 * Своя ветка классов (.rf-), а не переиспользование .rl-: там конструктор
 * правил с картой и редактором, здесь лента случаев. Общий класс на двух
 * экранах с разным устройством — это правка одного, ломающая другой.
 */

.rf-days { display: flex; align-items: center; gap: 12px; margin: 14px 0 4px; }
.rf-days b { font: 800 17px/1.2 Manrope, sans-serif; letter-spacing: -.02em; }

.rf-note {
  margin: 12px 0 16px; padding: 11px 14px; border-radius: var(--r-md);
  background: var(--soft); border: 1px solid var(--line-2); color: var(--text-3);
  font-size: 12.5px; line-height: 1.55;
}
.rf-note b { color: var(--text); }

.rf-empty {
  padding: 26px 18px; border-radius: var(--r-lg); background: var(--surface);
  border: 1px solid var(--line-2); color: var(--muted); font-size: 13.5px; text-align: center;
}

.rf-g {
  background: var(--surface); border: 1px solid var(--line-2); border-radius: var(--r-lg);
  margin-bottom: 10px; overflow: hidden;
}
.rf-g.on { border-color: var(--accent); box-shadow: 0 0 0 2px rgba(15, 118, 110, .08); }
.rf-ghead { padding: 13px 16px; }
.rf-gwhat { font-size: 14.5px; line-height: 1.4; }
.rf-gwhat b { font-weight: 800; font-size: 16px; letter-spacing: -.01em; }
.rf-gex { font-size: 13px; color: var(--text-2); margin-top: 5px; }
.rf-why { font-size: 12px; color: var(--muted); margin-top: 4px; line-height: 1.45; }
.rf-sub { font-size: 11.5px; color: var(--muted); margin-top: 5px; line-height: 1.45; }
.rf-dim { color: var(--muted); }
.rf-warn {
  margin-top: 7px; padding: 7px 10px; border-radius: var(--r-sm);
  background: var(--warn-bg); border: 1px solid #f2dfa0; color: #6b4d06;
  font-size: 11.5px; line-height: 1.45;
}
.rf-gact { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 10px; }

/* ── случаи ─────────────────────────────────────────────────────────────── */
.rf-cases { border-top: 1px solid var(--line); padding: 4px 16px 12px; }
.rf-case { display: grid; grid-template-columns: 130px 1fr; gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--line); }
.rf-case:last-child { border-bottom: 0; }
.rf-ctime { font-size: 12px; color: var(--muted); font-weight: 700; }
.rf-cwho { font-size: 13.5px; font-weight: 700; }
.rf-facts { display: flex; gap: 5px; flex-wrap: wrap; margin: 6px 0; }
.rf-fact {
  background: var(--soft); border-radius: 7px; padding: 4px 8px;
  font-size: 11.5px; font-weight: 600; color: var(--text-3);
}
.rf-fact b { color: var(--text); font-weight: 800; }
.rf-line { font-size: 13px; color: var(--text-2); line-height: 1.45; margin-top: 3px; }
.rf-tag {
  display: inline-block; background: var(--soft); border-radius: 6px; padding: 2px 7px;
  font-size: 11px; font-weight: 700; color: var(--muted); margin-left: 5px;
}
.rf-tag.me { background: rgba(15, 118, 110, .1); color: var(--accent-dark); }

/* ── возражение ─────────────────────────────────────────────────────────── */
.rf-obj {
  border-top: 1px solid var(--line); background: rgba(15, 118, 110, .04);
  padding: 13px 16px;
}
.rf-obj h4 { font: 800 12.5px/1.3 Manrope, sans-serif; margin-bottom: 9px; }
.rf-opts { display: flex; flex-direction: column; gap: 6px; }
.rf-opt {
  text-align: left; border: 1px solid var(--line-2); background: var(--surface);
  border-radius: 10px; padding: 9px 11px; font: inherit; cursor: pointer;
}
.rf-opt:hover { border-color: var(--accent-500); }
.rf-opt.on { border-color: var(--accent); box-shadow: 0 0 0 2px rgba(15, 118, 110, .1); }
.rf-opt b { display: block; font-weight: 800; font-size: 13px; margin-bottom: 1px; color: var(--text); }
.rf-opt span { font-size: 12.5px; color: var(--text-3); line-height: 1.4; }

.rf-answer { margin-top: 11px; border-top: 1px solid rgba(15, 118, 110, .18); padding-top: 11px; }
.rf-price {
  background: var(--warn-bg); border: 1px solid #f2dfa0; border-radius: 10px;
  padding: 9px 11px; font-size: 12.5px; line-height: 1.5; color: #5c4406; margin-bottom: 9px;
}
.rf-price.ok { background: rgba(15, 118, 110, .07); border-color: rgba(15, 118, 110, .22); color: #0b4f49; }
.rf-price.bad { background: var(--danger-bg); border-color: rgba(180, 35, 24, .28); color: #7a1a12; }

.rf-picks { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 9px; }
.rf-pf {
  border: 1px dashed var(--field); background: var(--surface); border-radius: 8px;
  padding: 6px 9px; font: 600 12px/1 Manrope, sans-serif; color: var(--text-3); cursor: pointer;
}
.rf-pf:hover { border-color: var(--accent-500); }
.rf-pf.on { border-style: solid; border-color: var(--accent); background: rgba(15, 118, 110, .08); color: var(--accent-dark); }

.rf-go { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.rf-num { width: 68px; padding: 7px 9px; border: 1px solid var(--field); border-radius: 8px; font: 800 13px Manrope, sans-serif; }
.rf-chk { display: flex; gap: 6px; align-items: center; font-size: 12.5px; color: var(--text-3); }

.rf-li { padding: 7px 0; border-bottom: 1px solid var(--line); font-size: 12.5px; }
.rf-li:last-child { border-bottom: 0; }
.rf-li.me { font-weight: 700; }

.rf-blind {
  margin-top: 18px; padding: 13px 16px; border-radius: var(--r-lg);
  background: var(--surface); border: 1px dashed var(--line-2);
}
.rf-blind h4 { font: 800 12.5px/1.3 Manrope, sans-serif; margin-bottom: 6px; }

@media (max-width: 720px) {
  .rf-case { grid-template-columns: 1fr; gap: 4px; }
}

/* Факт, возражение по которому убило бы правило: оно уже стоит на «поле =
 * это значение», и обратное условие не совпадёт никогда. Помечено красным
 * до нажатия — молчаливое «сохранено» здесь хуже отказа. */
.rf-pf.bad { border-color: rgba(180, 35, 24, .45); color: var(--danger); }
.rf-pf.bad.on { background: var(--danger-bg); border-color: var(--danger); color: #7a1a12; }

/* ── Подстановки в текст правила ────────────────────────────────────────────
 *
 * Теги вида {ключ} работали с самого переноса и нигде не были описаны: человек
 * видел их только в примерах-placeholder'ах. Чипы стоят ПОД полем, а не в
 * подсказке сбоку: их нажимают, а не читают.
 *
 * Список у каждого события свой, поэтому чип — кнопка, а не текст: чужой тег,
 * набранный от руки, не заменится ничем и уедет в заголовок задачи со
 * скобками. Предупреждение о таком рисуется тут же, красным.
 */
.rl-tags { display: flex; flex-wrap: wrap; gap: 5px; align-items: center; margin: 5px 0 2px; }
.rl-tags .rl-sub { margin: 0 2px 0 0; }
.rl-tag {
  border: 1px dashed var(--field); background: var(--surface); border-radius: 7px;
  padding: 3px 7px; cursor: pointer; color: var(--text-3);
  font: 700 11.5px/1.3 "SF Mono", Consolas, "Liberation Mono", monospace;
}
.rl-tag:hover { border-style: solid; border-color: var(--accent-500); color: var(--accent-dark); }
.rl-tags-none { margin: 5px 0 2px; }
.rl-tagwarn { margin: 6px 0 2px; }

/* Тег в справочнике — не кнопка: там его читают, а не вставляют. */
.rl-tagc {
  background: var(--soft); border-radius: 5px; padding: 1px 5px;
  font: 700 11.5px/1.5 "SF Mono", Consolas, "Liberation Mono", monospace; color: var(--text-3);
  white-space: nowrap;
}

/* Карточка вопроса, скрытого условием показа на странице теста.
   Правило явное: display у .card задан своим значением и перебивает
   hidden по умолчанию — вопрос остался бы на экране. */
[data-card][hidden] { display: none !important; }

/* Рассылка по списку в «Диалогах» (2026-09-14): кнопка в конце ряда папок,
   предупреждение над полем, образец текста с переносами — как увидит человек. */
.tgc-bcast-btn { margin-left: auto; }
.tgc-bwarn { color: var(--warn); background: var(--warn-bg); border-radius: var(--r-md); padding: 8px 10px; margin: 8px 0; font-size: 13px; }
/* Отмеченные без переписки — строкой ВНУТРИ предупреждения, а не вторым
   жёлтым блоком под ним: два одинаковых блока подряд глаз читает как один,
   и вторую причину пропуска человек не видит вовсе. */
.tgc-bnochat { margin-top: 6px; font-weight: 600; }
.tgc-bsum { margin: 12px 0 6px; }
.tgc-bsample { white-space: pre-wrap; background: var(--soft); border-radius: var(--r-md); padding: 6px 10px; margin: 6px 0; font-size: 13px; }
.tgc-bto { display: flex; flex-wrap: wrap; gap: 4px 12px; max-height: 160px; overflow: auto; margin: 8px 0; padding: 6px 0; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.tgc-bskip { font-size: 13px; margin: 4px 0; color: var(--muted); }

/* Пометки «здесь что-то не так» в воронках (владелец 2026-09-15): полоса над
   колонками с переходом по ним, значок у воронки и этапа, строка у ответа и в
   «Кому эта воронка», ссылка из карточки вакансии. Жёлтое — «внимание»,
   красное — «не сработает». */
.fn-issues { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 0 0 12px;
  padding: 9px 12px; border-radius: 11px; background: var(--warn-bg); color: var(--warn);
  border: 1px solid rgba(208, 162, 21, 0.3); }
.fn-issues.err { background: var(--danger-bg); color: var(--danger); border-color: rgba(180, 35, 24, 0.25); }
.fn-issues-n { font-weight: 800; white-space: nowrap; }
.fn-issues-t { flex: 1; min-width: 220px; color: var(--text); font-size: 13px; line-height: 1.4; }
.fn-issues-fix { color: var(--text-2); }
.fn-issues .btn { margin-left: auto; }
.fn-iss { flex: none; font-size: 10.5px; font-weight: 800; padding: 2px 7px; border-radius: 999px;
  background: var(--warn-bg); color: var(--warn); white-space: nowrap; }
.fn-iss.err { background: var(--danger-bg); color: var(--danger); }
.fn-ans-iss { margin: 10px 12px 0 15px; display: grid; gap: 6px; }
.fn-who .fn-ans-iss { margin: 8px 0 0; }
.fn-ans-iss-r { padding: 7px 9px; border-radius: 9px; background: var(--warn-bg); color: var(--text);
  font-size: 12.5px; line-height: 1.4; }
.fn-ans-iss-r.err { background: var(--danger-bg); }
.fn-ans-iss-r b { color: var(--warn); }
.fn-ans-iss-r.err b { color: var(--danger); }
.fn-ans-iss-r.cur { box-shadow: 0 0 0 2px var(--warn); }
.fn-ans-iss-r.err.cur { box-shadow: 0 0 0 2px var(--danger); }
.fn-ans.flash { animation: fnflash 1.4s ease-out; }
.vac-fn-iss { display: block; margin-top: 10px; padding: 7px 10px; border-radius: 9px; font-size: 12.5px;
  font-weight: 600; text-decoration: none; background: var(--warn-bg); color: var(--warn); }
.vac-fn-iss.err { background: var(--danger-bg); color: var(--danger); }

/* ── заявки из Telegram (screen-tgradar.js) ─────────────────────────────
   Вид взят из прототипа design/tg-radar.html, согласованного владельцем
   2026-09-15: поток карточками, как «Лента канала», минус-слова тегами, виды
   потока и разделы в одну строку. Все классы — с приставкой rd-: экран живёт
   в общем файле стилей и не должен задевать соседей. */

.rd-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; }
.rd-seg { display: inline-flex; flex-wrap: wrap; gap: 2px; padding: 3px; border-radius: 999px; background: #e3eaee; }
.rd-seg.rd-tabs { background: #eaeff3; }
.rd-seg > button, .rd-seg > a {
  display: inline-flex; align-items: center; border: 0; background: transparent; border-radius: 999px;
  padding: 6px 13px; cursor: pointer; font: inherit; font-size: 13px; font-weight: 700;
  color: var(--text-3); white-space: nowrap; text-decoration: none;
}
.rd-seg > button:hover, .rd-seg > a:hover { color: var(--text); }
.rd-seg > .on { background: #fff; color: var(--text); box-shadow: var(--shadow-sm); }
.rd-sn { margin-left: 5px; font-size: 11.5px; font-weight: 600; color: var(--muted); }
.rd-dot { display: inline-block; flex: none; width: 7px; height: 7px; margin-right: 6px; border-radius: 50%; background: #b6c5cc; }
.rd-dot.ok { background: var(--accent-500); }
.rd-dot.bad { background: var(--danger); }
.rd-strip { margin-bottom: 12px; padding: 8px 12px; border-radius: var(--r-md); background: #eef2f4; color: var(--text-2); font-size: 13px; }
.rd-strip.bad { background: var(--danger-bg); color: var(--danger); }
.rd-bad { color: var(--danger); }
.rd-sub { color: var(--muted); font-size: 12.5px; }
.rd-mt { margin-top: 10px; }
.rd-link { font-size: 12.5px; font-weight: 700; white-space: nowrap; }
.rd-btns { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.rd-cols { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); gap: 14px; align-items: start; }
.rd-stack { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
.rd-tbl { overflow-x: auto; }

/* минус-слова тегами */
#rd-minus { margin-bottom: 12px; }
.rd-mbar { display: flex; align-items: center; gap: 10px; padding: 6px 10px; border-radius: var(--r-md); background: #fff; box-shadow: var(--shadow-sm); }
.rd-lbl { display: inline-flex; align-items: center; gap: 4px; color: var(--muted); font-size: 12px; font-weight: 700; white-space: nowrap; }
.rd-taginp { flex: 1; min-width: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 5px; }
.rd-taginp input {
  flex: 1; width: auto; min-width: 170px; min-height: 0; padding: 4px 2px;
  border: 0; outline: 0; box-shadow: none; background: transparent; font-size: 13px;
}
.rd-taginp.sm { margin-top: 5px; }
.rd-taginp.sm input { min-width: 120px; font-size: 12px; box-shadow: inset 0 -1px 0 var(--field); }
.rd-mtag {
  display: inline-flex; align-items: center; gap: 3px; padding: 2px 3px 2px 9px; border-radius: 999px;
  background: #fdecea; color: #9a3412; font-size: 12px; font-weight: 700; white-space: nowrap;
}
.rd-wtag {
  display: inline-flex; align-items: center; gap: 2px; padding: 1px 2px 1px 8px; border-radius: 999px;
  background: #eaf0f3; color: var(--text-2); font-size: 12px; font-weight: 600; white-space: nowrap;
}
.rd-x { border: 0; padding: 0 6px; border-radius: 999px; background: transparent; color: inherit; font: inherit; font-weight: 800; line-height: 1.4; cursor: pointer; }
.rd-x:hover { background: rgba(154, 52, 18, 0.12); color: var(--danger); }
.rd-pn { margin-left: 3px; font-weight: 600; opacity: 0.7; }
.rd-mprev { padding: 6px 12px 0; font-size: 12.5px; color: var(--text-2); }
.rd-mprev:empty { display: none; }
.rd-stages { margin-bottom: 8px; }
.rd-contacts { margin-bottom: 4px; align-items: center; }
.rd-pcap { margin-right: 2px; }
.rd-keys { margin: 2px 0 10px; }
.rd-keys kbd {
  padding: 0 5px; border-radius: 5px; background: #fff; color: var(--text-2);
  font: 700 11px ui-monospace, Consolas, monospace; box-shadow: inset 0 -1px 0 #c9d6dc, inset 0 0 0 1px #dbe5ea;
}

/* поток карточками: левая полоса — этап, курсор клавиатуры — обводка */
.rd-card { border-left: 4px solid #d5dfe3; cursor: pointer; transition: box-shadow 0.12s; }
.rd-card:hover { box-shadow: var(--shadow-md); }
.rd-card.rd-v-open.rd-s-yes { border-left-color: var(--accent-500); }
.rd-card.rd-v-open.rd-s-maybe { border-left-color: #e0a100; }
.rd-card.rd-v-lead { border-left-color: var(--accent-dark); }
.rd-card.rd-v-hidden .tg-text { color: var(--text-3); }
.rd-card.cur { box-shadow: 0 0 0 2px #b9dfd9, var(--shadow-md); }
.rd-card.rd-sel { box-shadow: 0 0 0 2px var(--accent-500), var(--shadow-md); }
.rd-card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; }
/* Тег состояния занимает не больше половины шапки и обрезается многоточием:
   название правила в нём бывает длинным, а заголовок карточки — главное,
   что в ней читают. Полное название остаётся в подсказке и в причине внизу. */
.rd-card-head > .tag { flex: 0 1 auto; min-width: 0; max-width: 50%;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rd-card-head .rd-sub { font-size: 12px; line-height: 1.45; }
/* Источник — именем, а не синей ссылкой браузера: серая строка с синим
   подчёркиванием делала всю карточку блёклой (владелец 2026-09-15: «карточки
   серо очень выглядят»). */
.rd-card-src { min-width: 0; }
.rd-src-name { display: block; font-size: 13.5px; font-weight: 700; line-height: 1.35; color: var(--text); text-decoration: none; overflow-wrap: break-word; }
a.rd-src-name:hover { color: var(--accent-dark); text-decoration: underline; }
.rd-card .tg-text { color: var(--text); }
.rd-card .tg-more { margin-top: -6px; }
.rd-grp { border: 0; padding: 0; background: none; font: inherit; color: var(--accent-dark); cursor: pointer; }
.rd-grp:hover { text-decoration: underline; }
.rd-same { margin: 4px 0 8px; padding: 8px 10px; border-left: 3px solid var(--accent-soft); background: var(--bg, #f7f7f5); border-radius: 6px; display: grid; gap: 10px; }
.rd-same-it { display: grid; gap: 2px; }
.rd-same-text { font-size: 13px; }
.rd-same-it .tg-more { margin-top: 0; justify-self: start; }
.rd-same-side { margin: 0; }
.rd-changes { margin: 0; padding: 0; list-style: none; display: grid; gap: 6px; font-size: 13px; }
.rd-ch-at { display: inline-block; min-width: 88px; color: var(--text-3); font-variant-numeric: tabular-nums; }
.rd-card.rd-v-open.rd-s-yes { background: linear-gradient(180deg, #f2faf8 0, #fff 64px); }
.rd-card.rd-v-open.rd-s-maybe { background: linear-gradient(180deg, #fdf8ea 0, #fff 64px); }
.rd-src-veto { margin-top: 4px; }
.rd-tbl th.rd-gap, .rd-tbl td.rd-gap { padding-left: 18px; }
.rd-foot { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.rd-call { border: 0; cursor: pointer; font: inherit; font-size: 12px; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--accent-dark); background: var(--accent-soft); }
.rd-call:hover { color: #fff; background: var(--accent); }
.rd-call.known { color: var(--warn); background: var(--warn-bg); }
.rd-call svg { width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-width: 2; }
/* Телеграм-контакт и автор поста — теги-ссылки наружу: «так же как номер,
   чтобы выводился сразу и при клике открывался в новом окне» (владелец,
   2026-09-21). Вид как у набора, но ссылка: номер набирают у нас, а тут
   человек уходит в Телеграм писать своим аккаунтом. */
/* Почта — такой же тег, как @имя: контакт, по которому пишут (владелец,
   2026-09-22). Цвет тот же — это контакт, а не пометка. С 2026-09-23 это
   кнопка: открывает наше окно письма, а не почтовую программу. */
button.rd-mail { border: 0; cursor: pointer; font: inherit; font-size: 12px; font-weight: 700; }
.rd-tg, .rd-author, .rd-mail { display: inline-flex; align-items: center; gap: 4px; text-decoration: none;
  font-size: 12px; font-weight: 700; color: var(--accent-dark); background: var(--accent-soft); }
.rd-tg:hover, .rd-author:hover, .rd-mail:hover { color: #fff; background: var(--accent); }
.rd-tg .rd-ico, .rd-mail .rd-ico { width: 13px; height: 13px; }
.btn-call.rd-call-btn { width: 32px; height: 32px; min-width: 0; padding: 0; border-radius: 999px; }
.rd-more { display: flex; justify-content: center; padding: 14px 0 4px; }
.rd-t-fresh { color: #1f5fa8; background: #e3f1ff; }
.rd-t-own { color: #5b3fb0; background: #ede7fb; }

/* слова текста на выбор в минус-слова */
.rd-w { border-radius: 4px; cursor: pointer; }
.rd-w:hover { background: #fde2dd; }
.rd-w.m { box-shadow: inset 0 -2px 0 #f2c94c; }
.rd-w.on { background: #9a3412; color: #fff; box-shadow: none; }
.tg-text.rd-picking { display: block; -webkit-line-clamp: unset; overflow: visible; line-height: 1.7; }
.rd-pickbar { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; padding: 8px 10px; border-radius: var(--r-md); background: #fdf3f1; cursor: default; }
.rd-pickbar .pill.on { background: #9a3412; }
.rd-pickbar .rd-mprev { padding: 0; }

/* заявка подробно — панель справа */
.rd-side-wrap { position: fixed; inset: 0; z-index: 35; display: flex; justify-content: flex-end; background: rgba(14, 36, 44, 0.28); }
.rd-side {
  width: min(960px, 100%); height: 100%; display: flex; flex-direction: column;
  background: var(--bg); box-shadow: -28px 0 64px -30px rgba(14, 36, 44, 0.55);
}
.rd-side-head { flex: none; display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; padding: 14px 20px; background: #fff; border-bottom: 1px solid var(--line-2); }
.rd-side-head h3 { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 2px 0 0; font-size: 19px; }
.rd-side-head .x {
  flex: none; width: 30px; height: 30px; border: 0; border-radius: 9px; cursor: pointer;
  font-size: 20px; line-height: 1; color: var(--muted); background: var(--soft);
}
.rd-side-head .x:hover { background: #e6edf0; color: var(--text); }
.rd-side-body { flex: 1; min-height: 0; overflow-y: auto; padding: 16px 20px 32px; }
.rd-post {
  max-height: 50vh; overflow: auto; padding: 9px 12px; border-radius: var(--r-md); background: #f6f9fa;
  white-space: pre-wrap; overflow-wrap: anywhere; font-size: 14px; line-height: 1.6;
}
.rd-callrow { display: flex; align-items: center; gap: 10px; padding: 6px 0; }
.rd-callrow + .rd-callrow { border-top: 1px solid var(--line); }
.rd-path { display: flex; flex-direction: column; margin: 0; padding: 0; list-style: none; font-size: 12.5px; }
.rd-path li { display: grid; grid-template-columns: 22px minmax(0, 1fr); gap: 8px; padding: 6px 0; border-top: 1px solid var(--line-2); }
.rd-path li:first-child { border-top: 0; }
.rd-path .st {
  display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; border-radius: 999px;
  font-size: 11px; font-weight: 800; color: var(--accent-dark); background: var(--accent-soft);
}
.rd-path .pt { font-weight: 700; color: var(--text-2); }
.rd-path li.stop .st { color: var(--danger); background: var(--danger-bg); }
.rd-path li.stop .pt { color: var(--danger); }
.rd-path li.wait .st { color: var(--warn); background: var(--warn-bg); }
.rd-path li.skip, .rd-path li.skip .pt { color: var(--muted-2); }
.rd-path li.skip .st { color: var(--muted-2); background: #eef2f4; }
.rd-path .rd-why { margin-top: 4px; }
.rd-why { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.rd-why td { padding: 5px 4px; border-top: 1px solid var(--line-2); vertical-align: top; }
.rd-why td.c { font-weight: 800; color: var(--text-2); white-space: nowrap; }
.rd-why td.w { text-align: right; font-weight: 800; white-space: nowrap; }
.rd-why tr.skip td { color: var(--muted-2); }
.rd-why tr.sum td { font-weight: 800; border-top: 2px solid var(--line-2); }

/* окно звонка и лида — по образцу колл-центра */
.rd-callwin { background: var(--bg); }
.rd-call-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr); gap: 14px; align-items: start; }
.rd-hero { padding: 16px 18px; border-radius: var(--r-lg); color: #fff; background: linear-gradient(122deg, #123742 0%, #0f5b58 55%, #0f766e 100%); box-shadow: var(--shadow-md); }
.rd-hero .cap { display: flex; align-items: center; gap: 7px; font-size: 10px; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; color: #a7d8d2; }
.rd-hero h3 { margin: 6px 0 2px; font-size: 26px; font-weight: 800; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; color: #fff; }
.rd-dial { font-size: 13px; color: #d5ece9; }
.rd-live { flex: none; width: 8px; height: 8px; border-radius: 999px; background: #5eead4; animation: rdpulse 1.4s infinite; }
@keyframes rdpulse {
  0% { box-shadow: 0 0 0 0 rgba(94, 234, 212, 0.7); }
  70% { box-shadow: 0 0 0 8px rgba(94, 234, 212, 0); }
  100% { box-shadow: 0 0 0 0 rgba(94, 234, 212, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .rd-live { animation: none; }
}
.rd-outhint { margin-top: 8px; padding: 7px 10px; border-radius: var(--r-md); font-size: 12.5px; color: var(--accent-dark); background: var(--accent-soft); }
.rd-outhint.no { color: var(--text-3); background: #eef2f4; }
.rd-form { display: flex; flex-direction: column; gap: 10px; margin-top: 10px; }
.rd-two { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.rd-confirm-num { font-size: 22px; font-weight: 800; font-variant-numeric: tabular-nums; }
.rd-err { padding: 7px 10px; border-radius: var(--r-md); font-size: 12.5px; color: var(--danger); background: var(--danger-bg); }

/* источники */
.rd-kpis { grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); }
.rd-dec { display: inline-flex; gap: 2px; padding: 2px; border-radius: 999px; background: #e3eaee; white-space: nowrap; }
.rd-dec button { border: 0; padding: 4px 9px; border-radius: 999px; background: transparent; cursor: pointer; font: inherit; font-size: 12px; font-weight: 700; color: var(--text-3); }
.rd-dec button.sug { box-shadow: inset 0 0 0 1px var(--muted); }
.rd-dec button.on.take { color: #fff; background: var(--accent); box-shadow: none; }
.rd-dec button.on.watch { color: var(--text); background: #fff; box-shadow: var(--shadow-sm); }
.rd-dec button.on.drop { color: var(--text); background: #d9dee2; box-shadow: none; }
.rd-grade { padding: 2px 8px; border-radius: 999px; font-size: 12px; font-weight: 700; white-space: nowrap; }
.rd-grade.g-good { color: #1d7a4a; background: #dff3e8; }
.rd-grade.g-mid { color: #8a6200; background: #fff3d6; }
.rd-grade.g-bad { color: #9b3a2f; background: #f1e4e2; }
.rd-grade.g-few { color: var(--text-3); background: #e9eef1; }
.rd-take { width: 100%; min-height: 0; resize: vertical; font-size: 12.5px; line-height: 1.5; }

/* воронка */
.rd-fns { display: flex; flex-direction: column; gap: 2px; }
.rd-fn {
  display: grid; grid-template-columns: minmax(150px, 250px) minmax(0, 1fr) 70px 48px; gap: 10px; align-items: center;
  padding: 5px 6px; border-radius: 10px; font-size: 13px;
}
.rd-fn.go { cursor: pointer; }
.rd-fn.go:hover { background: var(--soft); }
.rd-fn.sub { font-size: 12.5px; color: var(--text-3); }
.rd-fn.sub .lbl { padding-left: 16px; }
.rd-fn.total { font-weight: 800; }
.rd-fn .lbl { min-width: 0; }
.rd-fn .bar { height: 14px; border-radius: 6px; background: #e8eef1; overflow: hidden; }
.rd-fn .bar i { display: block; height: 100%; border-radius: 6px; background: linear-gradient(90deg, var(--accent), var(--accent-500)); }
.rd-fn.cut .bar i { background: #c9d5db; }
.rd-fn.maybe .bar i { background: #e0a100; }
.rd-fn.bad .bar i { background: var(--danger); }
.rd-fn .num { text-align: right; font-weight: 800; font-variant-numeric: tabular-nums; }
.rd-fn .pc { text-align: right; font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }

/* фильтр отбора и сбор */
.rd-in { width: 100%; min-width: 0; min-height: 0; padding: 6px 9px; font-size: 13px; }
select.rd-in { padding-right: 30px; }
.rd-in-id { width: 74px; font-weight: 800; }
.rd-in-w { width: 76px; text-align: right; }
.rd-in-title { font-weight: 600; }
textarea.rd-in.rd-q { min-height: 52px; resize: vertical; font-size: 12.5px; line-height: 1.45; }
div.rd-q { overflow-wrap: anywhere; }
.rd-tbl th { white-space: nowrap; }
.rd-tbl th.right, .rd-tbl td.right { padding-left: 14px; }
.rd-off td { opacity: 0.55; }
.rd-rules td, .rd-phr td { vertical-align: top; }
.rd-set-row { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; padding: 8px 0; border-top: 1px solid var(--line); font-size: 13px; }
.card-t + .rd-set-row { border-top: 0; }
.rd-set-row label { display: inline-flex; align-items: center; gap: 8px; }
.rd-set-row .rd-in { width: auto; }
.rd-set-row .rd-in-w { width: 76px; }
.rd-savebar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--line-2); }
.rd-check { display: flex; flex-direction: column; gap: 4px; margin-top: 12px; padding: 10px 12px; border-radius: var(--r-md); font-size: 13px; color: var(--accent-dark); background: var(--accent-soft); }
.rd-check.bad { color: var(--danger); background: var(--danger-bg); }
.rd-meter + .rd-meter { margin-top: 10px; }
.rd-meter .top { display: flex; justify-content: space-between; gap: 10px; font-size: 13px; }
.rd-meter .top b { font-variant-numeric: tabular-nums; }
.rd-meter .bar { height: 8px; margin: 6px 0 4px; border-radius: 999px; background: #e3eaee; overflow: hidden; }
.rd-meter .bar i { display: block; height: 100%; background: linear-gradient(90deg, var(--accent), var(--accent-500)); }
.rd-meter .bar.warn i { background: #e0a100; }
.rd-meter .bar.bad i { background: var(--danger); }
.rd-state { display: flex; align-items: center; gap: 4px; font-size: 14px; }
.rd-screen .switch:disabled { opacity: 0.55; cursor: default; }
/* Разделы ставят карточки прямо в экран, а не в стопку: без отступа соседние
   карточки слипались углами, а подпись в заголовке карточки наследовала его
   заглавные буквы (владелец 2026-09-15, скриншот «Отбора»). */
.rd-screen > .card, .rd-screen > .rd-cols { margin-bottom: 14px; }
.card-t .rd-sub { margin-left: 6px; font-size: 12px; font-weight: 600; letter-spacing: 0; text-transform: none; }
/* Сбор: левая колонка — состояние, токен и тариф, правая — фразы тегами. */
.rd-cols.rd-cols-set { grid-template-columns: minmax(300px, 1fr) minmax(0, 2.2fr); }
.rd-set-gap { margin-left: 14px; }
.rd-phrs { display: flex; flex-direction: column; gap: 10px; margin-top: 6px; }
.rd-phr { padding: 10px 12px 12px; border-radius: var(--r-md); background: #f6f9fa; box-shadow: inset 0 0 0 1px var(--line-2); }
.rd-phr.off .rd-qrow, .rd-phr.off textarea { opacity: 0.55; }
.rd-phr textarea.rd-q { margin-top: 8px; background: #fff; }
.rd-phr-head { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.rd-phr-head .rd-in-id { width: 64px; background: #fff; }
.rd-seg.rd-seg-sm { padding: 2px; }
.rd-seg.rd-seg-sm > button { padding: 4px 10px; font-size: 12px; }
.rd-seg > button:disabled { cursor: default; }
.rd-qlen { font-size: 12px; font-weight: 700; color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.rd-qlen.warn { color: var(--warn); }
.rd-qlen.bad { color: var(--danger); }
.rd-qrow { display: grid; grid-template-columns: 96px minmax(0, 1fr); gap: 8px; align-items: start; margin-top: 10px; }
.rd-qrow .rd-lbl { padding-top: 3px; }
.rd-qtag {
  display: inline-flex; align-items: center; gap: 2px; padding: 2px 3px 2px 9px; border-radius: 999px;
  font-size: 12px; font-weight: 700; white-space: nowrap;
}
.rd-qtag.ro { padding-right: 9px; }
.rd-qform { opacity: 0.75; font-weight: 400; }
.rd-qtag.inc { background: var(--accent-soft); color: var(--accent-dark); }
.rd-qtag.exc { background: #fdecea; color: #9a3412; }
.rd-taginp input.rd-qin {
  flex: 1; width: auto; min-width: 150px; min-height: 0; height: auto; padding: 3px 4px; border: 0; border-radius: 0;
  outline: 0; background: transparent; box-shadow: inset 0 -1px 0 var(--field); font-size: 12.5px;
}
.rd-qmore { border: 0; padding: 2px 6px; border-radius: 999px; background: transparent; color: var(--accent-dark); font: inherit; font-size: 12px; font-weight: 700; cursor: pointer; white-space: nowrap; }
.rd-qmore:hover { background: var(--accent-soft); }
/* Отбор: «вето» в узкой колонке обрезалось, поле слова рисовалось второй рамкой. */
.rd-rules select.rd-in { min-width: 96px; }
.rd-taginp.sm input { height: auto; border-radius: 0; background: transparent; }

@media (max-width: 860px) {
  .rd-cols, .rd-call-grid, .rd-two { grid-template-columns: minmax(0, 1fr); }
  .rd-mbar { flex-wrap: wrap; }
  .rd-fn { grid-template-columns: minmax(0, 1fr) auto auto; }
  .rd-fn .bar { grid-column: 1 / -1; order: 3; }
}

/* Карточка «Звонки и номера» на дашборде (web/dash-calls.js), 2026-09-16.
   Сетки складываются в одну колонку на узком экране: дашборд открывают и с
   телефона. */
.ca.ca-loading { opacity: .75; }
.ca-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: 12px; }
.ca-seg { display: inline-flex; padding: 3px; border-radius: 999px; background: var(--soft); }
.ca-seg button { border: 0; background: transparent; padding: 5px 12px; border-radius: 999px; font: inherit; font-size: 12px; font-weight: 600; color: var(--text-3); cursor: pointer; }
.ca-seg button.on { background: var(--surface); color: var(--accent-dark); box-shadow: var(--shadow-sm); }
.ca-empty { padding: 18px 0 6px; color: var(--muted); font-size: 13px; }

.ca-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 10px; margin-bottom: 12px; }
.ca-kpi { border-radius: var(--r-md); background: var(--soft); padding: 10px 14px; min-width: 0; }
.ca-kpi.main { background: linear-gradient(135deg, var(--accent), var(--accent-500)); color: #fff; }
.ca-kpi .cap { font-size: 11px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
.ca-kpi.main .cap, .ca-kpi.main .sub { color: rgba(255, 255, 255, .85); }
.ca-kpi .val { margin-top: 2px; font-size: 26px; font-weight: 800; letter-spacing: -0.03em; line-height: 1.1; }
.ca-kpi .val small { font-size: 14px; font-weight: 600; }
.ca-kpi .sub { font-size: 12px; color: var(--muted); margin-top: 2px; }
.ca-delta { display: inline-block; margin-top: 4px; font-size: 12px; font-weight: 700; color: var(--muted); }
.ca-delta.up { color: var(--accent-dark); }
.ca-delta.down { color: var(--danger); }
.ca-kpi.main .ca-delta { color: #fff; }
.ca-delta-cap { font-weight: 400; opacity: .8; }

.ca-insights { display: grid; grid-template-columns: repeat(auto-fit, minmax(380px, 1fr)); gap: 8px; margin-bottom: 12px; }
.ca-insight { font-size: 12.5px; line-height: 1.45; padding: 7px 12px 7px 12px; border-radius: var(--r-sm); border-left: 3px solid var(--accent); background: var(--accent-soft); color: var(--text-2); }
.ca-insight.bad { border-left-color: var(--danger); background: var(--danger-bg); }

.ca-three { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin-bottom: 12px; align-items: stretch; }
.ca-panel { border: 1px solid var(--line-2); border-radius: var(--r-md); padding: 12px 14px; min-width: 0; margin-bottom: 12px; }
.ca-three .ca-panel { margin-bottom: 0; }
.ca-days { margin-bottom: 12px; }
.ca-days-h { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; flex-wrap: wrap; font-size: 12px; margin-bottom: 4px; }
.ca-panel-t { font-size: 13px; font-weight: 700; margin-bottom: 10px; }

.ca-chart-wrap { position: relative; }
.ca-chart { width: 100%; height: 64px; display: block; }
.ca-xs { display: flex; margin-top: 3px; }
.ca-xs span { flex: 1 1 0; min-width: 0; text-align: center; font-size: 11px; color: var(--muted); white-space: nowrap; }
.ca-xs span.we { color: var(--danger); }
.ca-hit { fill: transparent; }
.ca-chart g:hover .ca-hit { fill: var(--soft); }
.ca-b-calls { fill: #dfe8ec; background: #dfe8ec; }
.ca-b-ans { fill: #9fd8d1; background: #9fd8d1; }
.ca-b-talk { fill: var(--accent); background: var(--accent); }
.ca-grid-l { stroke: var(--line); stroke-dasharray: 3 4; }
.ca-axis { stroke: var(--line-2); }
.ca-y { display: none; }
.ca-legend { display: inline-flex; flex-wrap: wrap; gap: 12px; font-size: 11px; color: var(--muted); }
.ca-legend i { display: inline-block; width: 10px; height: 10px; border-radius: 3px; margin-right: 5px; vertical-align: -1px; }

.ca-src + .ca-src { margin-top: 9px; padding-top: 9px; border-top: 1px solid var(--line); }
.ca-src-m { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.ca-src-m .ca-row { grid-template-columns: 36px minmax(0, 1fr) 34px; margin-top: 0; }
.ca-src-h { display: flex; justify-content: space-between; gap: 8px; flex-wrap: wrap; font-size: 13px; margin-bottom: 4px; }
.ca-row { display: grid; grid-template-columns: 52px minmax(0, 1fr) 40px; align-items: center; gap: 8px; font-size: 12px; color: var(--muted); margin-top: 4px; }
.ca-row b { text-align: right; color: var(--text); }
.ca-row.wide { grid-template-columns: minmax(90px, 1.2fr) minmax(0, 1fr) 40px 52px; }
.ca-row.wide em { font-style: normal; text-align: right; }
.ca-meter { height: 8px; border-radius: 999px; background: #e8eef1; overflow: hidden; }
.ca-meter i { display: block; height: 100%; border-radius: 999px; background: linear-gradient(90deg, var(--accent), var(--accent-500)); }
.ca-meter.soft i { background: #9fd8d1; }
.ca-meter.full i { background: var(--danger); }

.ca-nums { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 12px; }
.ca-num { border-radius: var(--r-md); background: var(--soft); padding: 12px 16px; min-width: 0; border-top: 3px solid transparent; }
.ca-num.good { border-top-color: var(--accent-500); }
.ca-num.bad { border-top-color: var(--danger); }
.ca-num-h { display: flex; align-items: center; justify-content: space-between; gap: 6px; }
.ca-num-tail { font-size: 16px; font-weight: 800; letter-spacing: .02em; }
.ca-tag { font-size: 11px; font-weight: 600; padding: 2px 8px; border-radius: 999px; background: #e3eaee; color: var(--muted); }
.ca-tag.on { background: var(--accent-soft); color: var(--accent-dark); }
.ca-num-val { font-size: 26px; font-weight: 800; letter-spacing: -0.03em; margin-top: 6px; }
.ca-num.bad .ca-num-val { color: var(--danger); }
.ca-num.good .ca-num-val { color: var(--accent-dark); }
.ca-num-val span { font-size: 12px; font-weight: 500; color: var(--muted); margin-left: 6px; letter-spacing: 0; }
.ca-num-split { font-size: 11px; color: var(--muted); margin-top: 4px; }
.ca-spark { width: 100%; height: 30px; display: block; margin-top: 6px; }
.ca-spark-line { fill: none; stroke: var(--accent); stroke-width: 1.6; vector-effect: non-scaling-stroke; }
.ca-spark-fill { fill: rgba(15, 118, 110, .1); stroke: none; }
.ca-cap { grid-template-columns: 52px minmax(0, 1fr) 58px; }

.ca-hours { display: flex; gap: 4px; overflow-x: auto; padding-bottom: 2px; }
.ca-hour { flex: 1 0 22px; text-align: center; }
.ca-hour-bar { height: 56px; display: flex; align-items: flex-end; background: #f3f7f9; border-radius: 6px; overflow: hidden; }
.ca-hour-bar i { display: block; width: 100%; border-radius: 6px 6px 0 0; }
.ca-hour-p { font-size: 10px; font-weight: 700; color: var(--text-3); margin-top: 4px; min-height: 13px; }
.ca-hour-k { font-size: 10px; color: var(--muted); }

.ca-foot { font-size: 12px; color: var(--muted); line-height: 1.5; }

@media (max-width: 1200px) and (min-width: 861px) {
  .ca-three { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 860px) {
  .ca-three { grid-template-columns: minmax(0, 1fr); }
  .ca-insights { grid-template-columns: minmax(0, 1fr); }
  .ca-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ca-kpi .val { font-size: 23px; }
  .ca-xs span.alt { visibility: hidden; }
}

/* Номера для обзвона в «Настройках → Телефония» — плашками, 2026-09-16. */
.tel-rot { margin-left: 6px; padding: 2px 8px; border-radius: 999px; font-size: 11px; font-weight: 600; background: #e3eaee; color: var(--muted); }
.tel-rot.on { background: var(--accent-soft); color: var(--accent-dark); }
.tel-chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 4px; }
.tel-chip { position: relative; display: inline-flex; align-items: center; gap: 9px; padding: 7px 14px 7px 9px; border: 1.5px solid var(--field); border-radius: 999px; background: #fff; cursor: pointer; transition: border-color .15s, background .15s; max-width: 100%; }
.tel-chip:hover { border-color: var(--accent); }
.tel-chip input { position: absolute; opacity: 0; width: 1px; height: 1px; pointer-events: none; }
.tel-chip:focus-within { box-shadow: 0 0 0 3px var(--accent-soft); }
.tel-chip-mark { flex: none; width: 18px; height: 18px; border-radius: 50%; border: 1.5px solid var(--muted-2); background: #fff; position: relative; }
.tel-chip.on { border-color: var(--accent); background: var(--accent-soft); }
.tel-chip.on .tel-chip-mark { border-color: var(--accent); background: var(--accent); }
.tel-chip.on .tel-chip-mark::after { content: ""; position: absolute; left: 5px; top: 2px; width: 4px; height: 8px; border: solid #fff; border-width: 0 2px 2px 0; transform: rotate(45deg); }
.tel-chip-body { display: flex; flex-direction: column; line-height: 1.2; min-width: 0; }
.tel-chip-num { font-size: 13px; font-weight: 700; color: var(--text); white-space: nowrap; }
.tel-chip-sub { font-size: 11px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tel-chip.on .tel-chip-sub { color: var(--accent-dark); }
.tel-cap-row { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin-top: 12px; font-size: 13px; color: var(--text-3); }
.tel-cap-row input { width: 72px; text-align: center; }
.tel-cap-link { margin-left: auto; font-size: 12px; }

/* ── резюме с hh.ru: вторая панель слева от карточки (2026-09-22) ────────
   Соседний элемент, а не вложенный в карточку: вложенное рисовалось бы внутри
   её прокрутки и уезжало бы вверх вместе с ней. Ширины заданы через flex,
   поэтому на широком мониторе помещаются обе, а на узком первой отдаёт место
   карточка. */
.hhp {
  flex: 0 0 min(560px, 44vw); min-width: 0; height: 100%;
  display: flex; flex-direction: column;
  background: #fff; border-right: 1px solid var(--line-2);
  box-shadow: -28px 0 64px -34px rgba(14, 36, 44, 0.5);
  animation: hhp-in 0.18s ease-out both;
}
@keyframes hhp-in {
  from { opacity: 0; transform: translateX(28px); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) { .hhp { animation: none; } }

.hhp-head {
  flex: none; display: flex; align-items: flex-start; gap: 10px;
  padding: 16px 18px; border-bottom: 1px solid var(--line);
}
.hhp-head .grow { min-width: 0; }
.hhp-head h3 { margin: 2px 0 0; font-size: 18px; letter-spacing: -0.02em; }
/* Крестик — той же плашкой, что в шапке карточки. Голая кнопка браузера рядом
   с оформленной карточкой читается как чужая ✓факт, владелец, 2026-09-22: у
   панели резюме стиля не было вовсе, потому что правило написано для
   `.panel-head .x`, а шапка здесь своя. */
.hhp-head .x {
  flex: none; width: 30px; height: 30px; border: 0; border-radius: 9px;
  font-size: 20px; line-height: 1; color: var(--muted);
  background: var(--soft); cursor: pointer;
}
.hhp-head .x:hover { background: #e6edf0; color: var(--text); }
.hhp-body { flex: 1; min-height: 0; overflow-y: auto; padding: 16px 18px 40px; background: var(--soft); }
.hhp-foot {
  flex: none; display: flex; gap: 8px; align-items: center; flex-wrap: wrap;
  padding: 10px 18px; background: #fff; border-top: 1px solid var(--line);
}
/* Подпись подвала («прикрепил кто и когда», цена просмотра) прижата вправо,
   пока помещается, и ПЕРЕНОСИТСЯ целой строкой, когда нет. Без нижней границы
   ширины flex сжимал её до колонки в одно слово: на панели 44vw с тремя
   кнопками подпись вставала в четыре строки и раздувала подвал вдвое. */
.hhp-sign { flex: 1 1 200px; text-align: right; }

/* Марка источника. Не логотип hh: чужой знак в своей системе обещает больше,
   чем система делает, — данные здесь наши, снятые по API, а не страница hh. */
.hhp-src {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 8px; border-radius: 999px;
  font-size: 11px; font-weight: 700; letter-spacing: 0.02em;
  color: var(--accent-dark); background: var(--accent-soft);
}
.hhp-when { font-size: 12px; color: var(--muted); }

/* Опыт работы — лентой: слева даты и срок, справа место и обязанности. Срок
   («2 г. 4 мес.») стоит отдельной строкой: по двум датам его считают в уме, а
   кандидатов сравнивают именно по нему. */
.hhp-job { display: grid; grid-template-columns: 116px 1fr; gap: 12px; padding: 12px 0; border-top: 1px solid var(--line-2); }
.hhp-job:first-of-type { border-top: 0; }
.hhp-when-col { font-size: 12px; color: var(--muted); }
.hhp-when-col b { display: block; color: var(--text-3); font-size: 12px; font-weight: 700; margin-top: 2px; }
.hhp-job-pos { font-size: 14px; font-weight: 700; }
.hhp-job-co { font-size: 13px; color: var(--text-2); margin-top: 1px; }
.hhp-job-txt { font-size: 13px; color: var(--text-3); margin-top: 6px; white-space: pre-line; }

.hhp-kv { display: grid; grid-template-columns: 132px 1fr; gap: 6px 12px; font-size: 13px; }
.hhp-kv dt { color: var(--muted); }
.hhp-kv dd { color: var(--text-2); font-weight: 600; }

/* Контакты закрыты. Размыта не только цифра, но и подпись: иначе маска
   читается как «номера нет». */
.hhp-locked { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.hhp-masked { font-size: 15px; font-weight: 700; letter-spacing: 0.04em; color: var(--muted-2); }
.hhp-phone { font-size: 15px; font-weight: 700; }
.hhp-cost { font-size: 12px; color: var(--warn); background: var(--warn-bg); padding: 2px 8px; border-radius: 999px; font-weight: 700; }
/* Бесплатный просмотр — спокойным цветом: это не предупреждение, а ответ на
   вопрос «сколько это стоит». Жёлтым он читался бы как «осторожно». */
.hhp-free { font-size: 12px; color: var(--accent-dark); background: var(--accent-soft); padding: 2px 8px; border-radius: 999px; font-weight: 700; }
/* Кнопка и счётчик остатка — одной парой: панель узкая (44vw), и порознь
   flex разносил их по разным строкам, а счётчик, оторванный от кнопки,
   читается как подпись к чему-то другому. Переносятся теперь вместе. */
.hhp-act { display: inline-flex; align-items: center; gap: 8px; flex-wrap: nowrap; }

/* Остаток без утверждения о цене — серым. Ни зелёным («бесплатно»), ни жёлтым
   («списали»): мы как раз НЕ знаем, списалось ли, и цвет не должен говорить
   за нас. */
.hhp-left { font-size: 12px; color: var(--muted); background: var(--soft); padding: 2px 8px; border-radius: 999px; font-weight: 700; }

/* Скелет загрузки: полосы там же, где потом встанет текст. Крутящийся кружок
   ничего не обещает, а полосы показывают, что приедет и сколько его. */
.hhp-sk { height: 12px; border-radius: 6px; background: linear-gradient(90deg, var(--line-2), #f3f8fa, var(--line-2)); background-size: 200% 100%; animation: hhp-sh 1.1s linear infinite; }
@keyframes hhp-sh { from { background-position: 200% 0; } to { background-position: -200% 0; } }

/* Блок «Резюме на hh.ru» в карточке: состояние прямо в заголовке, действия
   значками справа. «Нашли или нет» — первое, что спрашивают у блока, и
   вычитывать ответ из абзаца текста не надо. */
.hh-state {
  margin-left: 8px; padding: 1px 7px; border-radius: 999px;
  font-size: 10px; font-weight: 700; letter-spacing: 0.02em; text-transform: none;
}
.hh-state.ok { color: var(--accent-dark); background: var(--accent-soft); }
.hh-state.many { color: var(--warn); background: var(--warn-bg); }
.hh-state.off, .hh-state.wait { color: var(--muted-2); background: var(--soft); }

.card-t.row { display: flex; align-items: center; gap: 6px; }
/* Отступ между значками — 8px: кнопки стоят в углу карточки, и в тесном ряду
   по ним промахиваются ✓факт, владелец, 2026-09-21. Сама плашка 30×30 — цель
   шире значка, попасть можно и мимо контура. */
.hh-acts { display: flex; align-items: center; gap: 8px; margin-left: auto; }
/* display:inline-flex обязателен И кнопке, и ссылке: у кнопки содержимое
   выравнивается по базовой линии текста, и значок сидит выше середины плашки —
   подсветка при наведении выглядит съехавшей ✓факт, владелец, 2026-09-21. */
.hh-acts .icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; min-width: 30px; padding: 0;
  border-radius: var(--r-sm); background: none;
}
.hh-acts .icon-btn:hover { background: #d9f2ef; }
/* Один размер значка на весь ряд: контуры нарисованы в разных viewBox, и
   разница в пиксель между соседями видна как «прыгающие» кнопки. */
.hh-acts .icon-btn svg { display: block; width: 16px; height: 16px; }
.hh-acts .hh-open-ico { margin-left: 6px; }
/* Открыто — значок отмечен, и шеврон разворачивается: теперь он закрывает. */
.hh-acts .icon-btn[aria-expanded="true"] { color: var(--accent-dark); background: var(--accent-soft); }
.hh-acts .icon-btn[aria-expanded="true"] svg { transform: rotate(180deg); }

/* Строка-кнопка «Выбрать, кто наш»: главное действие блока, когда система
   нашла однофамильцев. Стиля у неё не было, и браузер рисовал кнопку по
   умолчанию — чёрная рамка и жирный текст посреди карточки ✓факт, владелец,
   2026-09-22. */
.hh-row {
  display: flex; align-items: center; gap: 10px; width: 100%; margin-top: 10px;
  padding: 9px 11px; border: 1px solid var(--line); border-radius: var(--r-sm);
  background: #fff; font: inherit; text-align: left; cursor: pointer;
}
.hh-row:hover { border-color: var(--accent); background: var(--accent-soft); }
.hh-row .grow { flex: 1; min-width: 0; }
.hh-row .hh-title { display: block; }
.hh-row .cand-sub { display: block; margin-top: 1px; }
/* Шеврон — того же размера, что значки в углу блока, и разворачивается, когда
   панель открыта: тогда он закрывает, а не открывает. */
.hh-row .chev { flex: none; display: flex; color: var(--muted-2); }
.hh-row .chev svg { display: block; width: 16px; height: 16px; }
.hh-row[aria-expanded="true"] { border-color: var(--accent); background: var(--accent-soft); }
.hh-row[aria-expanded="true"] .chev { color: var(--accent-dark); }
.hh-row[aria-expanded="true"] .chev svg { transform: rotate(180deg); }

/* Сопутствующие действия строкой, без рамок: главное действие в блоке одно, и
   три одинаковые кнопки подряд перестают его показывать. */
.hh-mini { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 10px; font-size: 12px; }
.hh-mini a, .hh-mini button {
  padding: 0; border: 0; background: none; font: inherit; font-weight: 600;
  color: var(--accent-dark); cursor: pointer; text-decoration: none;
}
.hh-mini a:hover, .hh-mini button:hover { text-decoration: underline; }

/* ── Почта: окно письма и список писем ────────────────────────────────────
   Окно шире обычной модалки (решение владельца 2026-09-22: «форма ответа
   нужна побольше») — в 560 точках оформленное письмо не собрать. Свой корень
   #mail-root, а не modal-root: письмо пишут дольше реплики, и чужая модалка
   не должна его закрывать.

   Свёрнутое окно — полоска внизу справа: черновик лежит на сервере, но видеть,
   что письмо начато, человек должен, иначе он напишет его второй раз. */
/* Уровень 38 — между выезжающей панелью (35) и модалкой (40), и это не
   вкусовщина. На 40 письмо оказывалось на одном уровне с .overlay и выигрывало
   по порядку в разметке (#mail-root стоит после #modal-root): окно шаблонов
   рисовалось ПОД письмом, и кнопка «Шаблоны» выглядела сломанной. Поймано
   живой проверкой на стенде 2026-09-22 — по разметке этого не видно вовсе. */
/* Окно письма — в правом нижнем углу, вид из прототипа design/mail-screen.html
   (.mcomp). ✓факт, владелец, 2026-09-23: «у нас там было отличная форма по
   правому углу». Модалка по центру с затемнением закрывала карточку, ради
   которой письмо и пишут. Уровень 38 — прежний, по причине выше. */
.mailc-wrap {
  position: fixed; right: 22px; bottom: 0; z-index: 38;
  width: min(880px, calc(100vw - 44px)); max-height: calc(100vh - 64px);
  display: flex;
}
.mailc-wrap.max { left: 24px; right: 24px; top: 24px; bottom: 24px; width: auto; max-height: none; }
/* Свёрнутое — одна шапка, поднятая над кнопкой «Переписка» в том же углу. */
.mailc-wrap.min { bottom: 78px; width: min(420px, calc(100vw - 44px)); }
.mcomp {
  flex: 1; min-width: 0; min-height: 0; display: flex; flex-direction: column;
  background: var(--surface); border-radius: var(--r-lg) var(--r-lg) 0 0;
  box-shadow: var(--shadow-lg), 0 0 0 1px var(--field);
}
.mcomp.max, .mcomp.min { border-radius: var(--r-lg); }
.mcomp.min .mcomp-h { border-radius: var(--r-lg); cursor: pointer; }
/* Прокручивается набор письма, а не окно целиком: поля «кому» и «тема»
   остаются на виду. */
.mcomp-two { flex: 1; min-height: 0; overflow-y: auto; }
.mcomp.max textarea { min-height: 360px; }
.mcomp-h {
  display: flex; align-items: center; gap: 8px; padding: 10px 12px; border-radius: var(--r-lg) var(--r-lg) 0 0;
  background: #16242b; color: #eaf2f4; font-size: 13px; font-weight: 700;
}
.mcomp-h .grow { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mcomp-h .saved { font-size: 11px; font-weight: 600; color: #9db6bf; }
.mcomp-h button { border: 0; background: transparent; color: #cfe0e4; cursor: pointer; font-size: 16px; line-height: 1; padding: 2px 6px; }
.mcomp-h button:hover { color: #fff; }
.mcomp-h button svg { vertical-align: -2px; }
/* Линии окна письма — чёткие (владелец, 2026-09-23): поля разделены
   линией, заметной на белом, строка в работе отмечена полосой слева. */
.mcomp-f { display: flex; align-items: center; gap: 8px; padding: 8px 12px; border-bottom: 1px solid var(--field); font-size: 13px; }
.mcomp-f:focus-within { box-shadow: inset 3px 0 0 var(--accent); }
.mcomp-f label { color: var(--text-3); font-weight: 600; flex: none; width: 58px; }
.mcomp-f input { flex: 1; min-width: 0; border: 0; padding: 4px 0; font-size: 13px; background: transparent; box-shadow: none; }
.mcomp-f input:focus { outline: none; box-shadow: none; }
/* «От кого» при нескольких своих ящиках — выбор, но в строку окна, как поле. */
.mcomp-f select { flex: 1; min-width: 0; border: 0; padding: 4px 0; font-size: 13px; background: transparent; box-shadow: none; cursor: pointer; }
.mcomp-f select:focus { outline: none; box-shadow: none; }
.mcomp-f .cc { display: flex; gap: 8px; flex: none; }
.mcomp-f .cc button { border: 0; background: transparent; color: var(--muted); font-size: 12.5px; font-weight: 700; cursor: pointer; }
.mcomp-f .cc button:hover { color: var(--accent-dark); }
.mcomp-chips { display: flex; flex-wrap: wrap; gap: 6px; padding: 8px 12px; border-bottom: 1px solid var(--field); background: #f7fafb; }
.mcomp-chips .mc-tpl-new { color: var(--accent-dark); border-style: dashed; }
.mcomp-chips .pill { cursor: pointer; }
.mcomp textarea {
  margin: 8px 12px; min-height: 260px; resize: vertical; border: 0; padding: 0; box-shadow: none;
  font: inherit; font-size: 14px; line-height: 1.6; background: transparent; width: calc(100% - 24px);
}
.mcomp textarea:focus { outline: none; box-shadow: none; }
.mcomp-note { padding: 0 12px 8px; }
.mcomp-foot { display: flex; align-items: center; gap: 8px; padding: 10px 12px; border-top: 1px solid var(--field); flex-wrap: wrap; }
.mcomp-foot .sp { flex: 1; }
.mcomp-hint { padding: 0 12px 12px; }
.mcomp.min .mcomp-f, .mcomp.min .mcomp-chips, .mcomp.min textarea,
.mcomp.min .mcomp-foot, .mcomp.min .mcomp-hint { display: none; }
.mc-hidden { display: none; }
/* Вложения письма — файлы «Документов» (2026-09-23): чипы под текстом. */
.mcomp-atts { display: flex; flex-wrap: wrap; gap: 6px; padding: 0 12px 8px; }
.mc-att {
  display: inline-flex; align-items: center; gap: 6px; max-width: 100%; padding: 5px 8px; border-radius: var(--r-md);
  background: var(--soft); box-shadow: inset 0 0 0 1px var(--field); font-size: 12.5px;
}
.mc-att svg { flex: none; color: var(--text-3); }
.mc-att-n { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
.mc-att button { border: 0; background: transparent; color: var(--muted); cursor: pointer; padding: 0 2px; }
.mc-att button:hover { color: var(--danger); }
.mc-att.busy { opacity: .7; }
.mcomp.min .mcomp-atts { display: none; }
.mc-picks { display: flex; flex-direction: column; gap: 4px; max-height: 50vh; overflow-y: auto; }
.mc-pick {
  display: flex; align-items: center; gap: 8px; width: 100%; padding: 8px 10px; border: 0; border-radius: var(--r-md);
  background: #fff; box-shadow: inset 0 0 0 1px var(--field); cursor: pointer; text-align: left; font: inherit; font-size: 13px;
}
.mc-pick:hover { box-shadow: inset 0 0 0 1px var(--accent); }
.mc-pick .cand-sub { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mc-pick .mc-att-n { max-width: 45%; }
.mc-pick-mark { flex: none; font-size: 12px; font-weight: 700; color: var(--accent-dark); }
.mc-pick.on { background: #f0f8f6; }
.mc-pick.on .mc-pick-mark { color: var(--muted); }
a.matt { color: inherit; text-decoration: none; }
a.matt:hover { box-shadow: inset 0 0 0 1px var(--accent); }

/* Полоска «письмо уходит» и свёрнутое окно — обе внизу справа, на одном
   месте: это одно и то же письмо в разных состояниях. */
/* Плашка отмены — туда же, где система показывает тосты: по центру
   внизу. В правом нижнем углу она оказывалась ПОД кнопкой «Переписка»
   (z-index 45 против 38), и кнопки «Отменить отправку» не было видно
   вовсе — при том что отменить можно восемь секунд и второго шанса
   нет. Замечание владельца 2026-09-22 со скриншотом.

   Свёрнутое письмо остаётся справа (оно живёт долго и центр занимать
   не должно), но поднято над кнопкой и по слою, и по высоте. */
.mailc-hold, .mailc-min {
  position: fixed; right: 22px; bottom: 78px; z-index: 38;
  display: flex; align-items: center; gap: 12px;
  max-width: min(560px, calc(100vw - 44px));
  padding: 12px 16px; border-radius: var(--r-lg);
  background: #fff; border: 1px solid var(--line);
  box-shadow: 0 18px 38px -20px rgba(14, 36, 44, 0.55);
  font-size: 14px;
}
/* Плашка отмены — по центру низа, туда же, где система показывает
   тосты: в правом углу она встречалась с кнопкой «Переписка», и
   кнопки «Отменить отправку» не было видно. Отменить можно восемь
   секунд, второго шанса нет. */
.mailc-hold {
  right: auto; left: 50%; transform: translateX(-50%); bottom: 26px;
}
.mailc-min { cursor: pointer; }
.mailc-min .mail-subj, .mailc-min .cand-sub { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mailc-min .btn { margin-left: auto; }

/* Список писем карточки — строками, а не карточками переписки: у письма
   важны тема, адресат и дата, и в списке из двадцати их ищут глазами. */
.mail-list { display: flex; flex-direction: column; gap: 2px; }
.mail-row {
  padding: 9px 10px; border-radius: var(--r-md); cursor: pointer;
  border: 1px solid transparent;
}
.mail-row:hover { background: var(--soft); border-color: var(--line); }
.mail-row-top { display: flex; align-items: center; gap: 8px; }
.mail-subj { font-weight: 600; font-size: 14px; }
.mail-row-top .tag { margin-left: auto; }
.mail-note { color: var(--danger); }

/* Ссылка-кнопка внутри подсказки: «копия и скрытая» открывает два поля,
   которые нужны одному письму из десяти. */
.linkish {
  border: 0; background: none; padding: 0; cursor: pointer;
  color: var(--accent-ink, var(--text-2)); text-decoration: underline dotted;
  font: inherit;
}

/* ── раздел «Почта»: вид перенесён из прототипа design/mail-screen.html ──
   Прототип согласован с владельцем в пять заходов 2026-09-22 (последний —
   «не понятно, где входящее, а где исходящее»), и вид раздела берётся оттуда,
   а не придумывается заново. Окно письма (.mcomp) перенесено 2026-09-23 по
   слову владельца — см. .mailc-wrap ниже. Правка вида — сначала в прототипе. */
/* ── экран почты: папки и список; письмо открывается ПАНЕЛЬЮ ──────────── */
/* ✓факт, владелец, 2026-09-22: «лучше делать механику как в кандидатах, чтобы
   выезжала информация и инструменты, сейчас как-то смещено получается».
   Колонка чтения рядом со списком двигала весь экран, а серия писем в узкой
   колонке читалась как непонятно что. Теперь список писем занимает ширину, а
   письмо со всеми инструментами выезжает справа поверх — как карточка
   кандидата (.panel-wrap / .panel-head / .panel-body продуктовой версии). */
.ml { display: grid; grid-template-columns: 228px minmax(0, 1fr); gap: 14px; align-items: stretch; }
.ml-h { height: calc(100vh - 44px - 150px); min-height: 420px; }
.ml-nav { display: flex; flex-direction: column; gap: 2px; padding: 10px 8px; overflow-y: auto; }
.ml-cap { font-size: 11px; font-weight: 800; color: var(--muted); text-transform: uppercase; letter-spacing: .05em; padding: 12px 8px 4px; }
.ml-b {
  display: flex; align-items: center; gap: 9px; width: 100%; text-align: left;
  border: 0; background: transparent; cursor: pointer; padding: 7px 9px; border-radius: var(--r-sm);
  font-size: 13px; font-weight: 600; color: var(--text-2);
}
.ml-b:hover { background: var(--soft); }
.ml-b.on { background: var(--accent-soft); color: var(--accent-dark); }
.ml-b .lb { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ml-b .addr { display: block; font-size: 11px; font-weight: 600; color: var(--muted); }
.ml-b .n { font-size: 11.5px; font-weight: 800; color: var(--muted); }
.ml-b .ic { flex: none; display: inline-flex; color: var(--muted-2); }
.ml-b .ic svg { width: 15px; height: 15px; }
.ml-dot { width: 8px; height: 8px; border-radius: 999px; flex: none; }
/* Действия со своим ящиком — под ним, мелко: ими пользуются редко, но
   искать их в профиле владелец не должен (2026-09-23). */
.ml-box { position: relative; }
.ml-box-acts {
  position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
  display: none; align-items: center; gap: 2px;
}
.ml-box-acts .icon-btn { width: 26px; height: 26px; min-width: 26px; background: #fff; }
.ml-box-acts .icon-btn:hover { background: #d9f2ef; }
.ml-box-acts svg { width: 15px; height: 15px; }
.ml-box:hover .ml-box-acts, .ml-box:focus-within .ml-box-acts { display: flex; }
.ml-box:hover .ml-b .n, .ml-box:focus-within .ml-b .n { display: none; }
/* Значки не наезжают на адрес: строка на время наведения уступает им место. */
.ml-box:hover .ml-b, .ml-box:focus-within .ml-b { padding-right: 66px; }
/* Третий значок — «сделать основным» у неосновного ящика. */
.ml-box:has(.ml-box-acts > :nth-child(3)):hover .ml-b,
.ml-box:has(.ml-box-acts > :nth-child(3)):focus-within .ml-b { padding-right: 94px; }
.ml-box-add .lb { color: var(--accent-dark); }
.ml-dot.ok { background: var(--accent-500); } .ml-dot.bad { background: var(--danger); }

/* Список писем — строками, а не карточками: в почте глазами идут по колонке
   отправителей и по теме, а карточки с тенями эту колонку ломают. */
.mlist { display: flex; flex-direction: column; padding: 0; overflow: hidden; }
.mlist-h {
  display: flex; align-items: center; gap: 10px; padding: 9px 12px;
  border-bottom: 1px solid var(--field); font-size: 12px; color: var(--muted);
}
.mlist-h .grow { flex: 1; }
.mlist-h select { border: 0; background: transparent; color: var(--muted); font-size: 12px; font-weight: 700; cursor: pointer; }
/* Ширина — по содержимому: продуктовое `select { width: 100% }` иначе
   растягивает порядок писем на всю шапку и сминает счётчик переписок. */
.mlist-h select { width: auto; flex: none; padding: 4px 6px; }
.mlist-h .grow { min-width: 0; }
.mlist-b { flex: 1; overflow-y: auto; }
.mlist-more { padding: 10px 12px 14px; text-align: center; }
/* Строка — одна линия одной высоты: отправитель, тема с отрывком, пометки,
   дата (✓факт, владелец, 2026-09-23: «список писем компактнее и чётче, а то
   растянутые получаются и прыгающие»). Пометки встают в ту же линию после
   темы, дата короткая и не переносится. */
.mrow {
  display: grid; grid-template-columns: 26px 200px minmax(0, 1fr) 96px; gap: 0 10px;
  align-items: center; min-height: 42px; padding: 5px 12px 5px 8px; border-bottom: 1px solid var(--line-2);
  cursor: pointer; border-left: 3px solid transparent;
}
.mrow-from { display: flex; align-items: baseline; gap: 6px; min-width: 0; font-size: 13px; color: var(--text-2); }
.mrow-from b { font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mrow-from .cand-sub { flex: none; max-width: 78px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mrow-meta { display: flex; align-items: center; justify-content: flex-end; gap: 6px; font-size: 12px; color: var(--muted); white-space: nowrap; }
.mrow-body { display: flex; align-items: center; gap: 8px; min-width: 0; }
.mrow-body .msubj-line { flex: 1; margin-top: 0; }
/* Пометки не режутся: «ждёт ответа 1 сут» обрывалось на «1 су». Ужимается тема. */
.mrow-body .mrow-tags { flex: none; flex-wrap: nowrap; margin-top: 0; }
.mrow-tags > * { white-space: nowrap; }
.mrow-meta .mchain {
  display: inline-flex; align-items: center; justify-content: center; min-width: 18px; height: 18px;
  padding: 0 5px; border-radius: 999px; background: var(--soft); color: var(--text-3); font-size: 11px; font-weight: 800;
}
.mrow:hover { background: #f1f6f8; }
/* Действия значками при наведении (владелец, 2026-09-23): встают на место
   даты и вложения, строка шире не становится. С клавиатуры — так же. */
.mrow-meta { position: relative; min-height: 26px; }
.mrow-acts { display: none; align-items: center; gap: 2px; }
.mrow-acts .icon-btn { width: 26px; height: 26px; border-radius: var(--r-sm); color: var(--text-3); }
.mrow-acts .icon-btn:hover { background: #e3edf1; color: var(--accent-dark); }
.mrow-acts svg { width: 16px; height: 16px; }
.mrow:hover .mrow-acts, .mrow:focus-within .mrow-acts { display: flex; }
.mrow:hover .mrow-meta > :not(.mrow-acts), .mrow:focus-within .mrow-meta > :not(.mrow-acts) { display: none; }
.mrow.on { background: var(--accent-soft); border-left-color: var(--accent); }
.mrow.unread { background: #fff; }
.mrow.unread .mrow-from b, .mrow.unread .msubj { font-weight: 800; color: var(--text); }
.mrow-pick { display: flex; align-items: center; justify-content: center; }
.mrow-pick input { width: 15px; height: 15px; accent-color: var(--accent); cursor: pointer; }
.mrow-main { min-width: 0; }
.mfrom { display: flex; align-items: baseline; gap: 7px; font-size: 13.5px; color: var(--text-2); }
.mfrom b { font-weight: 600; color: var(--text-2); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mfrom .mdate { margin-left: auto; flex: none; font-size: 12px; color: var(--muted); }
.mfrom .mclip { flex: none; color: var(--muted); display: inline-flex; }
.mfrom .mclip svg { width: 13px; height: 13px; }
.msubj-line { margin-top: 2px; font-size: 13px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msubj { font-weight: 600; color: var(--text); }
.msnip { color: var(--muted); }
.mdraft { color: var(--danger); font-weight: 800; }
/* Метка «ответ» в строке списка: ответ от нового письма отличают сразу, не
   читая тему (владелец, 2026-09-23: «видеть в списке писем, где ответ, а
   где просто письмо»). */
.mre {
  display: inline-flex; align-items: center; gap: 3px; margin-right: 6px; padding: 0 7px 0 5px;
  border-radius: 999px; background: var(--accent-soft); color: var(--accent-dark);
  font-size: 11px; font-weight: 800; vertical-align: 1px;
}
.mre svg { width: 12px; height: 12px; }
.mrow-tags { display: flex; align-items: center; flex-wrap: wrap; gap: 5px; margin-top: 5px; }
.mrow-tags:empty { display: none; }
/* Кружок прочтения — кнопка: закрашен у новой переписки, у прочитанной
   виден кольцом при наведении на строку. Нажатие переключает (2026-09-23). */
.mdot, .mdot-sp { flex: none; width: 16px; height: 16px; align-self: center; }
.mdot {
  display: inline-flex; align-items: center; justify-content: center; padding: 0;
  border: 0; border-radius: 999px; background: transparent; cursor: pointer;
}
.mdot::before {
  content: ''; width: 8px; height: 8px; border-radius: 999px; box-sizing: border-box;
  border: 1.5px solid transparent; transition: border-color .12s, background .12s;
}
.mdot.on::before { background: var(--accent); border-color: var(--accent); }
.mrow:hover .mdot:not(.on)::before { border-color: var(--muted-2); }
.mdot:hover { background: var(--soft); }
.mdot:hover:not(.on)::before { border-color: var(--accent); }
.mdot:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.mtaken {
  display: inline-flex; align-items: center; gap: 4px; padding: 1px 7px; border-radius: 999px;
  font-size: 10.5px; font-weight: 800; color: var(--warn); background: var(--warn-bg); white-space: nowrap;
}

/* Поиск: строка всегда, разбор по полям — по кнопке. */
.msearch { display: flex; align-items: center; gap: 8px; flex: 1; max-width: 460px; }
.msearch input { flex: 1; padding: 7px 12px; border-radius: 999px; border: 1.5px solid var(--field); background: #fff; font-size: 13px; }
.msearch-adv { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px; padding: 12px 14px; margin-bottom: 10px; }
.msearch-adv label { display: block; font-size: 11px; font-weight: 800; color: var(--muted); margin-bottom: 4px; text-transform: uppercase; letter-spacing: .04em; }
.msearch-adv input, .msearch-adv select { width: 100%; padding: 6px 10px; border-radius: var(--r-sm); border: 1px solid var(--field); background: #fff; font-size: 13px; }

/* Письмо — как письмо: шапка, тело, вложения, действия под текстом.
   Живёт внутри выезжающей панели, поэтому своей прокрутки и высоты не имеет:
   прокручивается .panel-body, как в карточке кандидата. */
.mread-marks { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.mread-tools { display: flex; align-items: center; gap: 6px; margin-top: 10px; flex-wrap: wrap; }
.mread-tools .sp { flex: 1; }
.mempty { padding: 22px; text-align: center; color: var(--muted); font-size: 13px; }
.mprev {
  display: flex; align-items: center; gap: 9px; width: 100%; text-align: left;
  border: 0; border-bottom: 1px solid var(--line-2); background: transparent; cursor: pointer;
  padding: 9px 2px; font-size: 13px; color: var(--text-2);
}
.mprev:hover { background: #f7fafb; }
.mprev .mp-txt { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--muted); }
.mprev .mp-date { flex: none; font-size: 12px; color: var(--muted); }
/* Серия писем — один лист, как в почтовом клиенте: письма разделены тонкой
   линией, без рамок, цветных полос и заливок (✓факт, владелец, 2026-09-23:
   «не нравятся карточки серии писем: их рамки, разделение и выделения»).
   Входящее от нашего по-прежнему отличается до чтения текста (владелец,
   2026-09-22): цветом аватара, именем «Мы» и стрелкой направления у даты. */
.mthread { padding: 0; overflow: hidden; }
.mthread-h {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 12px 20px; border-bottom: 1px solid var(--field);
  font-size: 10px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: var(--muted);
}
.mthread-all {
  border: 0; background: transparent; padding: 0; cursor: pointer; font: inherit;
  font-size: 12.5px; font-weight: 600; letter-spacing: 0; text-transform: none; color: var(--accent-dark);
}
.mthread-all:hover { text-decoration: underline; }
.mthread .mprev { padding: 11px 20px; border-bottom: 1px solid var(--line-2); }
.mthread .mletter { padding: 16px 20px 18px; border-bottom: 1px solid var(--line-2); }
.mletter-h { display: flex; align-items: flex-start; gap: 11px; width: 100%; text-align: left;
  border: 0; background: transparent; padding: 0; font: inherit; cursor: pointer; }
.mletter-h:hover .mletter-who b { color: var(--accent-dark); }
.mdir { display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; color: var(--accent-dark); }
.mdir.out { color: var(--muted-2); }
.mdir svg { width: 13px; height: 13px; }
.mletter-date { display: flex; align-items: center; gap: 8px; }
.mava {
  flex: none; width: 36px; height: 36px; border-radius: 999px; display: flex; align-items: center; justify-content: center;
  font-size: 13px; font-weight: 800; color: var(--accent-dark); background: var(--accent-soft);
}
.mava.out { color: var(--text-2); background: var(--soft); }
.mletter-who { flex: 1; min-width: 0; font-size: 13.5px; }
.mletter-who b { font-weight: 700; }
.mletter-to { font-size: 12px; color: var(--muted); margin-top: 1px; }
.mletter-date { flex: none; font-size: 12px; color: var(--muted); }
.mbody { margin: 12px 0 0 47px; font-size: 14px; line-height: 1.62; color: var(--text); white-space: pre-wrap; }
.mbody.html a.mcta, .mcta {
  display: inline-block; padding: 10px 20px; border-radius: var(--r-sm); margin: 4px 0 8px;
  background: var(--accent); color: #fff; font-weight: 700; font-size: 14px; text-decoration: none;
}
.mbody.html hr { border: 0; border-top: 1px solid var(--line-2); margin: 12px 0; }
.mbody.html { white-space: normal; }
.mbody.html p { margin-bottom: 10px; }
.mbody.html ul { margin: 0 0 10px 18px; }
.mbody.html table { border-collapse: collapse; margin-bottom: 10px; font-size: 13px; }
.mbody.html td, .mbody.html th { border: 1px solid var(--line-2); padding: 5px 9px; }
.mimg-bar {
  display: flex; align-items: center; gap: 10px; margin: 10px 0 0 47px; padding: 8px 11px;
  border-radius: var(--r-sm); background: var(--warn-bg); color: var(--warn); font-size: 12.5px; font-weight: 600;
}
.mimg-stub {
  display: flex; align-items: center; justify-content: center; height: 76px; margin: 10px 0 0 47px;
  border: 1px dashed var(--field); border-radius: var(--r-sm); color: var(--muted-2); font-size: 12px;
}
.mquote-btn {
  margin: 10px 0 0 47px; border: 0; border-radius: var(--r-sm); background: var(--soft); color: var(--text-3);
  padding: 2px 9px; font-size: 13px; font-weight: 800; letter-spacing: .08em; cursor: pointer; line-height: 1.5;
}
.mquote-btn:hover { background: #dfe8ec; }
.mquote { margin: 8px 0 0 47px; padding-left: 12px; border-left: 2px solid var(--field); color: var(--muted); font-size: 13px; white-space: pre-wrap; }
.matts { display: flex; flex-wrap: wrap; gap: 8px; margin: 12px 0 0 47px; }
.matt {
  display: flex; align-items: center; gap: 9px; padding: 8px 11px; border-radius: var(--r-md);
  background: #fff; box-shadow: inset 0 0 0 1px var(--field); font-size: 13px; min-width: 210px;
}
.matt.big { box-shadow: inset 0 0 0 1px #f0c36b; background: #fffaf0; }
.matt .mi { width: 28px; height: 28px; border-radius: var(--r-sm); background: var(--soft); display: flex; align-items: center; justify-content: center; color: var(--text-3); flex: none; }
.matt .mn { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
.matt .msz { color: var(--muted); font-size: 12px; }
.mstate { margin: 10px 0 0 47px; font-size: 12px; font-weight: 700; color: var(--muted); }
.mstate.bad { color: var(--danger); }
.mstate.wait { color: var(--warn); }
.mfoot-acts { display: flex; gap: 8px; flex-wrap: wrap; padding: 14px 20px 18px 67px; }
/* Новое письмо сверху, ответ сразу под ним: черта — после ответа, а не между
   письмом и его ответом. */
.mthread .mletter:has(+ .mfoot-acts), .mthread .mprev:has(+ .mfoot-acts) { border-bottom: 0; }
.mthread .mfoot-acts:not(:last-child) { border-bottom: 1px solid var(--line-2); }
/* Правая колонка панели — «что за карточка»: этого в почтовом клиенте нет, и
   ради этого всё затевается. Стоит там же, где у кандидата «следующий шаг». */
.ml-card { display: flex; flex-direction: column; gap: 14px; }

.blk-acts { display: flex; align-items: center; gap: 6px; margin-left: auto; }
.blk-acts .icon-btn { width: 30px; height: 30px; border-radius: var(--r-sm); }
.blk-acts .icon-btn svg { display: block; width: 16px; height: 16px; }
/* Счётчик блока «Документы» — строкой под шапкой: шапка карточки держит
   отступ 12px, счётчик к ней ближе, до файлов — как между группами. */
.fs-blk-sum { margin: -6px 0 10px; }

.ml-bulk {
  display: flex; align-items: center; gap: 8px; padding: 8px 12px;
  border-bottom: 1px solid var(--line-2); background: var(--accent-soft); font-size: 13px; font-weight: 700; color: var(--accent-dark);
}
.ml-undo {
  position: fixed; left: 50%; bottom: 18px; transform: translateX(-50%); z-index: 55;
  display: flex; align-items: center; gap: 12px; padding: 9px 12px 9px 16px; border-radius: 999px;
  background: #16242b; color: #fff; box-shadow: var(--shadow-lg); font-size: 13px;
}
.ml-undo button { border: 0; background: #2a3b43; color: #eaf2f4; border-radius: 999px; padding: 5px 12px; font-weight: 700; cursor: pointer; }
.ml-undo button:hover { background: #34474f; }


.ml-note { font-size: 12.5px; line-height: 1.45; padding: 9px 11px; border-radius: var(--r-sm); background: var(--soft); color: var(--text-3); }
.ml-note.warn { background: var(--warn-bg); color: var(--warn); }
.ml-note.bad { background: var(--danger-bg); color: var(--danger); }

/* Ширина панели — под две колонки: письмо и «что за карточка». Верхнего
   предела продуктовой панели (1180px) держимся: панель во весь экран
   перестаёт быть панелью. */
.mail-panel .cols { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: 18px; align-items: start; }
@container (max-width: 900px) { .mail-panel .cols { grid-template-columns: 1fr; } }
.mail-panel .panel-head { align-items: flex-start; }
.mail-panel .panel-head .grow { min-width: 0; }
.mail-panel .panel-body { background: var(--soft); }

@media (max-width: 1500px) { .ml { grid-template-columns: 212px minmax(0, 1fr); } .msearch-adv { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 1180px) {
  .ml { grid-template-columns: 1fr; } .ml-h { height: auto; min-height: 0; }
  .mrow { grid-template-columns: 26px minmax(0, 1fr); }
  .mrow-from, .mrow-meta { grid-column: 2; justify-content: flex-start; }
  .ml-steps, .ml-two, .ml-grid2, .ml-grid3 { grid-template-columns: 1fr; }
}
/* Три колонки: папки, контакты, список. ✓факт, владелец, 2026-09-23:
   список во всю ширину «выглядит растянутым», а искать переписку удобнее
   от человека. Правила стоят после общих: .ml.ml3 весомее .ml, и в
   узком окне колонки складываются так же явно. */
.ml.ml3 { grid-template-columns: 212px 264px minmax(0, 1fr); }
/* Линии и рамки почты — чётче (✓факт, владелец, 2026-09-23: «более чёткими
   линиями и рамками, сейчас всё сливается»): колонки обведены, строки
   разделены линией, а не едва заметным оттенком. Рамка — тенью в 1px, чтобы
   размеры колонок не менялись. */
.ml > .card, .card.mthread { box-shadow: 0 0 0 1px var(--field), var(--shadow-sm); }
.ml-ppl .ml-pp { border-radius: 0; border-top: 1px solid var(--line-2); }
.ml-ppl .ml-pp.on { box-shadow: inset 3px 0 0 var(--accent); }
.ml-pp { padding: 6px 8px; }
.mava.sm { width: 28px; height: 28px; font-size: 11px; }
@media (max-width: 1500px) { .ml.ml3 { grid-template-columns: 196px 240px minmax(0, 1fr); } }
@media (max-width: 1180px) { .ml.ml3 { grid-template-columns: 1fr; } .ml-ppl { max-height: 280px; } }

/* ══ Документы: файлы и документы агентства (screen-files.js) ═════════════
   Перенесено из утверждённого прототипа design/files-screen.html (2026-09-23),
   без листов-макетов: вместо них настоящий просмотр файла. */

/* Пояснение прототипа: спокойная строка, а не жёлтая плашка — владелец
   считает плашки частью «сыро» (2026-09-22). */
.fs-note { font-size: 12.5px; line-height: 1.55; color: var(--muted); background: var(--soft); border-radius: var(--r-sm); padding: 9px 12px; }
.fs-note b { color: var(--text-2); }
.fs-note.warn { color: var(--warn); background: var(--warn-bg); }
.fs-note.warn b { color: var(--warn); }
.fs-note.bad { color: var(--danger); background: var(--danger-bg); }
.fs-note.bad b { color: var(--danger); }
.fs-note.ok { color: var(--accent-dark); background: var(--accent-soft); }

.fs-row-g { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
.fs-two { display: grid; grid-template-columns: minmax(0, 1fr) 420px; gap: 18px; align-items: start; }
.fs-three { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; align-items: start; }
.fs-stack { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
.fs-sub { font-size: 12px; color: var(--muted); }
/* ── раздел «Документы»: разрезы слева, список строками ───────────────── */
.fs { display: grid; grid-template-columns: 250px minmax(0, 1fr); gap: 14px; align-items: stretch; }
.fs-h { height: calc(100vh - 44px - 150px); min-height: 440px; }
.fs-nav { display: flex; flex-direction: column; gap: 2px; padding: 10px 8px; overflow-y: auto; }
.fs-cap { font-size: 11px; font-weight: 800; color: var(--muted); text-transform: uppercase; letter-spacing: .05em; padding: 12px 8px 4px; }
.fs-b {
  display: flex; align-items: center; gap: 9px; width: 100%; text-align: left;
  border: 0; background: transparent; cursor: pointer; padding: 7px 9px; border-radius: var(--r-sm);
  font: inherit; font-size: 13px; font-weight: 600; color: var(--text-2);
}
.fs-b:hover { background: var(--soft); }
.fs-b.on { background: var(--accent-soft); color: var(--accent-dark); }
.fs-b .lb { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fs-b .lb small { display: block; font-size: 11px; font-weight: 600; color: var(--muted); }
.fs-b .n { font-size: 11.5px; font-weight: 800; color: var(--muted); }
.fs-b .n.hot { color: #fff; background: var(--danger); border-radius: 999px; padding: 0 6px; }
.fs-b .n.act { color: var(--accent-dark); background: var(--accent-soft); border-radius: 999px; padding: 0 6px; }
.fs-b .ic { flex: none; display: inline-flex; color: var(--muted-2); }
.fs-b .ic svg { width: 15px; height: 15px; }
.fs-quota { margin: 14px 8px 4px; font-size: 11.5px; color: var(--muted); }
.fs-quota .bar { margin: 5px 0 3px; height: 6px; }

.fs-list { display: flex; flex-direction: column; padding: 0; overflow: hidden; position: relative; }
.fs-list-h {
  display: flex; align-items: center; gap: 10px; padding: 9px 12px;
  border-bottom: 1px solid var(--line-2); font-size: 12px; color: var(--muted);
}
.fs-list-h .grow { flex: 1; min-width: 0; }
.fs-list-h select { border: 0; background: transparent; color: var(--muted); font: inherit; font-size: 12px; font-weight: 700; cursor: pointer; }
.fs-list-b { flex: 1; overflow-y: auto; }
.fs-bulk { display: flex; align-items: center; gap: 8px; padding: 8px 12px; background: var(--accent-soft); color: var(--accent-dark); font-size: 12.5px; font-weight: 700; border-bottom: 1px solid var(--line-2); flex-wrap: wrap; }
.fs-crumbs { display: flex; align-items: center; gap: 6px; padding: 10px 14px 0; font-size: 12.5px; color: var(--muted); flex-wrap: wrap; }
.fs-crumbs button { border: 0; background: none; padding: 0; font: inherit; color: var(--accent-dark); cursor: pointer; font-weight: 700; }
.fs-crumbs b { color: var(--text); }
.fs-folders { display: flex; flex-wrap: wrap; gap: 8px; padding: 10px 14px 12px; border-bottom: 1px solid var(--line-2); }
.fs-fold {
  display: inline-flex; align-items: center; gap: 7px; padding: 7px 11px; border-radius: var(--r-sm);
  border: 1px solid var(--line-2); background: #fff; cursor: pointer; font: inherit; font-size: 12.5px; font-weight: 700; color: var(--text-2);
}
.fs-fold:hover { border-color: var(--field); background: #f7fafb; }
.fs-fold.on { border-color: var(--accent); background: var(--accent-soft); color: var(--accent-dark); }
.fs-fold svg { width: 15px; height: 15px; color: var(--muted-2); }
.fs-fold .n { color: var(--muted); font-weight: 800; font-size: 11.5px; }
.fs-fold.smart { border-style: dashed; }

.fs-frow {
  display: grid; grid-template-columns: 24px 34px minmax(0, 1fr) 190px 168px 92px;
  gap: 0 12px; align-items: center; padding: 9px 14px 9px 10px; border-bottom: 1px solid var(--line);
  cursor: pointer; border-left: 3px solid transparent;
}
.fs-frow:hover { background: #f7fafb; }
.fs-frow.on { background: var(--accent-soft); border-left-color: var(--accent); }
.fs-frow.fresh { border-left-color: var(--accent-500); }
.fs-frow input[type=checkbox] { width: 15px; height: 15px; accent-color: var(--accent); cursor: pointer; }
.fs-fname { min-width: 0; }
.fs-fname b { display: block; font-size: 13.5px; font-weight: 700; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fs-fmeta { display: flex; align-items: center; gap: 6px; margin-top: 3px; font-size: 11.5px; color: var(--muted); min-width: 0; flex-wrap: wrap; }
.fs-fmeta svg { width: 12px; height: 12px; vertical-align: -2px; }
.fs-fcard { font-size: 12.5px; color: var(--text-2); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fs-fcard small { display: block; font-size: 11px; color: var(--muted); }
.fs-fwhen { text-align: right; font-size: 11.5px; color: var(--muted); line-height: 1.35; }
.fs-fwhen b { display: block; color: var(--text-3); font-weight: 600; }
.fs-empty { padding: 26px; text-align: center; color: var(--muted); font-size: 13px; }

/* Значок расширения: цвет по виду файла, как в любом файловом менеджере —
   глаз находит «где тут PDF» раньше, чем читает имя. */
.fs-ext {
  width: 32px; height: 38px; border-radius: 6px; display: inline-flex; align-items: flex-end; justify-content: center;
  padding-bottom: 5px; font-size: 9.5px; font-weight: 800; letter-spacing: .03em; color: #fff; text-transform: uppercase;
  background: #8a9aa3; position: relative; flex: none;
}
.fs-ext::before { content: ""; position: absolute; top: 0; right: 0; width: 9px; height: 9px; background: rgba(255,255,255,.45); border-bottom-left-radius: 4px; }
.fs-ext.pdf { background: #d1453b; } .fs-ext.doc { background: #2f6fd6; } .fs-ext.xls { background: #1f8f5a; }
.fs-ext.img { background: #8a55c9; } .fs-ext.zip { background: #6b7a83; } .fs-ext.txt { background: #6b8592; }
.fs-ext.sm { width: 24px; height: 29px; font-size: 7.5px; padding-bottom: 3px; border-radius: 5px; }
.fs-ext.sm::before { width: 7px; height: 7px; }

/* Доступ — значком и словом: «видит заказчик» должно читаться без наведения,
   это главное, чего боятся при общем хранилище. */
.fs-acc { display: inline-flex; align-items: center; gap: 4px; padding: 1px 7px; border-radius: 999px; font-size: 10.5px; font-weight: 800; white-space: nowrap; }
.fs-acc svg { width: 12px; height: 12px; }
.fs-acc.team { color: var(--muted); background: var(--soft); }
.fs-acc.client { color: #1d5bb8; background: #e5eefc; }
.fs-acc.pd { color: var(--danger); background: var(--danger-bg); }

.fs-st { display: inline-flex; align-items: center; gap: 5px; padding: 2px 8px; border-radius: 999px; font-size: 11px; font-weight: 800; white-space: nowrap; }
.fs-st::before { content: ""; width: 6px; height: 6px; border-radius: 999px; background: currentColor; }
.fs-st.draft { color: var(--muted); background: var(--soft); }
.fs-st.review { color: #1d5bb8; background: #e5eefc; }
.fs-st.wait { color: var(--warn); background: var(--warn-bg); }
.fs-st.agreed, .fs-st.signed { color: var(--accent-dark); background: var(--accent-soft); }
.fs-st.remarks, .fs-st.rejected, .fs-st.expired { color: var(--danger); background: var(--danger-bg); }
.fs-st.expires { color: var(--warn); background: var(--warn-bg); }
.fs-st.none { display: none; }

/* Перетаскивание файла на список. Подсказка видна всегда тонкой строкой,
   а при перетаскивании список накрывается целиком. */
.fs-drop {
  position: absolute; inset: 0; z-index: 3; display: none; align-items: center; justify-content: center; flex-direction: column; gap: 6px;
  background: rgba(230, 244, 242, .93); border: 2px dashed var(--accent); border-radius: var(--r-lg);
  color: var(--accent-dark); font-weight: 800; font-size: 15px;
}
.fs-drop small { font-weight: 600; font-size: 12.5px; color: var(--text-3); }
.fs-list.dragging .fs-drop { display: flex; }
.fs-dropline { display: flex; align-items: center; gap: 8px; padding: 9px 14px; font-size: 12px; color: var(--muted); border-top: 1px dashed var(--line-2); }
/* ── панель файла ──────────────────────────────────────────────────────── */
/* Тон панели продуктовый (--soft), но поверх белого: сам --soft прозрачный,
   и без размытия подложки сквозь панель читался список под ней. */
.fs-panel .cols { grid-template-columns: minmax(0, 1fr) 400px; }
.fs-marks { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.fs-tools { display: flex; align-items: center; gap: 6px; margin-top: 10px; flex-wrap: wrap; }
.fs-tools .sp { flex: 1; }
/* Значки в кнопках раздела — контурные 16×16, как в прототипе. Только внутри
   раздела: у остальных экранов значки в кнопках свои. */
.fs-scr .btn svg, .fs-panel .btn svg, .fs-viewer .btn svg, .modal .fs-att svg { width: 15px; height: 15px; vertical-align: -3px; }
.fs-scr .btn.btn-sm svg, .fs-panel .btn.btn-sm svg, .fs-viewer .btn.btn-sm svg { margin-right: 5px; }
.fs-scr .icon-btn, .fs-panel .icon-btn, .fs-viewer .icon-btn { display: inline-flex; align-items: center; justify-content: center; }
.fs-scr .icon-btn svg, .fs-panel .icon-btn svg, .fs-viewer .icon-btn svg { width: 16px; height: 16px; }

.fs-prev { background: #e9eef1; border-radius: var(--r-md); padding: 18px; display: flex; justify-content: center; }
.fs-noprev { padding: 34px 20px; text-align: center; color: var(--muted); font-size: 13px; }
.fs-kv { display: grid; grid-template-columns: 118px minmax(0, 1fr); gap: 6px 10px; font-size: 13px; }
.fs-kv dt { color: var(--muted); } .fs-kv dd { margin: 0; color: var(--text-2); font-weight: 600; min-width: 0; }

.fs-acc-opt { display: flex; align-items: flex-start; gap: 10px; padding: 9px 10px; border-radius: var(--r-sm); border: 1px solid var(--line-2); margin-top: 7px; cursor: pointer; background: #fff; }
.fs-acc-opt.on { border-color: var(--accent); background: var(--accent-soft); }
.fs-acc-opt.off { opacity: .55; cursor: not-allowed; }
.fs-acc-opt input { margin-top: 3px; accent-color: var(--accent); }
.fs-acc-opt b { display: block; font-size: 13px; color: var(--text); }
.fs-acc-opt span { font-size: 12px; color: var(--muted); }

.fs-ver { display: flex; align-items: flex-start; gap: 10px; padding: 8px 0; border-top: 1px solid var(--line); font-size: 12.5px; }
.fs-ver:first-of-type { border-top: 0; }
.fs-ver .v { flex: none; min-width: 30px; height: 22px; border-radius: 999px; background: var(--soft); color: var(--text-3); font-weight: 800; font-size: 11px; display: inline-flex; align-items: center; justify-content: center; }
.fs-ver.cur .v { background: var(--accent); color: #fff; }
.fs-ver .t { flex: 1; min-width: 0; color: var(--text-2); }
.fs-ver .t small { display: block; color: var(--muted); }

/* ── блок «Документы» в карточке: группы сворачиваются ────────────────── */
.fs-grp { border-top: 1px solid var(--line); }
.fs-grp:first-of-type { border-top: 0; }
.fs-grp-h { display: flex; align-items: center; gap: 8px; width: 100%; padding: 9px 2px; border: 0; background: none; cursor: pointer; font: inherit; font-size: 13px; font-weight: 700; color: var(--text-2); text-align: left; }
.fs-grp-h svg { width: 14px; height: 14px; color: var(--muted); transition: transform .15s; }
.fs-grp-h.closed svg.chev { transform: rotate(-90deg); }
.fs-grp-h .n { color: var(--muted); font-weight: 800; font-size: 11.5px; }
.fs-grp-h .grow { flex: 1; }
.fs-mini { display: grid; grid-template-columns: 26px minmax(0, 1fr) auto; gap: 10px; align-items: center; padding: 6px 4px 6px 6px; border-radius: var(--r-sm); cursor: pointer; }
.fs-mini:hover { background: #f4f8f9; }
.fs-mini b { display: block; font-size: 13px; font-weight: 600; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fs-mini small { display: block; font-size: 11.5px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fs-mini .r { display: flex; align-items: center; gap: 5px; }
/* Действия строки блока — видны сразу, а не по наведению: «не вижу
   возможности скрыть от заказчика или удалить» (владелец 2026-09-23).
   Приглушены, пока строку не трогают, чтобы список не пестрел кнопками. */
.fs-mini .r .icon-btn { width: 26px; height: 26px; min-width: 26px; background: none; color: var(--muted); }
.fs-mini .r .icon-btn svg { width: 15px; height: 15px; }
.fs-mini:hover .r .icon-btn { color: var(--text-3); }
.fs-mini .r .icon-btn:hover { background: #d9f2ef; color: var(--accent-dark); }
.fs-mini .r .icon-btn.danger:hover { background: var(--danger-bg); color: var(--danger); }
/* Прослушать голосовое — строкой под именем файла или сообщения. */
.voice-player { display: block; width: 100%; max-width: 320px; height: 34px; margin-top: 6px; }
.voice-player-fail { display: block; margin-top: 6px; font-size: 11.5px; color: var(--danger); }
.fs-vnone .voice-player { max-width: 380px; width: 380px; height: 40px; }
.fs-cand-link { background: none; border: 0; padding: 0; font: inherit; color: var(--accent); cursor: pointer; text-align: left; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: baseline; }
.fs-cand-link:hover { text-decoration: underline; }
.video-player { display: block; width: 100%; max-width: 360px; max-height: 240px; margin-top: 6px; background: #000; border-radius: 8px; }
.fs-prev-media { padding: 10px; }
.fs-prev-media .video-player, .fs-prev-media .voice-player { max-width: 100%; margin: 0; }
.fs-vvideo .video-player { max-width: min(960px, 100%); width: auto; max-height: 72vh; margin: 0; }
.fs-inline-drop { margin-top: 10px; padding: 12px; border: 1.5px dashed var(--field); border-radius: var(--r-md); text-align: center; font-size: 12.5px; color: var(--muted); cursor: pointer; }
.fs-inline-drop:hover { border-color: var(--accent); color: var(--accent-dark); background: var(--accent-soft); }

/* Запрос документов: чек-лист с ходом (прототип design/files-screen.html,
   перенесено дословно 2026-09-23). */
.fs-req { border: 1px solid var(--line-2); border-radius: var(--r-md); padding: 11px 12px; margin-top: 8px; background: #fff; }
.fs-req-h { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 700; color: var(--text); }
.fs-req-h .grow { flex: 1; min-width: 0; }
.fs-req .bar { margin: 8px 0 6px; height: 6px; }
.fs-ri { display: flex; align-items: center; gap: 8px; padding: 5px 0; font-size: 12.5px; color: var(--text-2); border-top: 1px dashed var(--line-2); }
.fs-ri:first-of-type { border-top: 0; }
.fs-ri .grow { flex: 1; min-width: 0; }
.fs-ri .ok { color: var(--accent-dark); font-weight: 800; }
.fs-ri .wait { color: var(--muted); }
.fs-ri .bad { color: var(--danger); font-weight: 700; }
.fs-dot { width: 16px; height: 16px; border-radius: 999px; flex: none; display: inline-flex; align-items: center; justify-content: center; border: 1.5px solid var(--field); }
.fs-dot.ok { background: var(--accent); border-color: var(--accent); }
.fs-dot.ok::after { content: ""; width: 6px; height: 3px; border-left: 2px solid #fff; border-bottom: 2px solid #fff; transform: rotate(-45deg) translate(1px, -1px); }
.fs-dot.up { border-color: #1d5bb8; background: #e5eefc; }
.fs-dot.bad { border-color: var(--danger); background: var(--danger-bg); }
/* Причина возврата под пунктом — её видит заказчик. */
.fs-ri .fs-why { display: block; margin-top: 2px; color: var(--danger); font-size: 12px; }

.fs-att { display: flex; align-items: center; gap: 9px; padding: 7px 9px; border-radius: var(--r-sm); background: #fff; border: 1px solid var(--line-2); margin-top: 6px; }
.fs-att .grow { flex: 1; min-width: 0; }
.fs-att b { display: block; font-size: 12.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fs-att small { color: var(--muted); font-size: 11px; }

/* ── окно «Прикрепить» ───────────────────────────────────────────────── */
.modal.fs-pick { width: min(760px, 100%); }
.fs-pick-list { max-height: 340px; overflow-y: auto; border: 1px solid var(--line-2); border-radius: var(--r-md); }
.fs-pick-row { display: grid; grid-template-columns: 22px 28px minmax(0, 1fr) auto; gap: 10px; align-items: center; padding: 8px 11px; border-top: 1px solid var(--line); cursor: pointer; font-size: 13px; }
.fs-pick-row:first-child { border-top: 0; }
.fs-pick-row:hover { background: #f7fafb; }
.fs-pick-row.on { background: var(--accent-soft); }
.fs-pick-row small { display: block; font-size: 11.5px; color: var(--muted); }
.fs-pick-row input { accent-color: var(--accent); width: 15px; height: 15px; }

.kab-doc { display: grid; grid-template-columns: 34px minmax(0, 1fr) auto; gap: 12px; align-items: center; padding: 11px 4px; border-top: 1px solid var(--line); }
.kab-doc:first-of-type { border-top: 0; }
.kab-doc b { display: block; font-size: 13.5px; }
.kab-doc small { display: block; font-size: 12px; color: var(--muted); margin-top: 2px; }
.kab-doc .acts { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; justify-content: flex-end; }
.kab-up { display: inline-flex; align-items: center; gap: 6px; }

@media (max-width: 1500px) {
  .fs { grid-template-columns: 220px minmax(0, 1fr); }
  .fs-frow { grid-template-columns: 24px 34px minmax(0, 1fr) 160px 150px; }
  .fs-frow .fs-fwhen { display: none; }
}
@media (max-width: 1180px) {
  .fs, .fs-two, .fs-three, .fs-state { grid-template-columns: 1fr; }
  .fs-h { height: auto; min-height: 0; }
  .fs-frow { grid-template-columns: 24px 34px minmax(0, 1fr); }
  .fs-frow .fs-fcard, .fs-frow > .fs-stcol { grid-column: 3; }
}

/* ── второй заход: наша страница по механике кабинета ─────────────────── */
.fs-narrow { max-width: 1180px; }
.fs-name { display: block; padding: 0; border: 0; background: none; font: inherit; font-size: 13.5px; font-weight: 700; color: var(--text); text-align: left; cursor: pointer; overflow-wrap: anywhere; }
.fs-name:hover { color: var(--accent-dark); text-decoration: underline; text-underline-offset: 3px; }
.fs-our { border-left: 3px solid transparent; padding-left: 8px; margin-left: -8px; }
.fs-our.fresh { border-left-color: var(--accent-500); }
.fs-acc-btn { border: 0; cursor: pointer; font: inherit; font-size: 10.5px; font-weight: 800; padding: 4px 9px; }
.fs-acc-btn.team { background: #fff; box-shadow: inset 0 0 0 1px var(--line-2); }
/* Наведение — вуалью поверх заливки, а не filter: тот темнил и текст, и
   значок, и чип выглядел грязным. */
.fs-acc-btn:hover { box-shadow: inset 0 0 0 999px rgba(4, 40, 38, 0.06); }
.fs-acc-btn.team:hover { box-shadow: inset 0 0 0 1px var(--line-2), inset 0 0 0 999px rgba(4, 40, 38, 0.05); }
.fs-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 14px; }
.fs-tile { text-align: left; cursor: pointer; font: inherit; color: inherit; border: 0; }
.fs-tile:hover { box-shadow: 0 0 0 2px var(--accent-soft), var(--shadow-md); }
.fs-tile h4 { margin: 2px 0 0; font-size: 17px; }
/* В app.css поля и списки растянуты на всю ширину — в строках прототипа
   они должны занимать своё место, иначе подпись рядом сжимается в столбик. */
.fs-list-h select, .fs-list-h input, .fs-frow input, .fs-pick-row input, .fs-acc-opt input, .fs-row-g input[type=checkbox] { width: auto; flex: none; }

/* ── третий заход: просмотр и папки ──────────────────────────────────── */
.fs-thumb { padding: 0; border: 0; background: none; cursor: pointer; display: inline-flex; }
.fs-thumb:hover .fs-ext { filter: brightness(1.08); box-shadow: 0 0 0 2px var(--accent-soft); }
.kab-doc.ent { grid-template-columns: 16px 34px minmax(0, 1fr) auto; }
.kab-doc.ent > input[type=checkbox] { width: 15px; height: 15px; accent-color: var(--accent); margin: 0; }
.kab-doc.picked { background: var(--accent-soft); }
.kab-doc[draggable=true] { cursor: grab; }
.fs-infold { display: inline-flex; align-items: center; gap: 3px; color: var(--accent-dark); font-weight: 700; }
.fs-infold svg { width: 12px; height: 12px; }

.fs-ent { display: grid; grid-template-columns: 250px minmax(0, 1fr); gap: 14px; align-items: start; }
.fs-fcol { position: sticky; top: 10px; padding: 8px 6px; }
.fs-fcol .fs-b { gap: 7px; }
.fs-fcol .fs-b .lb .ic { margin-right: 6px; vertical-align: -3px; }
.fs-fcol .fs-b .n .fs-acc svg { width: 11px; height: 11px; }
.fs-newf { color: var(--accent-dark); margin-top: 4px; }
.fs-newf svg { width: 14px; height: 14px; vertical-align: -2px; }
body.fs-dragging [data-dropfolder] { outline: 1.5px dashed var(--accent); outline-offset: -2px; }
.fs-b.drop-on { background: var(--accent-soft); outline: 2px solid var(--accent) !important; }
@media (max-width: 900px) { .fs-ent { grid-template-columns: 1fr; } .fs-fcol { position: static; } }

.fs-viewer { position: fixed; inset: 0; z-index: 90; background: rgba(17, 24, 28, .94); display: flex; flex-direction: column; color: #e8edf0; }
.fs-vbar { display: flex; align-items: center; gap: 12px; padding: 10px 16px; background: #1b2429; border-bottom: 1px solid #2c373d; }
.fs-vbar b { display: block; font-size: 14px; color: #fff; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fs-vsub { font-size: 12px; color: #9fb0b8; margin-top: 2px; }
.fs-vacts { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
.fs-vacts .icon-btn { background: #26323a; color: #dfe7eb; border-color: #33424a; }
/* В тёмном просмотре общий светлый круг наведения вспыхивал пятном — здесь
   наведение остаётся в тёмной гамме. */
.fs-vacts .icon-btn:hover { background: #33424a; color: #fff; }
.fs-vx { border: 0; background: #26323a; color: #fff; width: 34px; height: 34px; border-radius: 8px; font-size: 22px; line-height: 1; cursor: pointer; }
.fs-vx:hover { background: #33424a; }
.fs-vbody { flex: 1; min-height: 0; display: grid; grid-template-columns: 64px minmax(0, 1fr) 64px; align-items: center; }
.fs-vpages { height: 100%; overflow-y: auto; padding: 24px 10px; display: flex; flex-direction: column; align-items: center; gap: 18px; }
.fs-vpage { width: min(760px, 100%); flex: none; }
.fs-vpage.img { width: min(900px, 100%); }
.fs-varr { justify-self: center; width: 46px; height: 46px; border-radius: 999px; border: 0; background: #26323a; color: #fff; font-size: 28px; line-height: 1; cursor: pointer; }
.fs-varr:hover:not(:disabled) { background: var(--accent); }
.fs-varr:disabled { opacity: .25; cursor: default; }
.fs-vstrip { display: flex; gap: 8px; padding: 10px 16px; overflow-x: auto; background: #1b2429; border-top: 1px solid #2c373d; }
.fs-vstrip button { flex: none; display: flex; align-items: center; gap: 7px; max-width: 220px; padding: 6px 10px; border-radius: 8px; border: 1px solid #33424a; background: #222d33; color: #cfd9de; font: inherit; font-size: 12px; cursor: pointer; }
.fs-vstrip button span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fs-vstrip button.on { border-color: var(--accent); background: #24403a; color: #fff; }
.fs-vnote { position: absolute; left: 50%; bottom: 70px; transform: translateX(-50%); font-size: 12px; background: rgba(0, 0, 0, .55); padding: 5px 12px; border-radius: 999px; color: #f3c9c9; }
@media (max-width: 700px) { .fs-vbody { grid-template-columns: 36px minmax(0, 1fr) 36px; } .fs-varr { width: 32px; height: 32px; font-size: 20px; } .fs-vbar { flex-wrap: wrap; } }

/* ── своё продуктовой версии: чего в прототипе не было ─────────────────── */
.fs-cnt { font-weight: 600; text-transform: none; letter-spacing: 0; }
.fs-cap-n { text-transform: none; letter-spacing: 0; font-weight: 600; }
.fs-sw { gap: 6px; font-size: 12.5px; color: var(--text-2); }
.fs-cand { text-transform: none; letter-spacing: 0; font-size: 13.5px; color: var(--text); }
.fs-chk { gap: 5px; font-size: 13px; margin-right: 10px; }
.fs-search { flex: 1; padding: 7px 12px; border-radius: 999px; border: 1.5px solid var(--field); background: #fff; font: inherit; font-size: 13px; }
.fs-list-h input[type=checkbox] { width: 15px; height: 15px; accent-color: var(--accent); }
.fs-trow { cursor: default; }
.fs-stcol { gap: 5px; }
.fs-subf { padding: 0 0 12px; border-bottom: 0; }
.fs-b:disabled { opacity: .5; cursor: not-allowed; }
.fs-dropline { cursor: pointer; }
/* Кабинет заказчика (client.html, режим компании) — из прототипа
   design/files-screen.html без рамки браузера: шапка во всю ширину, тело
   по центру, строки вакансий во вкладке «Подбор». */
.kab-top { display: flex; align-items: center; gap: 14px; padding: 14px 22px; background: #fff; border-bottom: 1px solid var(--line-2); flex-wrap: wrap; }
.kab-logo { width: 34px; height: 34px; border-radius: 10px; background: linear-gradient(140deg, var(--accent-500), var(--accent-dark)); color: #fff; font-weight: 800; display: flex; align-items: center; justify-content: center; flex: none; }
.kab-top .grow { flex: 1; min-width: 0; }
.kab-top h3 { margin: 0; font-size: 17px; }
.kab-body { max-width: 1120px; margin: 0 auto; padding: 22px 24px 60px; }
.kab-vac { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px; align-items: center; padding: 11px 0; border-top: 1px solid var(--line); }
.kab-vac:first-of-type { border-top: 0; }
.kab-vac b { font-size: 14px; }
@media (max-width: 640px) {
  .kab-body { padding: 16px 16px 48px; }
  .kab-vac { grid-template-columns: minmax(0, 1fr); }
}
/* Выбор карточки с поиском (screen-files.js, fsCardPickHTML): закрытый — как
   select системы, раскрытый — поиск и найденное по группам. */
.fs-cpick { position: relative; }
.fs-cpick-btn {
  width: 100%; text-align: left; padding: 9px 34px 9px 12px;
  border: 1.5px solid var(--field); border-radius: var(--r-md); background-color: #fff;
  font: inherit; font-size: 14px; color: var(--text); cursor: pointer;
  overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='11' height='7' viewBox='0 0 11 7'%3E%3Cpath d='M1 1l4.5 4.5L10 1' fill='none' stroke='%236b8592' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 13px center;
}
.fs-cpick-btn:hover { border-color: #c6d5dc; }
.fs-cpick.open .fs-cpick-btn, .fs-cpick-btn:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(15, 118, 110, 0.14); }
.fs-cpick-pop {
  position: absolute; left: 0; right: 0; top: calc(100% + 4px); z-index: 40;
  background: #fff; border: 1px solid var(--line-2); border-radius: var(--r-md);
  box-shadow: 0 12px 32px rgba(15, 40, 50, 0.16); padding: 8px;
}
.fs-cpick-list { max-height: 280px; overflow: auto; margin-top: 6px; }
.fs-cpick-cap { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); padding: 8px 8px 4px; }
.fs-cpick-it { display: block; width: 100%; text-align: left; border: 0; background: transparent; padding: 7px 8px; border-radius: var(--r-sm); font: inherit; font-size: 13.5px; color: var(--text); cursor: pointer; }
.fs-cpick-it b { font-weight: 600; }
.fs-cpick-it small { display: block; color: var(--muted); font-size: 12px; }
.fs-cpick-it:hover, .fs-cpick-it.act { background: var(--soft); }
.fs-cpick-it.on b { color: var(--accent-dark); }
.fs-cpick-foot { font-size: 12px; color: var(--muted-2); padding: 8px 8px 2px; }
/* Пароль клиента в окне выдачи: поле и «другой» одной строкой. */
.acc-pwd { display: flex; gap: 6px; align-items: center; }
.acc-pwd input { flex: 1; min-width: 0; font-family: ui-monospace, SFMono-Regular, Consolas, monospace; letter-spacing: 0.02em; }
.acc-pwd .btn { flex: none; }
/* HTML в просмотре — белый лист: у письма свой фон, а сквозь рамку просвечивал бы тёмный. */
.fs-vhtml { background: #fff; }
/* Кабинет заказчика в карточке клиента: кружок с инициалами контакта. */
.fs-remq { display: block; margin-top: 4px; font-size: 12.5px; color: var(--text-2); white-space: pre-wrap; }
.kab-me { display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--text-3); }
.kab-me .av { width: 30px; height: 30px; border-radius: 999px; background: #e5eefc; color: #1d5bb8; font-weight: 800; font-size: 12px; display: flex; align-items: center; justify-content: center; }
.fs-inline-drop.fs-dropping, .fs-dropline.fs-dropping { border-color: var(--accent); color: var(--accent-dark); background: var(--accent-soft); }
.fs-upl { display: flex; flex-direction: column; gap: 0; margin-bottom: 12px; max-height: 210px; overflow-y: auto; }
.fs-pick-row { width: 100%; text-align: left; border: 0; background: #fff; font: inherit; grid-template-columns: 22px minmax(0, 1fr) auto; }
.fs-pick-row svg { width: 16px; height: 16px; color: var(--muted-2); }
.fs-panel textarea { width: 100%; margin-top: 8px; padding: 8px 10px; border-radius: var(--r-sm); border: 1px solid var(--field); font: inherit; font-size: 13px; resize: vertical; }
.fs-panel .field select, .fs-panel .field input { width: 100%; }
/* Настоящий просмотр вместо листа-макета: PDF — встроенной читалкой
   браузера, картинка — как есть. */
.fs-pframe { width: 100%; height: 560px; border: 0; border-radius: 4px; background: #fff; }
.fs-pimg { max-width: 100%; max-height: 560px; border-radius: 4px; display: block; }
.fs-vpages { justify-content: center; }
.fs-vframe { width: min(980px, 100%); height: 100%; min-height: 60vh; flex: 1; border: 0; border-radius: 4px; background: #fff; box-shadow: 0 6px 24px rgba(0, 0, 0, .35); }
.fs-vimg { max-width: 100%; max-height: 100%; object-fit: contain; border-radius: 4px; box-shadow: 0 6px 24px rgba(0, 0, 0, .35); }
.fs-vnone { margin: auto; display: flex; flex-direction: column; align-items: center; gap: 10px; text-align: center; color: #cfd9de; font-size: 13px; max-width: 420px; }
.fs-vnone b { color: #fff; font-size: 15px; overflow-wrap: anywhere; }
.fs-vnone .fs-ext { width: 48px; height: 58px; font-size: 12px; }
.fs-viewer .fs-st { font-size: 11px; }

/* ── Вход: цветной фон, карточка и приветствие (web/auth-hello.js) ──────────
   Владелец 2026-09-24: «страницу входа сделаем более красочной и современной».
   Колонка формы по-прежнему .pub .pub-auth: фон лежит под ней fixed-слоем, и
   ширины, которые стережёт tests/clienthh.js, не меняются. Всё движение
   гасится при prefers-reduced-motion. */
:root {
  --au-1: #17a396;
  --au-2: #3b82f6;
  --au-3: #f59e0b;
  --au-4: #8b5cf6;
}
.au-page { background: #0b1f24; }
.au-bg {
  position: fixed; inset: 0; z-index: -1; overflow: hidden; pointer-events: none;
  background:
    radial-gradient(1200px 700px at 50% 120%, #0f766e 0%, rgba(15, 118, 110, 0) 60%),
    linear-gradient(160deg, #0b2a30 0%, #0d3b3f 45%, #12303f 100%);
}
.au-bg::after {
  content: ""; position: absolute; inset: 0;
  background-image: radial-gradient(rgba(255, 255, 255, 0.09) 1px, transparent 1px);
  background-size: 22px 22px;
  -webkit-mask-image: radial-gradient(ellipse at center, #000 30%, transparent 75%);
  mask-image: radial-gradient(ellipse at center, #000 30%, transparent 75%);
}
.au-blob {
  position: absolute; border-radius: 50%; filter: blur(70px); opacity: 0.55;
  animation: au-drift 18s ease-in-out infinite alternate;
}
.au-blob.b1 { width: 520px; height: 520px; background: var(--au-1); top: -140px; left: -120px; }
.au-blob.b2 { width: 460px; height: 460px; background: var(--au-2); bottom: -160px; right: -100px; animation-duration: 22s; animation-delay: -6s; }
.au-blob.b3 { width: 320px; height: 320px; background: var(--au-3); top: 18%; right: 12%; opacity: 0.32; animation-duration: 26s; animation-delay: -12s; }
.au-blob.b4 { width: 280px; height: 280px; background: var(--au-4); bottom: 12%; left: 10%; opacity: 0.35; animation-duration: 20s; animation-delay: -3s; }
@keyframes au-drift {
  0% { transform: translate(0, 0) scale(1); }
  50% { transform: translate(60px, 40px) scale(1.12); }
  100% { transform: translate(-40px, 70px) scale(0.94); }
}

.au-brand { display: flex; align-items: center; justify-content: center; gap: 10px; margin-bottom: 22px; color: #fff; }
.au-mark {
  width: 36px; height: 36px; border-radius: 11px; display: grid; place-items: center;
  background: conic-gradient(from 200deg, var(--au-1), var(--au-2), var(--au-4), var(--au-3), var(--au-1));
  box-shadow: 0 8px 24px -8px rgba(23, 163, 150, 0.8);
  animation: au-spin 14s linear infinite;
}
.au-mark span { width: 14px; height: 14px; border-radius: 5px; background: #0d3b3f; animation: au-spin 14s linear infinite reverse; }
.au-name { font-weight: 800; font-size: 20px; letter-spacing: -0.02em; }
@keyframes au-spin { to { transform: rotate(360deg); } }

.card.au-card {
  position: relative; padding: 28px 26px 24px; border-radius: var(--r-xl);
  background: rgba(255, 255, 255, 0.95);
  box-shadow: 0 40px 80px -30px rgba(0, 0, 0, 0.55), inset 0 0 0 1px rgba(255, 255, 255, 0.4);
  animation: au-rise 0.7s cubic-bezier(0.2, 0.8, 0.2, 1) both;
}
.au-card::before {
  content: ""; position: absolute; left: 22px; right: 22px; top: 0; height: 3px; border-radius: 0 0 3px 3px;
  background: linear-gradient(90deg, var(--au-1), var(--au-2), var(--au-4), var(--au-3));
  background-size: 200% 100%; animation: au-slide 6s linear infinite;
}
@keyframes au-slide { to { background-position: 200% 0; } }
@keyframes au-rise { from { opacity: 0; transform: translateY(18px) scale(0.98); } }
.au-card > * { animation: au-rise 0.6s cubic-bezier(0.2, 0.8, 0.2, 1) both; }
.au-card > :nth-child(1) { animation-delay: 0.08s; }
.au-card > :nth-child(2) { animation-delay: 0.14s; }
.au-card > :nth-child(3) { animation-delay: 0.2s; }
.au-card > :nth-child(4) { animation-delay: 0.26s; }
.au-card > :nth-child(5) { animation-delay: 0.32s; }
.au-card > :nth-child(6) { animation-delay: 0.38s; }
.au-card > :nth-child(n+7) { animation-delay: 0.44s; }
/* Перерисовка после ошибки — без появления, только встряска. */
.au-card.again, .au-card.again > * { animation: none; }
.au-card.again.au-shake { animation: au-shake 0.42s cubic-bezier(0.36, 0.07, 0.19, 0.97); }
@keyframes au-shake { 20%, 60% { transform: translateX(-8px); } 40%, 80% { transform: translateX(8px); } }

.au-cap { font-size: 12px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--accent-500); }
.au-card h2 { font-size: 26px; margin-top: 4px; }
.au-sub { color: var(--muted); margin-top: 6px; }
.au-card .field { margin-top: 16px; position: relative; }
.au-card .field label { font-weight: 700; color: var(--text-2); }
.au-card .field input {
  height: 46px; padding: 0 14px; border-radius: var(--r-md); font-size: 15px;
  border: 1.5px solid var(--field); background: #f7fafb;
  transition: border-color 0.2s, box-shadow 0.2s, background 0.2s;
}
.au-card .field input:focus { outline: none; border-color: var(--accent-500); background: #fff; box-shadow: 0 0 0 4px rgba(23, 163, 150, 0.15); }
.au-card .field input.au-pass { padding-right: 90px; }
.au-eye {
  position: absolute; right: 8px; bottom: 7px; height: 32px; padding: 0 10px; border: 0; border-radius: var(--r-sm);
  background: transparent; color: var(--muted); font: 600 12px Manrope, "Segoe UI", sans-serif; cursor: pointer;
}
.au-eye:hover { background: var(--accent-soft); color: var(--accent-dark); }
.au-err { margin-top: 14px; padding: 10px 12px; border-radius: 10px; background: var(--danger-bg); color: var(--danger); font-weight: 600; font-size: 13px; }
.au-card .btn.au-go {
  justify-content: center; height: 48px; margin-top: 20px; font-size: 15px;
  background: linear-gradient(120deg, var(--accent) 0%, var(--accent-500) 50%, #2f8fd8 100%);
  background-size: 180% 100%; transition: background-position 0.5s, transform 0.15s;
  box-shadow: 0 14px 28px -14px rgba(15, 118, 110, 0.9);
}
.au-card .btn.au-go:hover:not(:disabled) { background: linear-gradient(120deg, var(--accent) 0%, var(--accent-500) 50%, #2f8fd8 100%); background-size: 180% 100%; background-position: 100% 0; }
.au-card .btn.au-go:active { transform: scale(0.985); }
.au-card .btn.au-go.busy { font-size: 0; }
.au-card .btn.au-go.busy::after {
  content: ""; width: 18px; height: 18px; border-radius: 50%;
  border: 2.5px solid rgba(255, 255, 255, 0.35); border-top-color: #fff; animation: au-spin 0.7s linear infinite;
}
.au-card .btn.au-go.busy:disabled { background: linear-gradient(120deg, var(--accent), var(--accent-500)); color: #fff; }
.au-foot { margin-top: 14px; color: var(--muted); font-size: 12.5px; }

.au-hello {
  position: fixed; inset: 0; z-index: 1000; display: grid; place-items: center; padding: 16px;
  text-align: center; color: #fff; pointer-events: none; opacity: 0;
}
.au-hello.on { opacity: 1; pointer-events: auto; cursor: pointer; }
.au-hello.out { opacity: 0; transition: opacity 0.5s; }
.au-wash {
  position: absolute; left: var(--x, 50%); top: var(--y, 50%); width: 10px; height: 10px; border-radius: 50%;
  transform: translate(-50%, -50%) scale(0);
  background: radial-gradient(circle, #14958a 0%, #0f766e 45%, #0b3a45 100%);
}
.au-hello.on .au-wash { animation: au-wash 0.9s cubic-bezier(0.7, 0, 0.2, 1) forwards; }
@keyframes au-wash { to { transform: translate(-50%, -50%) scale(400); } }
.au-inner { position: relative; max-width: 560px; }
.au-check {
  width: 84px; height: 84px; margin: 0 auto 22px; border-radius: 50%;
  background: rgba(255, 255, 255, 0.14); display: grid; place-items: center; opacity: 0; transform: scale(0.6);
}
.au-hello.on .au-check { animation: au-pop 0.5s 0.55s cubic-bezier(0.2, 1.4, 0.4, 1) forwards; }
.au-check svg path { stroke-dasharray: 40; stroke-dashoffset: 40; }
.au-hello.on .au-check svg path { animation: au-draw 0.45s 0.85s ease-out forwards; }
@keyframes au-pop { to { opacity: 1; transform: scale(1); } }
@keyframes au-draw { to { stroke-dashoffset: 0; } }
.au-title { font-size: clamp(28px, 6vw, 44px); font-weight: 800; letter-spacing: -0.03em; line-height: 1.1; }
.au-w { display: inline-block; opacity: 0; transform: translateY(16px); }
.au-hello.on .au-w { animation: au-word 0.5s cubic-bezier(0.2, 0.8, 0.2, 1) forwards; }
@keyframes au-word { to { opacity: 1; transform: none; } }
.au-who { margin-top: 12px; font-size: 16px; color: #cdeee9; opacity: 0; }
.au-chips { margin-top: 18px; display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; opacity: 0; }
.au-chip { padding: 7px 13px; border-radius: 999px; background: rgba(255, 255, 255, 0.14); font-weight: 600; font-size: 13px; }
.au-hello.on .au-who { animation: au-fade 0.5s 1.35s forwards; }
.au-hello.on .au-chips { animation: au-fade 0.5s 1.55s forwards; }
.au-bar { width: 160px; height: 3px; margin: 26px auto 0; border-radius: 3px; background: rgba(255, 255, 255, 0.18); overflow: hidden; opacity: 0; }
.au-bar i { display: block; height: 100%; width: 0; background: #fff; border-radius: 3px; }
.au-hello.on .au-bar { animation: au-fade 0.3s 1.6s forwards; }
.au-hello.on .au-bar i { animation: au-load 1.3s 1.7s ease-in-out forwards; }
@keyframes au-fade { to { opacity: 1; } }
@keyframes au-load { to { width: 100%; } }
.au-spark { position: absolute; width: 8px; height: 8px; border-radius: 2px; top: 50%; left: 50%; opacity: 0; }
.au-hello.on .au-spark { animation: au-burst 1.2s 1s cubic-bezier(0.1, 0.7, 0.3, 1) forwards; }
@keyframes au-burst {
  0% { opacity: 1; transform: translate(-50%, -50%) rotate(0); }
  100% { opacity: 0; transform: translate(calc(-50% + var(--dx, 0px)), calc(-50% + var(--dy, 0px))) rotate(var(--r, 0deg)); }
}

@media (max-width: 480px) {
  .card.au-card { padding: 24px 18px 20px; }
  .au-card h2 { font-size: 23px; }
  .au-blob { filter: blur(50px); }
}
@media (prefers-reduced-motion: reduce) {
  .au-bg *, .au-brand *, .au-card, .au-card *, .au-card::before, .au-hello, .au-hello * {
    animation-duration: 0.01ms !important; animation-delay: 0s !important;
    animation-iteration-count: 1 !important; transition: none !important;
  }
}

/* ══════════════════════════════════════════════════════════════════════════
   СВОЁ ПРОТОТИПА «Контроль услуги». Выше — web/app.css целиком, без правок.
   Здесь только то, чего в системе нет: трек этапов, светофор, очередь дел,
   чек-лист выезда для телефона, матрица RACI, кабинет санатория и полоса
   «Прототип». Префикс sc- — чтобы не пересечься с классами системы.
   ══════════════════════════════════════════════════════════════════════════ */

body { height: 100vh; overflow: hidden; }
.app { height: calc(100vh - 44px); }

.proto {
  height: 44px; display: flex; align-items: center; gap: 10px; padding: 0 14px;
  background: repeating-linear-gradient(135deg, #2b2f36 0 12px, #30353d 12px 24px); color: #e9edf1;
  font-size: 13px; overflow-x: auto; white-space: nowrap;
}
.proto b { color: #ffd166; letter-spacing: .04em; font-size: 11px; text-transform: uppercase; }
.proto .sep { width: 1px; height: 22px; background: #4a515b; flex: none; }
.proto button {
  border: 0; border-radius: 999px; padding: 5px 11px; cursor: pointer;
  background: #444b55; color: #e9edf1; font-size: 12.5px; font-weight: 600; font-family: inherit;
}
.proto button.on { background: #ffd166; color: #1b1f24; }
.proto label { display: inline-flex; align-items: center; gap: 6px; color: #c9d1d9; }
.proto select, .proto input { background: #444b55; border: 0; border-radius: 8px; padding: 4px 6px; color: #e9edf1; font: inherit; font-size: 12.5px; color-scheme: dark; }

/* рабочая область: предел 1280px системы снят — экраны прототипа обязаны
   жить и на телефоне (критерий приёмки брифа). */
.sc { min-width: 0; padding: 14px 30px 60px; max-width: 1400px; }
.sc .head { grid-template-columns: minmax(0, 1fr) auto; }
.sc .head-actions { grid-column: 2; }
.sc .head h2 { font-size: 25px; }
.sc-sub { font-size: 13px; color: var(--muted); margin-top: 4px; }
.sc-sub b { color: var(--text-2); }

.sc-note { font-size: 12.5px; line-height: 1.55; color: var(--muted); background: var(--soft); border-radius: var(--r-sm); padding: 9px 12px; }
.sc-note b { color: var(--text-2); }
.sc-note.warn { color: var(--warn); background: var(--warn-bg); }
.sc-note.warn b { color: var(--warn); }
.sc-note.bad { color: var(--danger); background: var(--danger-bg); }
.sc-note.bad b { color: var(--danger); }
.sc-note.ok { color: var(--accent-dark); background: var(--accent-soft); }
.sc-note.ok b { color: var(--accent-dark); }

.sc-grid2 { display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr); gap: 16px; align-items: start; }
.sc-grid3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; }
.sc-stack { display: flex; flex-direction: column; gap: 16px; }
.sc-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.sc-sp { flex: 1; }
.sc-mt { margin-top: 16px; }
.sc-num { font-variant-numeric: tabular-nums; }
.sc-link { border: 0; background: none; padding: 0; font: inherit; color: var(--accent-dark); font-weight: 700; cursor: pointer; text-align: left; }
.sc-link:hover { text-decoration: underline; }
.sc-muted { color: var(--muted); }
.sc-bad { color: var(--danger); }

/* ── трек этапов ── */
.sc-track { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 6px; }
.sc-st { position: relative; padding: 10px 12px 11px; border-radius: var(--r-md); background: #fff; box-shadow: var(--shadow-sm); min-width: 0; }
.sc-st .t { font-size: 13px; font-weight: 800; letter-spacing: -0.01em; }
.sc-st .d { font-size: 11.5px; color: var(--muted); margin-top: 2px; }
.sc-st .r { font-size: 11.5px; color: var(--text-3); margin-top: 6px; line-height: 1.35; }
.sc-st .pay { display: inline-block; margin-top: 6px; }
.sc-st.done { background: var(--accent-soft); box-shadow: none; }
.sc-st.done .t::before { content: "✓ "; color: var(--accent); }
.sc-st.now { outline: 2px solid var(--accent); }
.sc-st.now::after { content: "сейчас"; position: absolute; top: 9px; right: 10px; font-size: 10px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: var(--accent); }
.sc-bar { height: 6px; border-radius: 3px; background: rgba(22, 48, 58, 0.08); overflow: hidden; margin-top: 8px; }
.sc-bar i { display: block; height: 100%; background: var(--accent-700); }
.sc-bar.bad i { background: var(--danger); }
.sc-bar.warn i { background: #d99a06; }

/* ── плитки ── */
.sc-kpis { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; }
.sc-kpi { background: #fff; border-radius: var(--r-md); box-shadow: var(--shadow-sm); padding: 13px 15px; border: 0; text-align: left; font: inherit; color: inherit; cursor: pointer; min-width: 0; }
.sc-kpi:hover { box-shadow: var(--shadow-md); }
.sc-kpi .cap { font-size: 10px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: var(--muted); }
.sc-kpi .val { margin-top: 5px; font-size: 24px; font-weight: 800; letter-spacing: -0.03em; }
.sc-kpi .val small { font-size: 14px; font-weight: 700; color: var(--muted); }
.sc-kpi .sub { font-size: 12px; color: var(--muted); margin-top: 2px; }
.sc-kpi.bad .val { color: var(--danger); }
.sc-kpi.warn .val { color: var(--warn); }
.sc-kpi.ok .val { color: var(--accent-dark); }

.sc-side-foot { margin-top: auto; }
.sc-side-card { background: rgba(255, 255, 255, .06); border-radius: 12px; padding: 10px 12px; }

/* светофор */
.sc-light { display: inline-block; width: 11px; height: 11px; border-radius: 999px; flex: none; }
.sc-light.green { background: var(--accent-500); }
.sc-light.yellow { background: #e0a410; }
.sc-light.red { background: var(--danger); }

/* ── ехать / не ехать ── */
.sc-go { border-radius: var(--r-lg); padding: 16px 18px; background: #fff; box-shadow: var(--shadow-sm); }
.sc-go .v { font-size: 20px; font-weight: 800; letter-spacing: -0.02em; display: flex; align-items: center; gap: 9px; }
.sc-go.no .v { color: var(--danger); }
.sc-go.yes .v { color: var(--accent-dark); }
.sc-go ul { margin: 10px 0 0 18px; font-size: 13px; color: var(--text-2); }
.sc-go li { margin: 3px 0; }
.sc-meter { display: grid; grid-template-columns: 130px minmax(0, 1fr) 64px; gap: 10px; align-items: center; font-size: 12.5px; margin-top: 10px; }
.sc-meter .sc-bar { margin: 0; position: relative; height: 8px; }
.sc-meter .sc-bar b { position: absolute; top: -3px; bottom: -3px; width: 2px; background: var(--text-2); }
.sc-meter .n { text-align: right; font-weight: 700; }

/* ── три задачи собственника ── */
.sc-own { background: #fff; border-radius: var(--r-lg); box-shadow: var(--shadow-sm); padding: 15px 16px; min-width: 0; }
.sc-own .cap { font-size: 10px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: var(--muted); }
.sc-own .big { font-size: 24px; font-weight: 800; letter-spacing: -0.03em; margin-top: 4px; }
.sc-own .ln { display: flex; justify-content: space-between; gap: 10px; font-size: 12.5px; padding: 6px 0; border-top: 1px solid var(--line); }
.sc-own .ln:first-of-type { margin-top: 8px; }
.sc-own .ln span { color: var(--muted); }
.sc-own .ln b { white-space: nowrap; }

/* ── очередь «нужно сделать» и строки-дела ── */
.sc-q { display: grid; grid-template-columns: 22px minmax(0, 1fr) auto; gap: 10px; align-items: center; padding: 10px 2px; border-top: 1px solid var(--line); }
.sc-q:first-of-type { border-top: 0; }
.sc-q > .ic { width: 22px; height: 22px; border-radius: 7px; display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 800; background: var(--soft); color: var(--text-3); }
.sc-q > .ic.bad { background: var(--danger-bg); color: var(--danger); }
.sc-q > .ic.warn { background: var(--warn-bg); color: var(--warn); }
.sc-q > .ic.ok { background: var(--accent-soft); color: var(--accent-dark); }
.sc-q b { display: block; font-size: 13.5px; font-weight: 700; }
.sc-q small { display: block; font-size: 12px; color: var(--muted); margin-top: 2px; }
.sc-q .acts { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; justify-content: flex-end; }
.sc-q.done b { color: var(--muted); font-weight: 600; text-decoration: line-through; text-decoration-color: rgba(107, 133, 146, .5); }
.sc-q.click { cursor: pointer; }
.sc-q.click:hover { background: #f7fafb; }

.sc-who { font-size: 10.5px; font-weight: 800; padding: 2px 8px; border-radius: 999px; background: #eaf0f3; color: var(--text-3); white-space: nowrap; }
.sc-who.client { background: #e5eefc; color: #1d5bb8; }
.sc-who.both { background: #efe9fb; color: #5b3fa8; }

/* ── план ── */
.sc-stage-h { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin: 18px 0 6px; }
.sc-stage-h h4 { font-size: 16px; }
.sc-stage-h span { font-size: 12.5px; color: var(--muted); }
.sc-task { display: grid; grid-template-columns: 26px minmax(0, 1fr) 110px 96px 120px; gap: 10px; align-items: center; padding: 9px 4px; border-top: 1px solid var(--line); }
.sc-task:first-child { border-top: 0; }
.sc-task .ttl { font-weight: 700; font-size: 13.5px; }
.sc-task .res { font-size: 12px; color: var(--muted); margin-top: 1px; }
.sc-task .due { font-size: 13px; font-weight: 700; text-align: right; }
.sc-task .due small { display: block; font-size: 11px; font-weight: 600; color: var(--muted); }
.sc-task select { width: 100%; }
.sc-task.st-done .ttl { color: var(--muted); }
.sc-chk { width: 22px; height: 22px; border-radius: 7px; border: 1.5px solid var(--field); background: #fff; cursor: pointer; display: flex; align-items: center; justify-content: center; padding: 0; color: #fff; font-size: 13px; font-weight: 900; }
.sc-chk.on { background: var(--accent); border-color: var(--accent); }
.sc-chk:disabled { cursor: default; opacity: .75; }

select.sc-sel, input.sc-in, textarea.sc-in {
  padding: 6px 8px; border-radius: var(--r-sm); border: 1px solid var(--field); background: #fff;
  font: inherit; font-size: 13px; color: var(--text); min-width: 0;
}
textarea.sc-in { width: 100%; min-height: 60px; resize: vertical; line-height: 1.45; }
input.sc-in.w { width: 100%; }
.sc-dates { display: flex; gap: 14px; flex-wrap: wrap; align-items: flex-end; }
.sc-dates .field { min-width: 150px; }

/* ── таблицы реестров: прокрутка внутри карточки, не у страницы ── */
.sc-tw { overflow-x: auto; margin: 0 -4px; padding: 0 4px; }
table.sc-t { width: 100%; border-collapse: collapse; font-size: 13px; }
table.sc-t th { text-align: left; font-size: 10.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); padding: 0 8px 8px 0; white-space: nowrap; vertical-align: bottom; }
table.sc-t td { padding: 7px 8px 7px 0; border-top: 1px solid var(--line); vertical-align: middle; }
table.sc-t td.r, table.sc-t th.r { text-align: right; }
table.sc-t tr.click { cursor: pointer; }
table.sc-t tr.click:hover td { background: #f7fafb; }
table.sc-t tfoot td { font-weight: 800; border-top: 2px solid var(--line-2); }
table.sc-t select.sc-sel, table.sc-t input.sc-in { font-size: 12.5px; padding: 4px 6px; }
table.sc-t input.sc-in.num { width: 70px; text-align: right; }
table.sc-t td.wrap { min-width: 200px; }
tr.sc-hl td { background: #fff3f1; }
tr.sc-hl:hover td { background: #ffe9e5 !important; }

/* RACI */
table.sc-raci td.c { text-align: center; padding: 4px 3px; }
table.sc-raci th.c { text-align: center; padding: 0 3px 8px; writing-mode: vertical-rl; transform: rotate(180deg); height: 96px; white-space: nowrap; }
table.sc-raci select { width: 50px; padding: 4px 2px; text-align: center; font-weight: 800; }
table.sc-raci td.step { min-width: 230px; font-weight: 600; }
table.sc-raci tr.grp td { background: var(--soft); font-size: 11px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }

/* ── выезд ── */
.sc-day { margin-top: 12px; }
.sc-day h4 { font-size: 15px; margin-bottom: 6px; }
.sc-slot { display: grid; grid-template-columns: 96px minmax(0, 1fr) minmax(0, 1fr) minmax(0, .9fr); gap: 12px; padding: 9px 0; border-top: 1px solid var(--line); font-size: 13px; }
.sc-slot .tm { font-weight: 800; }
.sc-slot .lb { display: none; font-size: 10px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.sc-slot .need { color: #1d5bb8; }

.sc-zones { display: flex; gap: 6px; overflow-x: auto; padding-bottom: 4px; margin-bottom: 12px; }
.sc-zones .pill { flex: none; }
.sc-ci { background: #fff; border-radius: var(--r-md); box-shadow: var(--shadow-sm); padding: 13px 14px; margin-bottom: 10px; }
.sc-ci .w { font-weight: 800; font-size: 14.5px; }
.sc-ci .nm { font-size: 12.5px; color: var(--muted); margin-top: 2px; }
.sc-marks { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; margin-top: 10px; }
.sc-marks button { padding: 10px 4px; border-radius: 10px; border: 1.5px solid var(--field); background: #fff; font: inherit; font-weight: 800; font-size: 13.5px; cursor: pointer; color: var(--text-2); }
.sc-marks button.on.m-yes { background: var(--accent); border-color: var(--accent); color: #fff; }
.sc-marks button.on.m-part { background: #e0a410; border-color: #e0a410; color: #fff; }
.sc-marks button.on.m-no { background: var(--danger); border-color: var(--danger); color: #fff; }
.sc-marks button.on.m-na { background: var(--text-3); border-color: var(--text-3); color: #fff; }
.sc-ci .more { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px; margin-top: 8px; align-items: start; }
.sc-ci .more textarea { min-height: 42px; }
.sc-photo { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; font-weight: 700; color: var(--text-3); border: 1px dashed var(--field); border-radius: 9px; padding: 8px 10px; cursor: pointer; white-space: nowrap; }
.sc-photo input { display: none; }
.sc-tofind { margin-top: 8px; display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }

/* ── панель объекта: поля «подпись — значение» ── */
.sc-kv { display: grid; grid-template-columns: 170px minmax(0, 1fr); gap: 8px 14px; font-size: 13px; align-items: center; }
.sc-kv > span { color: var(--muted); }
.sc-kv textarea.sc-in { min-height: 54px; }
.sc-how { background: var(--accent-soft); border-radius: var(--r-md); padding: 12px 14px; font-size: 13.5px; line-height: 1.55; color: var(--accent-dark); }
.sc-how b { display: block; font-size: 10px; letter-spacing: .09em; text-transform: uppercase; margin-bottom: 3px; }

/* лента */
.sc-feed { display: flex; flex-direction: column; }
.sc-ev { display: grid; grid-template-columns: 30px minmax(0, 1fr); gap: 10px; padding: 8px 0; border-top: 1px solid var(--line); font-size: 13px; }
.sc-ev:first-child { border-top: 0; }
.sc-ev .av { width: 30px; height: 30px; border-radius: 999px; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: 800; background: #eaf0f3; color: var(--text-3); }
.sc-ev .av.client { background: #e5eefc; color: #1d5bb8; }
.sc-ev .av.partner { background: var(--accent-soft); color: var(--accent-dark); }
.sc-ev .av.expert { background: #efe9fb; color: #5b3fa8; }
.sc-ev .when { font-size: 11.5px; color: var(--muted); }
.sc-ev.new { animation: sc-flash 2.4s ease-out; }
@keyframes sc-flash { 0% { background: #fff5d6; } 100% { background: transparent; } }

/* памятка «кто что делает» */
.sc-role-h { display: flex; align-items: center; gap: 10px; margin-bottom: 4px; }
.sc-role-h .av { width: 34px; height: 34px; border-radius: 999px; background: var(--accent-soft); color: var(--accent-dark); font-weight: 800; display: flex; align-items: center; justify-content: center; }
.sc-rules li { margin: 6px 0 6px 18px; font-size: 13.5px; line-height: 1.5; }

/* ── кабинет санатория ── */
.sc-cab { max-width: 1060px; margin: 0 auto; padding: 18px 20px 60px; }
.sc-cab-top { display: flex; align-items: center; gap: 14px; padding: 14px 18px; background: #fff; border-radius: var(--r-lg); box-shadow: var(--shadow-sm); margin-bottom: 14px; }
.sc-cab-logo { width: 40px; height: 40px; border-radius: 12px; background: linear-gradient(140deg, var(--accent-500), var(--accent-dark)); color: #fff; font-weight: 800; font-size: 18px; display: flex; align-items: center; justify-content: center; flex: none; }
.sc-cab-top h3 { font-size: 18px; margin: 0; }
.sc-cab-me { display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--text-3); }
.sc-cab-me .av { width: 32px; height: 32px; border-radius: 999px; background: #e5eefc; color: #1d5bb8; font-weight: 800; font-size: 12px; display: flex; align-items: center; justify-content: center; }
.sc-cab .tabs { max-width: 100%; overflow-x: auto; margin-bottom: 14px; }
.sc-hero { background: linear-gradient(120deg, #0f766e, #0b5c56); color: #fff; border-radius: var(--r-lg); padding: 18px 20px; margin-bottom: 14px; }
.sc-hero h2 { font-size: 22px; color: #fff; }
.sc-hero .cnts { display: flex; gap: 10px; margin-top: 12px; flex-wrap: wrap; }
.sc-hero .cnt { background: rgba(255, 255, 255, .14); border: 0; border-radius: 12px; padding: 9px 14px; color: #fff; font: inherit; cursor: pointer; text-align: left; }
.sc-hero .cnt b { display: block; font-size: 22px; font-weight: 800; }
.sc-hero .cnt span { font-size: 12px; opacity: .9; }
.sc-hero .cnt:hover { background: rgba(255, 255, 255, .22); }
.sc-up { position: relative; overflow: hidden; }
.sc-up input { position: absolute; inset: 0; opacity: 0; cursor: pointer; }
.sc-lock { opacity: .55; }

.sc-form-q { padding: 10px 0; border-top: 1px solid var(--line); }
.sc-form-q:first-child { border-top: 0; }
.sc-form-q .q { font-weight: 700; font-size: 13.5px; margin-bottom: 6px; }
.sc-form-g { font-size: 11px; font-weight: 800; letter-spacing: .07em; text-transform: uppercase; color: var(--muted); margin: 14px 0 2px; }

/* ── узкий экран ──
   Меню встаёт полосой сверху и прокручивается вбок; экраны — в одну колонку.
   Страница вбок не едет никогда: широкое (таблицы, матрица) прокручивается
   внутри своей карточки. */
@media (max-width: 1100px) {
  .sc-grid2 { grid-template-columns: 1fr; }
  .sc-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 760px) {
  .app { flex-direction: column; height: calc(100vh - 44px); }
  .sidebar { width: 100%; height: auto; flex-direction: row; align-items: center; gap: 8px; padding: 8px 10px; overflow-x: auto; overflow-y: hidden; }
  .sidebar .brand { padding: 0 6px 0 2px; flex: none; }
  .sidebar .brand-name { display: none; }
  .sidebar .nav { flex-direction: row; gap: 4px; }
  .sidebar .nav a { white-space: nowrap; padding: 7px 10px; }
  .sidebar .nav a::before { display: none; }
  .sidebar .nav .nav-ic { display: none; }
  .sidebar .sc-side-foot { display: none; }
  .main { flex: 1; min-height: 0; }
  .sc { padding: 12px 16px 60px; }
  .sc .head { grid-template-columns: 1fr; gap: 10px; }
  .sc .head-actions { grid-column: 1; justify-content: flex-start; }
  .sc .head h2 { font-size: 21px; }
  .sc-track { grid-template-columns: 1fr; }
  .sc-st .r { display: none; }
  .sc-grid3 { grid-template-columns: 1fr; }
  .sc-kpis { grid-template-columns: 1fr 1fr; gap: 8px; }
  .sc-kpi .val { font-size: 20px; }
  .sc-q { grid-template-columns: 22px minmax(0, 1fr); }
  .sc-q .acts { grid-column: 2; justify-content: flex-start; }
  .sc-task { grid-template-columns: 26px minmax(0, 1fr) 84px; }
  .sc-task .who-c { display: none; }
  .sc-task .st-c { grid-column: 2 / 4; }
  .sc-slot { grid-template-columns: 1fr; gap: 3px; }
  .sc-slot .lb { display: block; }
  .sc-kv { grid-template-columns: 1fr; gap: 4px; }
  .sc-meter { grid-template-columns: 96px minmax(0, 1fr) 52px; }
  .sc-cab { padding: 12px 12px 60px; }
  .sc-cab-top { flex-wrap: wrap; }
  .sc-marks button { padding: 13px 2px; font-size: 14px; }
  .panel-body { padding: 14px 14px 40px; }
  .panel-head { padding: 14px; }
  .tabs { max-width: 100%; overflow-x: auto; }
  .modal { width: 100% !important; max-height: calc(100vh - 24px); overflow-y: auto; }
  .overlay { padding: 12px; }
}

/* ── рабочая версия: своё поверх app.css и own.css (префикс sc-) ─────────── */

/* Выход, пароль и состояние сохранения: у агентства — внизу меню, у санатория —
   в шапке кабинета, без проекта — в шапке экрана (app.js meActs). Раньше
   висели поверх экранов в правом верхнем углу. */
.sc-me-acts { display: inline-flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.sc-sync { font-size: 12px; color: var(--muted, #5b6b7a); }
.sc-sync:empty { display: none; }
.sc-sync.bad { color: var(--danger, #b42318); font-weight: 600; }
.sidebar .sc-me { padding: 0 2px; }
.sidebar .sc-me .sc-me-acts { width: 100%; }
.sidebar .sc-me .btn { flex: 1; justify-content: center; background: rgba(255, 255, 255, .08); border-color: rgba(255, 255, 255, .14); color: #e8f1f3; }
.sidebar .sc-me .btn:hover { background: rgba(255, 255, 255, .16); }
.sidebar .sc-me .sc-sync { flex-basis: 100%; color: #b9ccd2; }
.sidebar .sc-me .sc-sync.bad { color: #fda4af; }
.sc-cab-me .sc-me-acts { margin-left: 10px; }
@media (max-width: 720px) {
  .sidebar .sc-me { flex: none; }
  .sidebar .sc-me .sc-me-acts { flex-wrap: nowrap; }
}

/* Знак санатория в шапке меню вместо точки «Контроль услуги». */
.sc-side-brand { gap: 11px; }
.sc-side-brand .sc-leaf { box-sizing: border-box; padding: 3px; border-radius: 50%; background: #f8f6ef; }
.sc-side-brand .brand-name { line-height: 1.1; }
.sc-side-brand .brand-name small { display: block; font-size: 11.5px; font-weight: 600; letter-spacing: .02em; color: #9fb6bd; margin-top: 2px; }

/* Форма заведения проекта: поля не слипаются. */
.sc-init .card .field + .field, .sc-init .card .sc-grid2 + .field, .sc-init .card .field + .sc-grid2,
.sc-init .card .sc-grid2 + .sc-grid2 { margin-top: 12px; }
.sc-init .card .sc-grid2 { gap: 12px; }

/* Ссылка с кнопкой «Копировать» и QR в окне. */
.sc-link { display: flex; gap: 8px; }
.sc-link input { flex: 1; min-width: 0; font-family: ui-monospace, Consolas, monospace; font-size: 12px; }
.sc-qr { width: 220px; max-width: 100%; margin: 14px auto 6px; }
.sc-qr svg { display: block; width: 100%; height: auto; }
.sc-key { font-family: ui-monospace, Consolas, monospace; font-size: 15px; letter-spacing: .06em; text-align: center; margin-bottom: 4px; word-break: break-all; }

/* Страницы без рабочего места: анкета и опрос с телефона. */
.sc-pub { background: var(--bg, #eff3f6); }
.sc-pub .pub { padding-left: 16px; padding-right: 16px; }
.sc-pub textarea.sc-in, .sc-pub input { width: 100%; box-sizing: border-box; }
.sc-pub .field + .field, .sc-pub .sc-form-g + .field { margin-top: 14px; }
.sc-pub .sc-form-g { font-size: 15px; margin: 22px 0 8px; }
.sc-pub .sc-form-g:first-child { margin-top: 0; }
.sc-sq { padding: 12px 0; border-bottom: 1px solid var(--line, #e6ebf0); }
.sc-sq:last-of-type { border-bottom: 0; }
.sc-opts { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.sc-opt { display: inline-flex; align-items: center; gap: 6px; min-height: 40px; padding: 6px 12px; border: 1px solid var(--line-2, #d7dee5);
  border-radius: 10px; cursor: pointer; font-size: 14px; background: var(--surface, #fff); }
.sc-opt input { width: auto; margin: 0; }
.sc-opt:has(input:checked) { border-color: var(--accent, #0f766e); background: var(--accent-soft, #e6f4f1); }
.sc-scale { display: flex; justify-content: space-between; margin-top: 4px; font-size: 12px; }

/* Отчёт опроса: свободные ответы списком. */
.sc-texts { margin: 8px 0 0; padding-left: 18px; font-size: 14px; }
.sc-texts li + li { margin-top: 4px; }

/* ── клиент этой установки (web/src/brand): знак-лист с сайта санатория ── */
.sc-leaf { display: inline-block; flex: none; }
.sc-leaf svg { display: block; width: 100%; height: 100%; }

/* Вход и приглашение — вид входа пайплайна (.au-*), свои только знак и
   цвета пятен: бирюза системы плюс олива и золото санатория. Классы .au-*
   не переопределяются — меняются только их переменные. */
.sc-auth { --au-2: #6b7050; --au-3: #b8a975; --au-4: #8e7e33; }
.sc-auth-col { padding-top: 9vh; padding-bottom: 40px; }
.sc-auth-brand { text-decoration: none; }
.sc-auth-brand:hover .au-name { text-decoration: underline; text-underline-offset: 4px; }
.sc-auth-brand > span:last-child { display: flex; flex-direction: column; line-height: 1.15; text-align: left; }
.sc-auth-sub { font-size: 12px; font-weight: 600; color: rgba(255, 255, 255, 0.72); letter-spacing: 0.02em; }
.sc-auth .sc-qr { background: #fff; padding: 8px; border-radius: 12px; }

/* Анкета и опрос: знак и полное название санатория над шапкой. */
.sc-pub-brand { display: flex; align-items: center; gap: 10px; margin: 4px 0 14px; color: var(--text-2, #334155);
  font-weight: 700; font-size: 14px; text-decoration: none; }
/* Кабинет санатория: знак вместо буквы. */
.sc-cab-logo.sc-cab-mark { background: #f8f6ef; box-shadow: inset 0 0 0 1px #eae1d2; padding: 3px; }
.sc-auth-brand .sc-leaf { box-sizing: border-box; padding: 5px; border-radius: 50%; background: #f8f6ef;
  box-shadow: 0 10px 26px -10px rgba(184, 169, 117, 0.9), 0 0 0 1px rgba(234, 225, 210, 0.6); }
