/* [2026-09-06][CLX][КП-V1-W5-DRAFT] Экран черновика КП и правки списка КП.
 *
 * ЧТО ЭТО. Стили ТОЛЬКО для экрана подборки (`client/js/pages/kp-draft.js`) и для того
 * немногого, что добавлено в список КП (`client/js/pages/quotes.js`). Каркас берётся из
 * `components.css` — `.detail-card`, `.calc-field`, `.input`, `.select`, `.state-box`,
 * `.modal-overlay/.modal`, `.quotes-toolbar`. Здесь только то, чего там нет.
 *
 * 🪤 ПОЧЕМУ НЕ `.quote-item`. В `components.css:1514` уже живёт `.quote-item` — флекс-строка
 * старого редактора КП из пяти полей. Раскладка волны 5 — сетка из восьми колонок с органами
 * выбора цвета и подключения. Дописывать в чужой класс = менять старый экран, который ещё
 * работает, пока выключатель `kp_v1_enabled` в `false`. Поэтому весь новый экран живёт на
 * своём префиксе `kp-`, и ни одно правило отсюда не задевает старую разметку.
 *
 * 🪤 ИМЕНА `cat-sr__kp-*` В ВИТРИНЕ ЗАНЯТЫ «ключевыми параметрами», это не КП
 * (`PORTAL-INVENTORY §3.2`). Здесь префикс `kp-` без `cat-sr__`, пересечения нет.
 *
 * Мобильной раскладки НЕТ намеренно — решение владельца 30.07 («мобильную адаптацию не
 * делать и не предлагать до запроса»). Проверено на 1440×900 и 1280×800.
 */

/* ── Шапка черновика ─────────────────────────────────────────────────────── */

.kp-head {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  flex-wrap: wrap;
  margin-bottom: var(--space-4);
}

.kp-head__num {
  font-family: var(--font-data);
  font-size: var(--text-lg);
  font-weight: 600;
}

/* [2026-09-11][CLX][НОМЕР-РУЧНОЙ] Карандаш правки номера. Значок тихий: правка редкая, и
   кнопка не должна спорить с номером за внимание. Проступает при наведении и по фокусу —
   с клавиатуры её видно так же, как мышью. */
.kp-head__edit {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-sm, 4px);
  background: transparent;
  color: var(--c-text-muted);
  cursor: pointer;
  opacity: .55;
  transition: opacity .15s ease, color .15s ease, background-color .15s ease;
}

.kp-head__edit svg { width: 15px; height: 15px; }

.kp-head__edit:hover,
.kp-head__edit:focus-visible {
  opacity: 1;
  color: var(--c-text-primary);
  background: var(--c-bg-subtle, rgba(0, 0, 0, .05));
}

/* Пометка «рукой» рядом с номером: человек должен видеть, что номер не автоматический,
   не открывая журнал. Слово, а не значок: значок пришлось бы объяснять. */
.kp-head__manual {
  margin-left: var(--space-2);
  font-family: var(--font-ui);
  font-size: var(--text-xs);
  font-weight: 400;
  color: var(--c-text-muted);
}

.kp-head__num--empty {
  font-family: var(--font-ui);
  font-weight: 400;
  color: var(--c-text-muted);
}

.kp-head__series {
  font-size: var(--text-base);
  color: var(--c-text-secondary);
}

/* [2026-09-08][CLX][НА-ПРОВЕРКУ] Описание серии заехало из архива и владельцем ещё не читано.
   Тихо: тот же кегль подписи, мутный цвет, никакой подложки и никакой рамки — плашки и жёлтые
   коробки сегодня как раз убирали из «Обращений» как машинный приём. Выгрузке не мешает. */
.kp-head__review {
  font-size: var(--text-sm);
  color: var(--c-text-muted);
  font-style: italic;
}

.kp-head__spacer { flex: 1; }

.kp-head__status {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.kp-head__status .select { min-width: 150px; }

/* ── Вид документа ───────────────────────────────────────────────────────── */

.kp-kind {
  display: flex;
  gap: var(--space-2);
  align-items: center;
  flex-wrap: wrap;
}

.kp-kind__btn {
  padding: 6px 16px;
  font-size: var(--text-base);
  border: 1px solid var(--c-border);
  border-radius: 16px;
  background: transparent;
  color: var(--c-text-secondary);
  cursor: pointer;
  transition: all var(--tr-fast);
}

.kp-kind__btn:hover { border-color: var(--c-primary); color: var(--c-primary); }

.kp-kind__btn.is-on {
  background: var(--c-primary);
  border-color: var(--c-primary);
  color: var(--text-on-accent);
}

.kp-kind__hint {
  font-size: var(--text-sm);
  color: var(--c-text-muted);
  margin-top: var(--space-2);
}

/* ── Блок «Кому» ─────────────────────────────────────────────────────────── */

.kp-grid {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: var(--space-3) var(--space-5);
}

.kp-grid__wide { grid-column: 1 / -1; }

.kp-check {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-base);
  cursor: pointer;
  user-select: none;
}

.kp-check input { cursor: pointer; }

.kp-gender {
  display: flex;
  gap: var(--space-2);
  align-items: center;
}

/* 🪤 [2026-09-08][CLX][ПЕРЕВЁРСТКА] `display: flex` СИЛЬНЕЕ атрибута `hidden`: браузерное
   правило `[hidden]{display:none}` живёт в таблице агента и любым своим `display` перебивается.
   Переключатель рода прячется именно атрибутом (`kp-gender-box.hidden = true`), и без этой
   строки он оставался бы на экране всегда — предлагая выбрать род там, где он уже определён.
   Та же грабля уже стоила времени на кабинете поставщика (память: `[hidden]` у flex/grid). */
.kp-gender[hidden] { display: none; }

/* ── [2026-09-08][CLX][ПЕРЕВЁРСТКА] Компактный блок «Клиент и сделка» ────────────────────────
 *
 * Три строки вместо двух карточек: поля · органы выбора · подсказки. Высота блока — около
 * 150 px против прежних ~330 px, поэтому «Позиции» видны без прокрутки на 1440×900.
 * Сетка полей — четыре равные колонки; на 1280 они не ужимаются ниже 180 px (минимум задан
 * `minmax`), иначе телефон не помещается целиком и его приходится читать по частям. */
.kp-brief {
  margin-bottom: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.kp-brief__row {
  display: grid;
  grid-template-columns: repeat(4, minmax(180px, 1fr));
  gap: var(--space-3) var(--space-5);
  align-items: end;
}

/* Вторая строка — не поля, а органы разной ширины: сетка из четырёх равных колонок им не
   годится (переключатель вида вдвое шире галочки). Отсюда флекс с растяжимым комментарием. */
.kp-brief__row--controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3) var(--space-5);
}

.kp-brief__notes { flex: 1 1 260px; }

/* ── [2026-09-08][CLX][КП-ДИЗАЙНЕР] Строка «Клиент от дизайнера» ─────────────────────────────
 * Обязательный ответ, поиск по реестру от трёх букв и — при тёзках — отказ выбирать за
 * человека. Выпадающего списка нет намеренно: реестр целиком на экран не выгружается. */
.kp-brief__row--designer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-3);
  position: relative;
}

.kp-des__label { margin: 0; }

.kp-des__q { max-width: 320px; }

/* Выбранный дизайнер — плашкой, а не полем ввода: он уже выбран, править его нечего. */
.kp-des__chip {
  display: inline-flex;
  align-items: center;
  padding: 4px 10px;
  border-radius: 12px;
  background: var(--c-primary-light, var(--c-bg));
  color: var(--c-primary-dark, var(--c-text));
  font-size: var(--text-base);
}

.kp-des__note {
  font-size: var(--text-sm);
  color: var(--c-text-muted);
}

/* Найденные — узким столбиком под полем поиска, поверх остального: строка «от дизайнера»
   не должна раздвигать блок и уводить позиции вниз при каждом наборе букв. */
.kp-des__res {
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 30;
  display: flex;
  flex-direction: column;
  min-width: 320px;
  max-width: 520px;
  background: var(--c-card);
  border: 1px solid var(--c-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md);
  overflow: hidden;
}

.kp-des__res:empty { display: none; }

.kp-des__row {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border: none;
  border-bottom: 1px solid var(--c-border);
  background: transparent;
  text-align: left;
  font-size: var(--text-base);
  cursor: pointer;
}

.kp-des__row:last-child { border-bottom: none; }
.kp-des__row:hover { background: var(--c-bg); }

.kp-des__tag { color: var(--c-text-muted); font-weight: 400; }

/* [2026-09-16][CLX][ФОТО-ПОД-ЧЕРТОЙ] Непроверенные кадры менеджеров — под тонкой чертой. */
.kp-gal__line {
  margin: var(--space-4) 0 var(--space-2);
  padding-top: var(--space-2);
  border-top: 1px solid var(--c-border);
  font-size: var(--text-sm);
  color: var(--c-text-muted);
}
.kp-gal__who { display: block; font-size: var(--text-sm); color: var(--c-text-muted); padding: 2px 6px; }
.kp-rev { display: grid; gap: var(--space-3); }
.kp-rev img { max-height: 320px; width: auto; max-width: 100%; justify-self: center; }
.kp-rev__row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.kp-rev__label { min-width: 150px; font-size: var(--text-sm); color: var(--c-text-muted); }

.kp-des__meta { color: var(--c-text-muted); font-size: var(--text-sm); }

.kp-brief__hints {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-5);
  font-size: var(--text-sm);
  color: var(--c-text-muted);
  min-height: 1em;                 /* без имени подсказки нет — блок не должен прыгать */
}

/* ── [2026-09-08][CLX][ПЕРЕВЁРСТКА] Рабочий блок: позиции и фото вместе ──────────────────────
 * Слова Александра — «позиции с фото — отдельным блоком». Фото серии перестало быть отдельной
 * карточкой: и таблица, и кадр — про одно и то же, про то, что уйдёт клиенту. */
.kp-work { margin-bottom: var(--space-5); }

.kp-work__photo {
  margin-top: var(--space-5);
  padding-top: var(--space-4);
  border-top: 1px solid var(--c-border);
}

.kp-work__sub {
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--c-text-muted);
  margin-bottom: var(--space-3);
}

/* ── Позиции ─────────────────────────────────────────────────────────────── */

.kp-items { display: block; }

/* Восемь колонок из `designer.md §2.2`. «Мощн.» снимается целиком у T4 —
   тогда на её месте не пустая клетка, а отсутствующая колонка (класс --nopower).
   [2026-09-08][CLX][ПЕРЕВЁРСТКА] Первая колонка выросла с 28 до 76 px: в ней теперь номер
   позиции И снимок прибора из каталога. Числа остальных колонок не тронуты. */
.kp-item,
.kp-items__head {
  display: grid;
  /* 🪤 [2026-09-11][CLX][ЦВЕТ-НЕ-ЧИТАЕТСЯ] Колонка цвета была 132 px, а «Чёрный RAL 9005
     (глянец или мат)» требует 187,9 — на экране стояло «Чёрный RAL 900…», и понять, глянец
     там или мат, было нельзя. А это то, что уедет клиенту в документ. Ширину подбирали ПО
     ЗАМЕРУ: 132 → 176 → 190 → 206 → 230.

     🔴 ПОЧЕМУ ПОДГОНЯЛИ ЧЕТЫРЕЖДЫ. Первые три замера считали ширину ТЕКСТА и не учитывали,
     что Chrome рисует стрелку списка ВНУТРИ содержательной области — она съедает 20 точек.
     Каждая цель выходила на двадцать оптимистичнее правды, и ширина догоняла её по кругу.
     Итоговое число взято по САМОМУ ДЛИННОМУ имени списка («Лаки: медь, золото, бронза,
     технолак» — 230), а не по тому, что попалось на глаза первым: подгонять под конкретную
     строку значит чинить до следующего цвета.

     Колонка серии при этом нигде ничего не обрезала — у неё 490 точек на 1440 при нужных 161.
     Полное имя цвета подписано у самого списка. */
  grid-template-columns: 76px minmax(180px, 1fr) 96px 230px 88px 104px 132px 32px;
  gap: var(--space-2);
  align-items: center;
}

.kp-item--nopower,
.kp-items__head--nopower {
  grid-template-columns: 76px minmax(180px, 1fr) 96px 230px 104px 132px 32px;
}

/* Номер и снимок — в ОДНОЙ клетке, а не двумя колонками: девятая колонка отняла бы место у
   названия серии, а оно и так самое тесное. */
.kp-item__lead {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

/* Снимок прибора. `object-fit: contain` — потому что кадры каталога разной пропорции, и
   обрезка по центру срезала бы у вертикальных радиаторов ровно то, по чему их узнают.
   Нет кадра — пустая рамка того же размера: строка не должна прыгать по высоте. */
.kp-item__thumb {
  width: 44px;
  height: 44px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--c-bg);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-sm, 4px);
  overflow: hidden;
}

.kp-item__thumb img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

.kp-items__head {
  padding: 0 0 var(--space-2);
  border-bottom: 1px solid var(--c-border);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--c-text-muted);
}

.kp-item {
  padding: var(--space-3) 0;
  border-bottom: 1px solid var(--c-border);
}

.kp-item:last-child { border-bottom: none; }

.kp-item__num {
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--c-bg);
  border-radius: 50%;
  font-size: var(--text-xs);
  font-weight: 500;
  color: var(--c-text-muted);
}

.kp-item__info { min-width: 0; }

.kp-item__title {
  font-weight: 500;
  font-size: var(--text-base);
  overflow-wrap: anywhere;
}

/* «Вариант 1» — БЕЗ `text-transform: uppercase`. Спека аналитика §1.2 п. 2 пишет подпись
   строчными, и ровно так она печатается в документе. Заглавные тут стоили ложной тревоги
   на проверке: браузер отдаёт в `innerText` УЖЕ преобразованный текст, поиск «Вариант 1»
   не находил ничего, и проверка объявила подпись отсутствующей, хотя она была на экране. */
.kp-item__alt {
  font-size: var(--text-xs);
  letter-spacing: 0.02em;
  color: var(--c-text-muted);
  margin-bottom: 2px;
}

/* Вторая строка — «исполнение словами» плюс органы выбора подключения и вида нижнего.
   Слова и органы стоят рядом намеренно: менеджер сверяет глазами то, что уйдёт в документ. */
.kp-item__exec {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
  margin-top: var(--space-2);
  font-size: var(--text-sm);
  color: var(--c-text-muted);
}

/* Компактные органы выбора внутри строки: класса `select-sm` в портале нет (проверено
   grep по components.css), поэтому размер задаётся здесь, а не выдуманным классом. */
.kp-item .select {
  padding: 4px 8px;
  font-size: var(--text-sm);
  height: auto;
}

.kp-item__exec .select { max-width: 230px; }

.kp-item__size,
.kp-item__power {
  font-size: var(--text-sm);
  color: var(--c-text-secondary);
  text-align: center;
}

.kp-item__qty {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-1);
}

.kp-item__qty-val {
  min-width: 24px;
  text-align: center;
  font-weight: 500;
}

.kp-item__price { text-align: right; }

.kp-item__unit { font-weight: 600; }

.kp-item__line {
  font-size: var(--text-xs);
  color: var(--c-text-muted);
  margin-top: 2px;
}

/* Метка «Своя цена» — она же кнопка правки этой цены: одна подпись вместо двух одинаковых
   (найдено глазами 06.09). Не цветом — цветных плашек в портале нет. */
.kp-item__manual {
  display: inline-block;
  margin-top: 2px;
  padding: 1px 8px;
  border: 1px solid var(--c-text-muted);
  border-radius: 10px;
  background: transparent;
  font: inherit;
  font-size: var(--text-xs);
  color: var(--c-text-secondary);
  cursor: pointer;
}

.kp-item__manual:hover { border-color: var(--c-primary); color: var(--c-primary); }

.kp-item__acts {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
  margin-top: var(--space-1);
}

.kp-item__acts .btn { padding: 2px 8px; font-size: var(--text-xs); }

.kp-item__del {
  color: var(--c-text-muted);
  font-size: 1.2rem;
  line-height: 1;
  background: transparent;
  border: none;
  cursor: pointer;
}

.kp-item__del:hover { color: var(--c-danger); }

/* 🪤 [2026-09-11][CLX][КП-КАРТОЧКА] Та же кнопка помощи, что и у `.kp-acts` выше (см. её
   комментарий), при прокрутке проходила поверх строки «Итого» — знак «₽» скрывался под
   кнопкой (замер: строка кончалась на 1385 px, кнопка занимала 1372…1418 px, перекрытие
   13 px). Тот же приём: своё место под фиксированную кнопку освобождаем мы, тем же числом. */
.kp-total {
  padding-top: var(--space-4);
  padding-right: 80px;
  margin-top: var(--space-4);
  border-top: 2px solid var(--c-border);
  text-align: right;
  font-size: var(--text-2xl);
}

/* ── Фото ────────────────────────────────────────────────────────────────── */

.kp-photo {
  display: flex;
  gap: var(--space-5);
  align-items: flex-start;
  flex-wrap: wrap;
}

.kp-photo__frame {
  width: 160px;
  height: 188px;              /* соотношение 0,853 — designer §2.2 */
  border: 1px solid var(--c-border);
  border-radius: var(--radius);
  background: var(--c-bg);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  flex-shrink: 0;
}

.kp-photo__frame img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

.kp-photo__empty {
  padding: var(--space-3);
  font-size: var(--text-xs);
  color: var(--c-text-muted);
  text-align: center;
}

.kp-photo__side {
  flex: 1;
  min-width: 260px;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.kp-photo__rule {
  font-size: var(--text-sm);
  color: var(--c-text-muted);
}

.kp-photo__acts {
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
}

/* ── Условия серии ───────────────────────────────────────────────────────── */

.kp-cond { display: flex; flex-direction: column; gap: var(--space-2); }

.kp-cond__row {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  font-size: var(--text-base);
  line-height: 1.45;
}

.kp-cond__row input { margin-top: 3px; flex-shrink: 0; }

/* 🪤 [2026-09-11][CLX][КП-КАРТОЧКА] Первый пункт условий шёл одной строкой на 207 знаков во
   всю ширину карточки — глаз терял начало следующей строки. Комфортная длина сплошного
   текста — 75–90 знаков; 70ch держит её с запасом на любом шрифте, не завися от px-ширины
   карточки. Переносится и оборачивается сам `<span>`, галочка (flex-shrink: 0 выше) не
   двигается. */
.kp-cond__row span { max-width: 70ch; }

/* Галочки выключены НАМЕРЕННО (см. комментарий у разметки в DraftPage.jsx) — снятые строки
   всё равно уйдут в документ, хранить выбор порталу негде. Записка под списком это
   объясняет, но сама галочка визуально не отличалась от настоящей: `disabled` уже даёт
   верный курсор (обычная стрелка — проверено), а вот вид оставался «как у живой». Гасим
   его, чтобы не обещать взглядом того, чего экран не делает. */
.kp-cond__row input:disabled { opacity: 0.55; }

.kp-cond__row--off { color: var(--c-text-muted); text-decoration: line-through; }

.kp-note {
  margin-top: var(--space-3);
  padding: var(--space-3);
  border: 1px dashed var(--c-border);
  border-radius: var(--radius);
  font-size: var(--text-sm);
  color: var(--c-text-secondary);
}

/* ── Панель действий ─────────────────────────────────────────────────────── */

/* 🪤 НАЙДЕНО ГЛАЗАМИ: правый край полосы действий перекрывался плавающей кнопкой помощи
   (`.hh-fab`, `help-hub.js`) — «Удалить» уходила ей под низ. Кнопка помощи прижата к правому
   краю ОКНА и о нашей вёрстке не знает, поэтому место под неё освобождаем мы. */
.kp-acts {
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
  align-items: center;
  padding-right: 80px;
}

.kp-acts__spacer { flex: 1; }

/* 🪤 [2026-09-11][CLX][КП-КАРТОЧКА] «Сохранить» стояла на 2 px ниже соседей (26 px против
   28 px), хотя середины совпадали — кнопка казалась «утопленной». Причина не в этом ряду,
   а в `components.css`: у светлых кнопок (`.btn-outline`) рамка 1 px входит в высоту, у
   главной (`.btn-primary`) рамки нет вовсе. Прозрачная рамка той же толщины возвращает
   высоту к общей, ничего не меняя в цвете — правило нарочно ограничено этим рядом, как и
   другие точечные правки `.kp-acts` выше, чтобы не трогать общий `.btn-primary` во всём
   портале. */
.kp-acts .btn-primary { border: 1px solid transparent; }

/* ── Окна ────────────────────────────────────────────────────────────────── */

.kp-modal { width: 460px; max-width: calc(100vw - 40px); }

.kp-modal--wide { width: 620px; }
/* [2026-09-16][CLX][ЗАМЕЧАНИЯ-Б6] Подтверждение имени и номера перед выгрузкой. */
.kp-confirm { padding: var(--space-3); border: 1px solid var(--c-border); border-radius: var(--radius); background: var(--c-bg); margin-bottom: var(--space-3); }
.kp-confirm__head { font-weight: 600; margin-bottom: 4px; }
.kp-confirm__line { display: flex; gap: var(--space-2); align-items: center; }
.kp-confirm__line .input { flex: 1; }
.kp-confirm__check { display: block; margin-top: var(--space-3); font-weight: 600; }
/* [2026-09-16][CLX][ЗАМЕЧАНИЯ-Б3] Окно выбора кадров: большое, прокрутка только у сетки, кнопки всегда видны. */
.kp-modal--gallery { width: min(1100px, calc(100vw - 40px)); max-height: 92vh; }
.kp-modal--gallery .modal__body { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0; overflow: hidden; }
.kp-modal--gallery .kp-modal__foot { flex: none; }
.kp-gal-scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding-right: 4px; }
.kp-gal-scroll .kp-gal { max-height: none; overflow: visible; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); }
.kp-gal-scroll .kp-gal__cell img { height: 170px; }
/* [2026-09-27][CLX][ФОТО-L1] Кадры крупнее — чтобы разглядеть прибор без лупы (решение 22.09-3 п. 2);
   «Ваши фото» с плиткой «+ Своё фото», метка «в КП · N», кнопки «Убрать» под кадром. */
.kp-gal-scroll .kp-gal { grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); }
.kp-gal-scroll .kp-gal__cell img { height: 200px; }
.kp-gal__head { margin: var(--space-2) 0 0; font-size: var(--text-sm); font-weight: 600; color: var(--c-text-secondary); }
.kp-gal__head + .kp-gal { margin-top: var(--space-2); }
.kp-gal__done { color: var(--c-success); }
.kp-gal__inkp {
  position: absolute; top: 34px; left: 6px;
  padding: 2px 8px; border-radius: 10px;
  background: var(--c-success); color: #fff;
  font-size: 11px; font-weight: 600; line-height: 1.4;
}
.kp-gal__acts { display: flex; flex-wrap: wrap; gap: 6px; padding: 0 6px 6px; }
.kp-gal__cell.kp-gal__add {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
  min-height: 228px; padding: var(--space-3);
  border-style: dashed; color: var(--c-text-secondary); font: inherit; text-align: center;
}
.kp-gal__cell.kp-gal__add:hover:not(:disabled) { border-color: var(--c-primary); color: var(--c-primary); }
.kp-gal__cell.kp-gal__add:disabled { opacity: .6; cursor: progress; }
.kp-gal__add-plus { font-size: 40px; line-height: 1; font-weight: 300; }
.kp-gal__add-text { font-weight: 600; }
.kp-gal__add-sub { font-size: 11px; color: var(--c-text-muted); }
/* [2026-09-28][CLX][ФОТО-L1-ШАГ2] «В КП: [1] [2]» — порядок кадров перетаскиванием; «Не годится»; очередь разбора. */
.kp-gal__slots { display: flex; align-items: center; gap: var(--space-2); margin: 0 0 var(--space-2); flex-wrap: wrap; }
.kp-gal__slots-t { font-size: var(--text-sm); font-weight: 600; color: var(--c-text-secondary); }
.kp-gal__slot {
  position: relative; width: 96px; height: 72px; border: 1px solid var(--c-border); border-radius: 6px;
  overflow: hidden; background: var(--c-surface, #fff); cursor: grab;
}
.kp-gal__slot[draggable="false"] { cursor: default; }
.kp-gal__slot:active { cursor: grabbing; }
.kp-gal__slot img { width: 100%; height: 100%; object-fit: cover; display: block; pointer-events: none; }
.kp-gal__slot.is-drop { border-color: var(--c-primary, #b07a3c); box-shadow: 0 0 0 2px var(--c-primary, #b07a3c) inset; }
.kp-gal__flag { color: var(--c-text-muted); }
.kp-gal__queue-line { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.kp-gal__qrow { display: flex; gap: var(--space-3); padding: var(--space-2) 0; border-bottom: 1px solid var(--c-border); }
.kp-gal__qrow img { width: 200px; height: 150px; object-fit: cover; flex: 0 0 auto; border-radius: 6px; }
.kp-gal__qbody { display: grid; gap: 4px; align-content: start; }
.kp-gal__qhead { font-weight: 600; }

.kp-modal__foot {
  display: flex;
  gap: var(--space-2);
  justify-content: flex-end;
  flex-wrap: wrap;
  padding: var(--space-4) var(--space-5) var(--space-5);
  border-top: 1px solid var(--c-border);
}

/* 🪤 НАЙДЕНО ГЛАЗАМИ. В портале нет правила `.btn:disabled` вообще (проверено: слово
   `disabled` в components.css встречается 7 раз и ни разу для `.btn`). Поэтому выключенная
   кнопка выглядела ровно как рабочая: «Сохранить» в окне «Своя цена» при пустом «Почему»,
   «Скачать PDF/Excel» на пустой подборке, «Всё верно, собрать» без подтверждённого
   обращения. Правило нарочно ограничено моими блоками — трогать общий `.btn` значит менять
   весь портал, а это не зона волны.
   [2026-09-15][CLX][ДОСКА-V2-ПРИЁМКА] + `.kp-ct__actions` — ряд кнопок окон разговора, стадии и отметок:
   «Подтвердить» без выбранной причины в «Проиграна»/«Отложили» была `disabled`, но выглядела рабочей
   (фон, прозрачность 1, курсор-рука — приёмка 15.09, находка 6). */
.kp-modal__foot .btn:disabled,
.kp-acts .btn:disabled,
.kp-item__acts .btn:disabled,
.kp-ct__actions .btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

.kp-modal__row {
  display: flex;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--c-border-light);
  font-size: var(--text-base);
}

.kp-modal__row:last-child { border-bottom: none; }

.kp-modal__key { color: var(--c-text-muted); flex-shrink: 0; }

.kp-modal__val { text-align: right; overflow-wrap: anywhere; }

.kp-modal__err {
  margin-top: var(--space-2);
  font-size: var(--text-sm);
  color: var(--c-danger);
  min-height: 1em;
}

.kp-modal__sub {
  margin: var(--space-4) 0 var(--space-2);
  font-size: var(--text-sm);
  font-weight: 600;
}

.kp-code {
  font-family: var(--font-data);
  font-size: var(--text-sm);
  padding: var(--space-2) var(--space-3);
  background: var(--c-bg);
  border: 1px solid var(--c-border);
  border-radius: var(--radius);
  overflow-wrap: anywhere;
}

.kp-hist { max-height: 420px; overflow-y: auto; }

.kp-hist__row {
  display: grid;
  grid-template-columns: 130px 130px 1fr;
  gap: var(--space-3);
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--c-border-light);
  font-size: var(--text-sm);
}

.kp-hist__row:last-child { border-bottom: none; }

.kp-hist__when { color: var(--c-text-muted); font-family: var(--font-data); }

.kp-hist__who { color: var(--c-text-secondary); }

/* Плашка сторожа (🟠 косметика): документ отдан, но вёрстку надо посмотреть. */
.kp-flash {
  margin-bottom: var(--space-4);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--c-warning);
  border-radius: var(--radius);
  font-size: var(--text-base);
  background: var(--c-card);
}

/* ── Список КП: то немногое, что добавлено волной 5 ──────────────────────── */

.kp-search {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-3);
}

.kp-search .input { max-width: 420px; }

.kp-search__found {
  font-size: var(--text-sm);
  color: var(--c-text-muted);
}

.quote-card__series {
  font-size: var(--text-sm);
  color: var(--c-text-secondary);
}

/* ── [2026-09-08][CLX][СПИСОК-КП] Одна сетка и один шрифт ────────────────────────────────────
 *
 * Восемь колонок: № · Клиент · Серия · Позиции · Сумма · Менеджер · Дата · Статус.
 *
 * 🔴 `grid-template-columns` у шапки и у строки — ОДНА запись на оба класса. Разнеси их по
 * двум правилам, и первая же правка ширины поедет только в одном месте: подписи разъедутся с
 * ячейками, а глазами это ловится только на длинном списке. Сторож `verify_quotes_list.js`
 * сверяет, что селекторы шапки и строки стоят в ОДНОМ правиле с шириной колонок.
 *
 * Числа (номер, позиции, сумма, дата) — тем же шрифтом интерфейса, что и текст, но с ровными
 * цифрами (`tabular-nums`). Александр просил «один шрифт», поэтому моноширинного здесь нет;
 * ровная ширина цифры даёт то же самое — столбик сумм стоит на одной вертикали.
 *
 * Мобильной раскладки нет намеренно (решение владельца 30.07). Проверено на 1440×900 и 1280×800. */
/* 🔴 [2026-09-11][CLX][СХЛОПНУТЫЕ-КОЛОНКИ] У ТЕКСТОВЫХ КОЛОНОК ЕСТЬ НИЖНЯЯ ГРАНИЦА.
   Осмотр 11.09 на 1280×800: «Клиент» 14,8 px, «Серия» 11,7, «Менеджер» 7,4 — вместо имён
   многоточия, а шапка «Менеджер» превратилась в «М». Причина — `minmax(0, …fr)`: доля умеет
   сжиматься до НУЛЯ, а соседние колонки держат жёсткие 68–108 px и места не отдают. Панель
   отбора слева забрала ширину, и весь дефицит лёг на три колонки, в которых как раз имена.
   Даже на 1440×900 «Менеджер» оставался 42,4 px и обрезал собственную подпись.

   Теперь у них настоящий минимум, а у строки — общая наименьшая ширина. Не влезает в окно —
   таблица прокручивается вбок ВНУТРИ СЕБЯ (`.kp-page__table { overflow: auto }`), и имя можно
   домотать. Это честнее прежнего: раньше содержимое не уезжало за край, а уничтожалось. */
.kp-qrow,
.kp-qrow--head {
  display: grid;
  /* 🪤 [2026-09-11][CLX][СТАТУС-ЗА-КРАЕМ] ЧИСЛО СЧИТАНО, А НЕ ВЗЯТО НА ГЛАЗ. Первая попытка
     дала строке 1212 точек при 1088 доступных — и «Статус» уехал за край на обоих размерах
     окна. Поменять обрезанные имена на спрятанную плашку статуса — не починка: по статусу
     список и читают. Узкие колонки ужаты до их СОДЕРЖИМОГО («сегодня», «6 мес. назад», число
     позиций), просвет между колонками 16 → 12, и строка теперь помещается в окно 1440
     целиком. На 1280 середина всё же поедет — поэтому «Статус» ещё и закреплён у края. */
  /* 🪤 Восемь точек, которые рисовали ПУСТУЮ полосу прокрутки. Замер: таблица считала себя
     1096 при доступных 1088 — это ровно наименьшая ширина строки плюс её собственный левый
     отступ 16. Прокрутка при этом не открывала ничего: всё уже было видно. Даём строке 1064,
     чтобы полосы не было вовсе и плашка статуса не упиралась в край (замер показал зазор 0). */
  min-width: 1064px;
  grid-template-columns:
    minmax(108px, 0.85fr)  /* № */
    minmax(140px, 1.9fr)   /* Клиент */
    minmax(120px, 1.5fr)   /* Серия */
    56px                   /* Позиции */
    minmax(96px, 0.85fr)   /* Сумма */
    minmax(84px, 0.95fr)   /* Менеджер */
    84px                   /* Дата */
    84px                   /* Движение */
    92px                   /* На связь */
    100px;                 /* Статус */
  gap: var(--space-3);
  align-items: center;
  font-size: var(--text-base);
}

/* 🪤 ЗАМЕРЕНО В БРАУЗЕРЕ: подписи шапки стояли на 0,66 px левее своих ячеек. Причина не в
   сетке, а в РАМКЕ: у строки `border: 1px`, у шапки её не было, и внутренняя ширина у них
   отличалась на 2 px — доли колонок `fr` считаются от разной ширины. Прозрачная рамка той же
   толщины возвращает их к одному числу. Меньше пикселя глазами не видно, но именно так
   начинается «список поехал»: добавь кто-нибудь шапке отступ — и уедет уже заметно. */
.kp-qrow--head {
  padding: 0 var(--space-5) var(--space-2);
  border: 1px solid transparent;
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--c-text-muted);
}

.kp-qrow {
  padding: var(--space-3) var(--space-5);
  background: var(--c-card);
  border: 1px solid var(--c-border);
  border-radius: var(--radius);
  cursor: pointer;
  transition: border-color var(--tr-fast), box-shadow var(--tr-fast);
}

.kp-qrow:hover {
  border-color: var(--c-primary);
  box-shadow: var(--shadow-md);
}

/* Длинное имя клиента и длинное имя серии обязаны УРЕЗАТЬСЯ, а не раздвигать сетку: иначе одна
   строка списка ломает выравнивание всем остальным. Полный текст остаётся в подсказке. */
.kp-qrow__client,
.kp-qrow__series,
.kp-qrow__manager,
.kp-qrow__num {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.kp-qrow__num { font-weight: 600; font-variant-numeric: tabular-nums; }
.kp-qrow__client { font-weight: 500; }
.kp-qrow__series { color: var(--c-text-secondary); }
.kp-qrow__manager { color: var(--c-text-secondary); }

/* 🪤 [2026-09-11][CLX][КП-КАРТОЧКА] Насыщенность выше написана для ЯЧЕЕК ДАННЫХ и через общий
   класс попадала в шапку: «№» 600, «Клиент» 500, остальные восемь подписей — 400 (унаследовано
   от `.kp-qrow--head`). Подписи шапки должны быть одинаковы между собой — возвращаем этим двум
   тот же вес, что у остальных восьми, только внутри шапки; сами данные не тронуты. */
.kp-qrow--head .kp-qrow__num,
.kp-qrow--head .kp-qrow__client,
/* Тем же путём протекала и «Сумма» (`.kp-qrow__sum` ниже задан весом 600 для ЧИСЕЛ): осмотр
   глазами 11.09 нашёл её жирной, когда остальные восемь подписей уже были выровнены —
   правило починили не до конца, разнобой стал из трёх весов двумя. */
.kp-qrow--head .kp-qrow__sum { font-weight: 400; }

.kp-qrow__items,
.kp-qrow__sum,
.kp-qrow__date {
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.kp-qrow__sum { font-weight: 600; }
.kp-qrow__date { color: var(--c-text-muted); }
/* Ярлык статуса не тянется на всю колонку: растянутая плашка читается как кнопка. */
/* 🔴 СТАТУС ЗАКРЕПЛЁН У ПРАВОГО КРАЯ. Когда таблица всё-таки едет вбок (узкое окно), уезжать
   должна середина, а не то, по чему список читают глазами. Подложка обязательна — без неё
   уезжающие ячейки просвечивают сквозь закреплённую. */
.kp-qrow__status {
  justify-self: start;
  position: sticky;
  /* 🪤 ОТСТУП НЕ НОЛЬ, И ЭТО НЕ ПОДГОНКА. Закрепление отсчитывается от края ОБЛАСТИ
     ПРОКРУТКИ, а строка списка — карточка со своим полем 20 и рамкой 1. При `right: 0`
     ячейка вылезала за собственную строку ровно на 21 точку: замер 11.09 показал плашку,
     кончающуюся на 1416 при правом крае строки 1395, и нулевой зазор у «Отправлено».
     Число взято из тех же величин, что задают саму карточку, поэтому оно не разъедется. */
  right: calc(var(--space-5) + 1px);
  background: inherit;
  padding-left: var(--space-2);
  /* 🔴 СЛОЙ ПРОСТАВЛЕН ЯВНО, а не оставлен на `auto`. При `auto` закреплённая ячейка держится
     только тем, что позиционированный элемент рисуется поверх обычных соседей. Дай кто-нибудь
     однажды соседней ячейке `position` или `transform` — и уезжающее «Движение» поедет ПОВЕРХ
     статуса. Замечено осмотром 11.09 как «на будущее»; чинится дешевле сейчас, чем потом. */
  z-index: 2;
}
.kp-qrow--head .kp-qrow__status { background: var(--c-bg, var(--bg)); z-index: 3; }
.kp-qrow .kp-qrow__status { background: var(--c-card, var(--surface)); }

/* Шапка колонок над числовыми ячейками — по тому же правому краю, что и сами числа. */
.kp-qrow--head .kp-qrow__items,
.kp-qrow--head .kp-qrow__sum,
.kp-qrow--head .kp-qrow__date { text-align: right; }

/* [2026-09-06][CLX][КП-V1] Окна КП поверх слоя панели «Изменения цен».
   Панель ставит на весь экран прозрачный перехватчик нажатий (`.pn-ov`, z-index 1290,
   `price-notify.js:39`) — он нужен ей, чтобы клик мимо панели её откладывал. Но окна портала
   живут на z-index 200, то есть ПОД ним: пока панель цен висит, ни «Своя цена», ни
   «Проверьте перед выгрузкой» не нажимались вовсе — замерено в живом браузере, клик не доходил.
   Поднимаем окна КП над перехватчиком; сам перехватчик не трогаем, иначе сломается закрытие
   панели по клику мимо. */
#kp-overlay { z-index: 1300; }

/* ── [2026-09-08][CLX][ГАЛЕРЕЯ] Кадры серии для КП ───────────────────────────────────────────
   Решение Александра 08.09: «заменить фото» показывает кадры этой серии, первыми — подходящие
   под конкретное КП. Сетка, номер выбора, метка «подходит» и просмотр крупно. */
.kp-gal {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: var(--space-3);
  margin-top: var(--space-3);
  max-height: 52vh;
  overflow-y: auto;
}

.kp-gal__cell {
  position: relative;
  border: 1px solid var(--c-border);
  border-radius: var(--radius-sm, 6px);
  overflow: hidden;
  cursor: pointer;
  background: var(--c-surface, #fff);
  transition: border-color .12s ease, box-shadow .12s ease;
}
.kp-gal__cell:hover { border-color: var(--c-text-secondary); }
.kp-gal__cell.is-on { border-color: var(--c-primary, #b07a3c); box-shadow: 0 0 0 2px var(--c-primary, #b07a3c) inset; }
/* Кадр недоступен, пока у КП есть своё загруженное фото: сначала его убрать. */
.kp-gal__cell.is-off { opacity: .45; cursor: default; }

.kp-gal__cell img { width: 100%; height: 150px; object-fit: cover; display: block; }

/* Номер = порядок кадров в документе, а не просто галочка. */
.kp-gal__num:empty { display: none; }
.kp-gal__num {
  position: absolute; top: 6px; left: 6px;
  min-width: 22px; height: 22px; padding: 0 6px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 11px; background: var(--c-primary, #b07a3c); color: #fff;
  font-size: 12px; font-weight: 600; line-height: 1;
}

.kp-gal__badge {
  position: absolute; top: 6px; right: 6px;
  padding: 2px 7px; border-radius: 10px;
  background: rgba(0, 0, 0, .62); color: #fff;
  font-size: 11px; line-height: 1.4;
}

.kp-gal__why {
  display: block; padding: 5px 7px;
  font-size: 11px; color: var(--c-text-secondary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.kp-gal__zoom {
  position: absolute; right: 6px; bottom: 28px;
  width: 26px; height: 26px; border: 0; border-radius: 13px;
  background: rgba(0, 0, 0, .62); color: #fff; cursor: zoom-in;
  font-size: 13px; line-height: 1;
}

/* Просмотр крупно — поверх окна выбора (у окна z-index портала), чтобы выбор не терялся. */
.kp-zoom {
  /* [2026-09-18][CLX][СТИЛИ-ОДНО-МЕСТО] Этаж — из общей лестницы (`frontend-src/shared/ui.css`).
     Было 4000 — своё число мимо всякой лестницы: просмотр оказывался НА ОДНОМ ЭТАЖЕ с окнами, и кто кого перекроет, решал
     порядок правил в файле. Теперь просмотр заведомо выше окна — он из окна и открывается. */
  position: fixed; inset: 0; z-index: var(--z-lightbox);
  display: flex; align-items: center; justify-content: center;
  background: rgba(0, 0, 0, .78); cursor: zoom-out;
  padding: 24px;
}
.kp-zoom img { max-width: 92vw; max-height: 92vh; object-fit: contain; }
/* [2026-09-16][CLX][ЗАМЕЧАНИЯ-Б4] Галерея: стрелки по бокам, полоса отметки под кадром. */
.kp-zoom { cursor: default; gap: 12px; }
.kp-zoom__fig { margin: 0; display: flex; flex-direction: column; align-items: center; gap: 10px; min-width: 0; }
.kp-zoom__fig img { max-width: calc(100vw - 180px); max-height: calc(100vh - 110px); }
.kp-zoom__bar { display: flex; align-items: center; gap: 12px; color: #fff; font-size: 13px; flex-wrap: wrap; justify-content: center; }
.kp-zoom__count { font-variant-numeric: tabular-nums; opacity: .85; }
.kp-zoom__why { opacity: .85; max-width: 46vw; }
.kp-zoom .kp-zoom__pick { background: #fff; }
.kp-zoom__nav { flex: none; width: 52px; height: 52px; border-radius: 50%; border: 0; cursor: pointer;
  background: rgba(255, 255, 255, .16); color: #fff; font-size: 34px; line-height: 48px; }
.kp-zoom__nav:hover { background: rgba(255, 255, 255, .3); }


/* ───────────────────────────────────────────────────────────────────────────
 * [2026-09-08][CLX][СПИСОК-КП-ФИЛЬТРЫ] Панель отбора и колонка «Движение».
 *
 * Панель — строка подписанных полей, без рамок и коробок: отбор это оснастка, а не содержание
 * экрана. Ровно тем же приёмом сегодня разгружали «Обращения» — разделяет воздух, а не линия.
 *
 * «Движение» показывает, как давно по КП что-то делали. Холодной пометкой (двух недель молчания
 * достаточно, чтобы сделка остыла) красится ТОЛЬКО текст — не вся строка: подсветить строку
 * значит закричать, а таких КП со временем будет большинство, и крик перестанут слышать.
 * ─────────────────────────────────────────────────────────────────────────── */
.kp-qfilters {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--space-3) var(--space-4);
  margin: 0 0 var(--space-4);
}
.kp-qfilter { display: flex; flex-direction: column; gap: 3px; font-size: var(--text-sm); }
.kp-qfilter > span { color: var(--text-muted); font-size: var(--text-xs); }
.kp-qfilter select.input, .kp-qfilter input.input { min-width: 132px; }
.kp-qfilter--mine { flex-direction: row; align-items: center; gap: 6px; padding-bottom: 7px; }
.kp-qfilter--mine > span { color: var(--text); font-size: var(--text-sm); }
.kp-qfilters__count { margin-left: auto; color: var(--text-muted); font-size: var(--text-sm); padding-bottom: 7px; }

.kp-qrow__move { color: var(--text-muted); font-variant-numeric: tabular-nums; }
.kp-qrow__move.is-cold { color: var(--warning, #8A6A1F); }


/* ───────────────────────────────────────────────────────────────────────────
 * [2026-09-08][CLX][ОБРАТНАЯ-СВЯЗЬ] Колонка «На связь», кнопка среза и окно разговора.
 *
 * Состояния красятся ТЕКСТОМ, не заливкой строки: просроченных КП со временем станет
 * большинство, и подсвеченный список перестанут читать целиком. Кнопкой сделана вся ячейка —
 * менеджер целится в дату, а не в значок сбоку.
 * ─────────────────────────────────────────────────────────────────────────── */
.kp-contact {
  background: none; border: 0; padding: 2px 0; cursor: pointer;
  font: inherit; color: var(--text-muted); text-align: left;
  border-bottom: 1px dashed transparent;
}
.kp-contact:hover { border-bottom-color: currentColor; }
.kp-contact:focus-visible { outline: 2px solid var(--c-primary); outline-offset: 2px; border-radius: 2px; }
.kp-contact--overdue { color: #B23A2E; font-weight: 600; }
.kp-contact--today   { color: #8A6A1F; font-weight: 600; }
.kp-contact--missing { color: #8A6A1F; }
.kp-contact--soon    { color: var(--text); }
.kp-contact--new     { color: var(--text-muted); font-style: italic; }
/* Закрытая сделка: портал её больше не требует, и в списке она не кричит. */
.kp-contact--closed  { color: var(--text-muted); text-decoration: line-through; }

.kp-due {
  background: none; border: 1px solid var(--c-border); border-radius: 20px;
  padding: 5px 12px; font: inherit; font-size: var(--text-sm); cursor: pointer;
  color: var(--text-muted); align-self: flex-end;
}
.kp-due.is-hot { color: #B23A2E; border-color: currentColor; }
.kp-due.is-on { background: var(--c-primary); border-color: var(--c-primary); color: #fff; }
.kp-due:disabled { opacity: .55; cursor: default; }

.kp-ct__sub { color: var(--text-muted); font-size: var(--text-sm); margin-bottom: 12px; }
.kp-ct__hist { max-height: 220px; overflow-y: auto; margin-bottom: 16px; }
.kp-ct__item { padding: 8px 0; border-bottom: 1px solid var(--c-border); }
.kp-ct__item:last-child { border-bottom: 0; }
.kp-ct__meta { color: var(--text-muted); font-size: var(--text-xs); margin-bottom: 3px; }
.kp-ct__text { white-space: pre-wrap; }
.kp-ct__empty { color: var(--text-muted); font-style: italic; }
.kp-ct__field { display: block; margin-bottom: 12px; }
.kp-ct__field > span { display: block; font-size: var(--text-sm); color: var(--text-muted); margin-bottom: 4px; }
.kp-ct__field textarea.input { width: 100%; resize: vertical; }
.kp-ct__field--date input.input { width: 190px; }
.kp-ct__close { display: flex; align-items: center; gap: 8px; font-size: var(--text-sm); margin-bottom: 14px; }
.kp-ct__err { color: #B23A2E; font-size: var(--text-sm); margin-bottom: 10px; }
.kp-ct__actions { display: flex; justify-content: flex-end; gap: var(--space-3); }

/* ─────────────────────────────────────────────────────────────────────────────
   [2026-09-09][CLX][СТАТУСЫ-КП] Ярлык-кнопка и окно смены статуса.

   Ярлык остаётся ЯРЛЫКОМ на вид: тот же `.badge`, те же цвета статусов. Кнопкой он стал
   ради нажатия из списка, и выглядеть кнопкой не должен — иначе в строке появляется второй
   орган управления рядом с датой связи, и строка читается как панель, а не как запись.
   ───────────────────────────────────────────────────────────────────────────── */
.kp-status {
  border: 0;
  font: inherit;
  font-size: var(--text-xs);
  cursor: pointer;
  transition: box-shadow .12s ease, filter .12s ease;
}
/* 🪤 Найдено глазами 09.09: одного `brightness(.94)` на светло-сером ярлыке не видно вовсе —
   плашка выглядела мёртвой, и что она нажимается, выдавал только курсор. Обводка в тон текста
   заметна на ЛЮБОМ из пяти цветов, потому что берётся от самого ярлыка, а не задана числом. */
.kp-status:hover { filter: brightness(.96); box-shadow: 0 0 0 2px currentColor inset; }
.kp-status:focus-visible { outline: 2px solid var(--c-primary); outline-offset: 2px; }
/* Причина отказа под ярлыком в карточке КП. Она и есть то, ради чего заведены статусы, —
   поэтому стоит на виду, а не в подсказке. */
.kp-status__why { margin-top: 6px; font-size: var(--text-sm); color: var(--text-muted); }

.kp-st__opts { display: flex; flex-direction: column; gap: 2px; margin-bottom: 14px; }
.kp-st__opt {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px; border-radius: 8px; cursor: pointer;
}
.kp-st__opt:hover { background: var(--c-surface-2, #f6f6f5); }
.kp-st__opt.is-current { background: var(--c-surface-2, #f6f6f5); }
.kp-st__now { margin-left: auto; color: var(--text-muted); font-size: var(--text-xs); }
.kp-st__opt-note { color: #B23A2E; }
/* 🪤 `hidden` перебивается авторским `display` — этой граблёй в портале взаиморасчётов уже
   «не закрывалась» модалка. Блок причины отказа объявлен блочным, поэтому правило нужно
   именно здесь, а не в общем месте. */
.kp-st__lost[hidden] { display: none; }

/* ════════════════════════════════════════════════════════════════════════════════════════════
 * [2026-09-11][CLX][КАРКАС] Каркас страницы раздела КП — тот же, что у каталога.
 *
 * Решение Александра 11.09: сперва общее, потом частное. Строение задаёт общий на два раздела
 * `frontend-src/shared/PageShell.jsx`, здесь — только его ВИД под приставку `kp-page`.
 * У каталога то же самое живёт в `catalog-showroom.css` под приставкой `cat-sr`.
 *
 * Порядок частей один на оба раздела:
 *   toolbar — сколько нашли, поиск, вкладки статусов;
 *   strip   — применённые условия чипсами, каждое снимается крестиком;
 *   content — панель отбора СЛЕВА и колонка содержимого справа;
 *   main    — таблица, она же прокручивается; нижняя строка остаётся на виду.
 *
 * 🔴 ВЫСОТА СЧИТАЕТСЯ ОТ РОДИТЕЛЯ, И ЭТО НЕ КОСМЕТИКА. `height: 100%` у корня работает только
 * пока между ним и `#page-content` нет узла с `height: auto`. Ровно на этом 10.09 витрина
 * вытянулась на 2 790 px вместо 713, и нижняя строка уехала за край окна — вторая страница
 * стала недостижима. Обёртка острова поэтому объявлена `display: contents` (см. `main.jsx`).
 * ════════════════════════════════════════════════════════════════════════════════════════════ */

.kp-page {
  height: 100%;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

/* Верхняя полоса. Высота фиксирована: полоса статусов не должна менять её при переносе,
   иначе панель отбора слева прыгает — та же причина, по которой у каталога полоса серий
   живёт ВНУТРИ строки «Найдено», а не под ней.
   [2026-09-13][CLX][КП-ТАБЛИЦА] Числа — те же, что у `.cat-sr__toolbar`: отступ 8/16, подложка
   поверхности, счёт тем же кеглем. Два раздела рядом в одном меню не должны отличаться полосой. */
.kp-page__toolbar {
  display: flex;
  align-items: center;
  gap: var(--sr-space-3);
  min-height: 52px;
  padding: var(--sr-space-2) var(--sr-space-4);
  flex-wrap: nowrap;
  background: var(--surface);
  border-bottom: 1px solid var(--border-subtle, var(--c-border));
}
.kp-page__count { font-size: var(--sr-text-sm); color: var(--text-secondary); white-space: nowrap; flex-shrink: 0; }
.kp-page__count strong { color: var(--text); font-weight: 600; }

/* Строка применённых условий. Её нет, когда условий нет: пустая полоса с отступами — это
   полоса неизвестно чего. */
.kp-page__strip {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) 0;
}
.kp-page__chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 8px 3px 10px;
  border: 1px solid var(--c-border); border-radius: 999px;
  background: var(--c-card); color: var(--text);
  font-size: var(--text-xs); line-height: 1.6; cursor: pointer;
}
.kp-page__chip:hover { border-color: var(--accent); }
.kp-page__chip-label { color: var(--text-muted); }
.kp-page__chip-value { font-weight: 600; }
.kp-page__chip-x { color: var(--text-muted); font-size: 14px; line-height: 1; }
.kp-page__chip:hover .kp-page__chip-x { color: var(--accent); }
.kp-page__chip-all {
  border: 0; background: none; padding: 3px 4px;
  color: var(--text-muted); font-size: var(--text-xs); cursor: pointer; text-decoration: underline;
}
.kp-page__strip-note { color: var(--text-muted); font-size: var(--text-xs); }

.kp-page__content { flex: 1; display: flex; overflow: hidden; min-height: 0; }

/* [2026-09-13][CLX][КП-ТАБЛИЦА] Панель отбора слева — это панель каталога (`.cat-sr__filters`:
   ширина 260, прилипший верх, разделы с заголовком). Своего здесь только то, чего у каталога нет. */

/* Поиск переехал в панель, как у каталога. Общее правило `.kp-search` прежнего раздела делает
   обёртку флексом с нижним полем — в панели обёртка обязана быть коробкой для крестика. */
.kp-page__side .kp-search { display: block; margin-bottom: 0; }
/* Справа у поля один крестик, а не два значка, как у каталога: подсказке «Клиент, номер, серия»
   нужны её 56 точек отступа под текст, иначе она обрывается на «сер». */
.kp-page__side .kp-search .cat-sr__fsearch { padding-right: 32px; }

/* «На связь» — на месте «Применить» у каталога. Базовый `.kp-due` прежнего раздела — пилюля;
   здесь она получает вид кнопки панели, а смыслы подсветки те же: красный текст — пора звонить,
   заливка — отбор включён. */
.kp-page__side .kp-due {
  flex: 1; align-self: auto; text-align: center;
  border-radius: var(--radius); border: 1px solid var(--border);
  padding: 8px 10px; font-size: var(--sr-text-sm); font-weight: 500; color: var(--text);
  white-space: nowrap; min-width: 0;
}
/* «Сбросить всё» — по своей ширине: иначе делит строку поровну и сжимает «На связь» в три строки. */
.kp-page__side .cat-sr__factions--top .cat-sr__btn--ghost { flex: 0 0 auto; padding-left: 10px; padding-right: 10px; }
.kp-page__side .kp-due.is-hot { color: #B23A2E; border-color: currentColor; }
.kp-page__side .kp-due.is-on { background: var(--accent); border-color: var(--accent); color: var(--text-on-accent); }
.kp-page__side .kp-due:disabled { opacity: .55; cursor: default; }

/* Списки «один из» (менеджер, партнёр): радиокнопка тем же акцентом, что галочки заводов. */
.kp-qf__opt input { accent-color: var(--accent); cursor: pointer; }
.kp-qf__opt .cat-sr__brand-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Период: две даты столбиком — в строку по две при ширине панели поле даты не вмещает число. */
.kp-qf__period { display: flex; flex-direction: column; gap: var(--sr-space-2); }
.kp-qf__date { display: flex; align-items: center; gap: var(--sr-space-2); font-size: var(--sr-text-sm); }
.kp-qf__date > span { width: 22px; color: var(--text-muted); }
.kp-qf__date input {
  flex: 1; min-width: 0; padding: 6px 8px; border: 1px solid var(--border);
  border-radius: var(--radius-sm); font-size: var(--sr-text-sm); font-family: var(--sr-font-ui);
  background: var(--bg); color: var(--text); outline: none;
}
.kp-qf__date input:focus { border-color: var(--accent); }

.kp-page__main { flex: 1; display: flex; flex-direction: column; min-width: 0; min-height: 0; }
/* [2026-09-13][CLX][ПРИЧЁСКА] Нижняя строка КП — своей высоты. У каталога она держит 103 точки
   ВСЕГДА, потому что номера страниц переносят её во вторую строку и таблица иначе прыгала бы под
   курсором (`catalog-showroom.css`, «Нижняя строка»). У КП страниц нет, строка одна при любом отборе
   (замер 13.09: переключатели вида и сделок + «Показано…» занимают ~870 точек из 964 на 1280), и
   эти 103 точки были белой полосой в 46 точек под таблицей. */
.kp-page__bottom.cat-sr__bottombar { min-height: 0; }
/* [2026-09-13][CLX][КП-ТАБЛИЦА] Таблица и нижняя строка — классы каталога (`.cat-sr__table-wrap`,
   `.cat-sr__pagination`): прокручивается грид внутри себя, нижняя строка остаётся на виду.
   Прежние поля `.kp-page__table`/`.kp-page__bottom` подгонялись под столбик карточек и удалены. */

/* ── Ячейки таблицы КП ──
   🪤 Имя `kp-qgrid`, а не `kp-grid`: `.kp-grid` (сетка 3×, `display: grid`) уже занят блоком
   «Кому» карточки КП (`kp-draft.js`). Взятый взаймы класс сжал грид до 305 точек посреди экрана —
   поймано на стенде 13.09 глазами. */
.kp-qgrid__num { display: inline-flex; align-items: center; gap: 6px; min-width: 0; max-width: 100%; overflow: hidden; white-space: nowrap; }
.kp-page .ag-theme-quartz .kp-qgrid__cell--num { overflow: hidden; }
.kp-qgrid__no { font-weight: 600; font-variant-numeric: tabular-nums; }
/* Год — пометкой рядом с номером, не частью номера (решение Александра 13.09). */
.kp-qgrid__year { color: var(--text-muted); font-variant-numeric: tabular-nums; }
.kp-qgrid__deal-n { margin-left: 2px; }
.kp-qgrid__muted { color: var(--text-muted); }
.kp-qgrid__text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kp-qgrid__client { font-weight: 500; }
.kp-qgrid__n, .kp-qgrid__sum, .kp-qgrid__date { font-variant-numeric: tabular-nums; white-space: nowrap; }
.kp-qgrid__sum { font-weight: 600; }
.kp-qgrid__date { color: var(--text-muted); }
.kp-qgrid__move { color: var(--text-muted); font-variant-numeric: tabular-nums; white-space: nowrap; cursor: help; }
.kp-qgrid__move.is-cold { color: var(--warning, #8A6A1F); }
/* Строки второй и дальше редакций в развёрнутом показе — отбивка «└» без заливки; заливку
   раскрытия (как у исполнений каталога) получают только строки, открытые стрелкой. */
.kp-qgrid__lead { text-align: center; }
/* Сделки в развёрнутом показе отбиты чертой по верху первой строки сделки. Рамка у строки грида
   сдвинула бы высоту 44 — поэтому тень внутрь, она места не занимает. */
.kp-page .ag-theme-quartz .ag-row.kp-qgrid__row--deal-start { box-shadow: inset 0 2px 0 var(--border); }
/* Ярлык статуса в закреплённой колонке не тянется на всю ширину: растянутая плашка — кнопка. */
.kp-qgrid .kp-status { white-space: nowrap; }
.kp-qgrid .kp-contact { white-space: nowrap; }

/* [2026-09-11][CLX][НА-ОСНОВАНИИ] Полоса вариантов под шапкой карточки.
   Не плашка и не рамка: это оснастка, а не содержание. Текущий вариант подчёркнут снизу —
   тем же приёмом, что и активная вкладка статуса, чтобы не заводить на экране второй способ
   сказать «вы здесь». */
.kp-family {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: var(--space-2) var(--space-3);
  margin: 0 0 var(--space-3);
  font-size: var(--text-sm);
}
.kp-family__label { color: var(--text-muted); font-size: var(--text-xs); }
.kp-family__item {
  color: var(--text-secondary, var(--c-text-secondary));
  text-decoration: none; padding: 2px 0; border-bottom: 2px solid transparent;
}
.kp-family__item:hover { color: var(--accent); border-bottom-color: var(--c-border); }
.kp-family__item.is-here {
  color: var(--text); font-weight: 600; border-bottom-color: var(--accent); cursor: default;
}

/* [2026-09-11][CLX][ЦЕНА-БЕЗ-НАЦЕНКИ] Раскрытие строки позиции: из чего сложилась цена.
   Подробности — ПОЛНАЯ ширина под строкой (`grid-column: 1 / -1`), а не колонка сбоку:
   в сетке позиции колонки узкие, и таблица чисел в них не помещается. */
/* 🪤 [2026-09-11][CLX][ПОДРОБНЕЕ-НЕ-ТАМ] Кнопка была ДЕВЯТЫМ ребёнком сетки из восьми
   колонок и уезжала под номер позиции (правый край 181 px вместо места у цены 1219–1351).
   Теперь она внутри блока действий цены — там же, где «Своя цена», то есть в колонке цены
   и по смыслу, и по месту. */
.kp-item__more {
  border: 0; background: none; padding: 0;
  color: var(--text-muted); font-size: var(--text-xs);
  text-decoration: underline; text-underline-offset: 2px; cursor: pointer;
}
.kp-item__more:hover { color: var(--accent); }
.kp-item.is-open { background: var(--c-card); }

.kp-item__details {
  grid-column: 1 / -1;
  display: flex; flex-wrap: wrap; gap: var(--space-5);
  margin-top: var(--space-2); padding: var(--space-3) 0 var(--space-2);
  border-top: 1px dashed var(--c-border);
}
.kp-pd { border-collapse: collapse; font-size: var(--text-sm); min-width: 320px; }
.kp-pd td { padding: 3px 0; }
.kp-pd td:last-child { text-align: right; padding-left: var(--space-5); font-variant-numeric: tabular-nums; }
.kp-pd__use { cursor: pointer; }
.kp-pd__use:hover { color: var(--accent); }
.kp-pd__hint { color: var(--text-muted); font-size: var(--text-xs); font-weight: 400; }
.kp-pd__markup td { color: var(--text-muted); }
.kp-pd__now td { border-top: 1px solid var(--c-border); padding-top: 6px; }
.kp-pd__why { color: var(--text-muted); font-size: var(--text-xs); font-weight: 400; }

.kp-pd__hist { min-width: 320px; flex: 1; }
.kp-pd__hist-title {
  font-size: var(--text-xs); text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--text-muted); margin-bottom: var(--space-2);
}
.kp-pd__hist-row {
  display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-3);
  font-size: var(--text-sm); padding: 3px 0;
}
.kp-pd__hist-when { color: var(--text-muted); font-variant-numeric: tabular-nums; }
.kp-pd__hist-who { color: var(--text-secondary, var(--c-text-secondary)); }

/* 🪤 [2026-09-11][CLX][КП-КАРТОЧКА] Причина правки («Юля так решила») жила отдельным элементом
   ряда с `flex-basis: 100%` — во флекс-обёртке с `wrap` это значит «начни СВОЙ ряд с нуля»,
   поэтому причина падала к левому полю карточки (x=105), а не под текст «что» (x=229,7), рядом
   с которым она по смыслу стоит. Чтобы причина оказалась НЕ где угодно на новой строке, а
   именно под своим текстом, она теперь не сосед «что» по ряду, а его ребёнок в отдельной
   колонке (`.kp-pd__hist-what-wrap` в разметке `Items.jsx`) — тогда левый край сам равен левому
   краю текста, каким бы ни было «когда»/«кто» перед ним. */
.kp-pd__hist-what-wrap { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.kp-pd__hist-why { color: var(--text-muted); font-size: var(--text-xs); }

/* ════════════════════════════════════════════════════════════════════════════════════════════
 * [2026-09-13][CLX][СТАДИИ] Ярлык стадии сделки — вместо ярлыка статуса КП.
 *
 * Цвет — от ГРУППЫ стадии (продажа · исполнение · успех · проигрыш), а не от каждой из
 * девятнадцати: радуга из девятнадцати плашек не читается. «Отложили» — приглушённо: это ещё не
 * отказ. Тона — те же, что у прежних ярлыков (`components.css`), новых цветов нет.
 * Ярлык — кнопка (открывает окно стадии), но выглядит ярлыком, как прежде (урок 09.09).
 * ════════════════════════════════════════════════════════════════════════════════════════════ */
.kp-stage {
  display: inline-flex; align-items: center; max-width: 100%;
  padding: 2px 8px; border: 0; border-radius: 10px;
  font: inherit; font-size: var(--text-xs); font-weight: 500; line-height: 1.5;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  cursor: pointer; transition: box-shadow .12s ease, filter .12s ease;
  background: #f3f4f6; color: #6b7280;
}
.kp-stage:hover { filter: brightness(.96); box-shadow: 0 0 0 2px currentColor inset; }
.kp-stage:focus-visible { outline: 2px solid var(--c-primary); outline-offset: 2px; }
/* Модификатор — группа стадии (React) ИЛИ колонка доски (старые страницы, `quotes.js`/`kp-draft.js`
   ставят `kp-stage--<board_column>`): оба пути дают один цвет. */
.kp-stage--sales, .kp-stage--new, .kp-stage--details, .kp-stage--kp_sent, .kp-stage--wait_pay
                      { background: #dbeafe; color: #1e40af; }
.kp-stage--fulfilment, .kp-stage--supplier_bill, .kp-stage--ordered, .kp-stage--arrived,
.kp-stage--to_client, .kp-stage--done
                      { background: #fef3c7; color: #92400e; }
.kp-stage--won        { background: #d1fae5; color: #065f46; }
.kp-stage--lost       { background: #fee2e2; color: #991b1b; }
.kp-stage--postponed  { background: #f3f4f6; color: #4b5563; }
/* В закреплённой колонке таблицы длинное слово стадии обрезается многоточием — целиком оно
   в подсказке. Плашка не растягивается на всю ячейку. */
.kp-qgrid .kp-stage { display: inline-block; vertical-align: middle; }

/* ════════════════════════════════════════════════════════════════════════════════════════════
 * [2026-09-14][CLX][ДОСКА-V2] Окно подтверждения стадии (`StageDialog.jsx`).
 *
 * Решение Александра 14.09: каждый перенос и каждая смена стадии — через окно с «Подтвердить».
 * Обычно в окне стадии ОДНОЙ колонки (2–3 строки) — окно узкое; «Все стадии» раскладывает пять
 * колонок и три зоны сеткой 4×2, чтобы поле причины не уезжало за нижний край на 800 точках.
 * ════════════════════════════════════════════════════════════════════════════════════════════ */
.modal.kp-stage-dlg { width: 560px; max-width: calc(100vw - 32px); }
.modal.kp-stage-dlg:has(.kp-stage-dlg__opts--all) { width: 880px; }
.kp-stage-dlg__opts { display: flex; flex-direction: column; gap: 1px; margin-bottom: 12px; }
.kp-stage-dlg__opts--all {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px 12px; margin-bottom: 14px;
}
.kp-stage-dlg__group { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.kp-stage-dlg__gtitle {
  font-size: var(--text-xs); font-weight: 600; text-transform: uppercase; letter-spacing: .04em;
  color: var(--text-muted); padding: 2px 8px;
}
.kp-stage-dlg__group--zone .kp-stage-dlg__gtitle { border-top: 1px solid var(--border-subtle, var(--c-border)); padding-top: 6px; }
.kp-stage-dlg .kp-st__opt { padding: 5px 8px; gap: 8px; line-height: 1.3; }
.kp-stage-dlg .kp-st__now { flex-shrink: 0; }
.kp-stage-dlg__all {
  align-self: flex-start; margin: -4px 0 12px; padding: 2px 8px; border: 0; background: none;
  font: inherit; font-size: var(--text-sm); color: var(--accent-text, var(--accent));
  text-decoration: underline; text-underline-offset: 2px; cursor: pointer;
}
.kp-stage-dlg__all:focus-visible { outline: 2px solid var(--c-primary); outline-offset: 2px; }
.kp-stage-dlg__text { margin: 4px 0 14px; color: var(--text-secondary); line-height: 1.45; }
/* Счётчик знаков «Отложили»: красный, пока короче порога, приглушённый — когда хватает. */
.kp-stage-dlg__counter { display: block; margin-top: 4px; font-size: var(--text-xs); color: #B23A2E; font-variant-numeric: tabular-nums; }
.kp-stage-dlg__counter.is-enough { color: var(--text-muted); }

/* ════════════════════════════════════════════════════════════════════════════════════════════
 * [2026-09-13][CLX][КАНБАН] Доска сделок — второй вид `#/kp-r` (`QuotesBoard.jsx`).
 * 🔁 [2026-09-14][CLX][ДОСКА-V2] ПЯТЬ колонок на всю ширину, зоны итога внизу окна во время
 * переноса (контракт §4). Прежние девять колонок, блок итога справа и выбор проигрыша — удалены.
 *
 * Стоит на месте таблицы в том же каркасе: отбор слева, нижняя строка на виду. Прокручивается
 * ВНУТРИ СЕБЯ; шапка колонки прилипает к верху — число и сумма видны при любой прокрутке.
 * Колонки делят ширину поровну, но не уже 212 точек: на 1440 все пять встают без прокрутки
 * (замер 14.09: при 224 пятая уходила за край на 52 точки), на 1280 доска прокручивается вбок,
 * а не сжимает карточку до нечитаемой.
 * ════════════════════════════════════════════════════════════════════════════════════════════ */
.kp-page__board {
  flex: 1; min-height: 0; min-width: 0; display: flex; overflow: hidden; position: relative;
  background: var(--bg-secondary, #f6f6f5);
}
.kp-board__scroll { flex: 1 1 auto; min-width: 0; min-height: 0; overflow: auto; position: relative; }
.kp-board--empty { display: flex; align-items: center; justify-content: center; }
.kp-board__stray {
  position: sticky; left: 0; margin: 8px 12px 0; padding: 6px 10px; border-radius: var(--radius-sm);
  background: #fef3c7; color: #92400e; font-size: var(--sr-text-sm); width: max-content;
}
.kp-board__lanes {
  display: flex; align-items: stretch; gap: 8px;
  padding: 8px 12px 12px; min-width: 100%; min-height: 100%; box-sizing: border-box;
}
.kp-board__lane {
  flex: 1 0 212px; min-width: 212px; display: flex; flex-direction: column;
  border-radius: var(--radius); background: var(--surface);
  border: 1px solid var(--border-subtle, var(--c-border));
  transition: box-shadow .12s ease, border-color .12s ease;
}
.kp-board__lane.is-over { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent) inset; }

.kp-board__head {
  position: sticky; top: 0; z-index: 2;
  display: grid; grid-template-columns: 1fr auto; align-items: baseline; gap: 2px 8px;
  width: 100%; padding: 8px 10px; text-align: left; box-sizing: border-box;
  border-bottom: 1px solid var(--border-subtle, var(--c-border));
  border-radius: var(--radius) var(--radius) 0 0;
  background: var(--surface); color: var(--text);
}
.kp-board__title {
  font-size: var(--sr-text-sm); font-weight: 600;
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.kp-board__count { font-size: var(--sr-text-xs); color: var(--text-muted); font-variant-numeric: tabular-nums; }
.kp-board__csum {
  grid-column: 1 / -1; font-size: var(--sr-text-xs); color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}

.kp-board__cards { display: flex; flex-direction: column; gap: 6px; padding: 6px; flex: 1 1 auto; min-height: 64px; }
.kp-board__none { color: var(--text-muted); font-size: var(--sr-text-xs); text-align: center; padding: 16px 0; }

.kp-board__card {
  position: relative;
  display: flex; flex-direction: column; gap: 4px;
  padding: 8px 10px; border-radius: var(--radius-sm);
  background: var(--surface); border: 1px solid var(--border-subtle, var(--c-border));
  font-size: var(--sr-text-sm); color: var(--text); cursor: grab;
  transition: border-color .12s ease, box-shadow .12s ease, opacity .12s ease;
}
.kp-board__card:hover { border-color: var(--accent); box-shadow: 0 1px 3px rgba(0, 0, 0, .06); }
.kp-board__card:active { cursor: grabbing; }
.kp-board__card:focus-visible { outline: 2px solid var(--c-primary); outline-offset: 1px; }
/* Цвет карточки — ТОЛЬКО по датам (решение Александра 14.09): жёлтый — срок сегодня, красный —
   прошёл; без срока — без цвета. Полоска слева + лёгкая заливка тех же тонов, что дата связи
   (`.kp-contact--today/--overdue`) и тема портала (`--warning-light`, `--error-light`). */
.kp-board__card[data-attention="today"] {
  background: var(--warning-light, #FBF3E4);
  border-color: color-mix(in srgb, #8A6A1F 35%, transparent);
  box-shadow: inset 3px 0 0 #C4912A;
}
.kp-board__card[data-attention="overdue"] {
  background: var(--error-light, #F9EDEC);
  border-color: color-mix(in srgb, #B23A2E 35%, transparent);
  box-shadow: inset 3px 0 0 #B23A2E;
}
.kp-board__card[data-attention]:not([data-attention=""]):hover { border-color: var(--accent); }

.kp-board__client { font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kp-board__line { display: flex; align-items: center; gap: 6px; min-width: 0; }
.kp-board__line--top .kp-board__client { flex: 1 1 auto; }
/* Метка стадии — ярлык `.kp-stage` (цвет колонки старой раскладки), короче на карточке. */
/* `inline-block`, а не флекс ярлыка: многоточие у текста внутри флекс-контейнера не рисуется. */
/* [2026-09-15][CLX][ДОСКА-V2-ПРИЁМКА] Метка стоит СВОЕЙ строкой под именем клиента и может занять всю
   ширину карточки (было `max-width: 58%` рядом с именем — обрезалась на 16–18 карточках из 18). */
.kp-board__stage-chip { display: inline-block; flex: 0 1 auto; min-width: 0; max-width: 100%; padding: 1px 7px; font-size: 11px; line-height: 1.5; }
.kp-board__line--sub, .kp-board__line--foot { font-size: var(--sr-text-xs); color: var(--text-secondary); }
.kp-board__deal { font-weight: 500; font-variant-numeric: tabular-nums; white-space: nowrap; }
.kp-board__muted { color: var(--text-muted); white-space: nowrap; }
.kp-board__sum { margin-left: auto; font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
.kp-board__series { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kp-board__manager { margin-left: auto; white-space: nowrap; color: var(--text-muted); }
.kp-board__move { color: var(--text-muted); white-space: nowrap; cursor: help; }
.kp-board__move.is-cold { color: var(--warning, #8A6A1F); font-weight: 600; }
.kp-board__line--foot { position: relative; min-height: 20px; }
.kp-board__line--foot .kp-contact { margin-left: auto; white-space: nowrap; font-size: var(--sr-text-xs); }
.kp-board__err { color: #B23A2E; font-size: var(--sr-text-xs); line-height: 1.35; }

/* Строка дела: дата и что сделать (слова сервера). */
.kp-board__todo { display: flex; align-items: baseline; gap: 6px; min-width: 0; font-size: var(--sr-text-xs); color: var(--text-secondary); }
.kp-board__todo-date { font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
.kp-board__card[data-attention="today"] .kp-board__todo-date { color: #8A6A1F; }
.kp-board__card[data-attention="overdue"] .kp-board__todo-date { color: #B23A2E; }
/* [2026-09-15][CLX][ДОСКА-V2-ПРИЁМКА] «Что сделать» переносится на вторую строку: в одну строку главное
   слово терялось («Подтверждение поста…», «Вернуться к отложенн…», приёмка 15.09, находка 4). Больше
   двух строк не бывает — третья обрезается многоточием, полный текст в подсказке строки. */
.kp-board__todo-text {
  min-width: 0; overflow: hidden; white-space: normal; overflow-wrap: anywhere;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2;
}

/* Быстрые действия — ПОВЕРХ нижней строки, при наведении и фокусе. Не `display`: карточка не
   меняет высоту, и колонка не прыгает под мышью. `visibility` вместо одной прозрачности —
   скрытые кнопки не ловят щелчок и не стоят в порядке Tab, пока карточка не в фокусе. */
.kp-board__quick {
  position: absolute; inset: -3px -4px; z-index: 1;
  display: flex; align-items: center; justify-content: flex-end; gap: 3px;
  background: inherit; border-radius: var(--radius-sm);
  opacity: 0; visibility: hidden; transition: opacity .12s ease, visibility 0s linear .12s;
}
.kp-board__card .kp-board__quick { background: var(--surface); }
.kp-board__card[data-attention="today"] .kp-board__quick { background: var(--warning-light, #FBF3E4); }
.kp-board__card[data-attention="overdue"] .kp-board__quick { background: var(--error-light, #F9EDEC); }
.kp-board__card:hover .kp-board__quick,
.kp-board__card:focus-within .kp-board__quick { opacity: 1; visibility: visible; transition: opacity .12s ease; }
.kp-board.is-dragging .kp-board__quick { opacity: 0; visibility: hidden; }
.kp-board__quick button {
  flex: 1 1 0; min-width: 0; justify-content: center;
  display: inline-flex; align-items: center; gap: 3px; height: 22px; padding: 0 4px;
  border: 1px solid var(--border-subtle, var(--c-border)); border-radius: var(--radius-sm);
  background: var(--surface); font: inherit; font-size: 11px; font-weight: 500;
  color: var(--text-secondary); cursor: pointer; white-space: nowrap;
}
.kp-board__quick button:hover { border-color: var(--accent); color: var(--accent); }
.kp-board__quick button:focus-visible { outline: 2px solid var(--c-primary); outline-offset: 1px; }
.kp-board__quick svg { display: block; flex: none; }
/* На узкой карточке (224 точки колонки) три подписи со значками не помещаются — значки прячем,
   подписи остаются: слово понятнее значка. На широкой колонке значки видны. */
@container kpcard (max-width: 240px) { .kp-board__quick svg { display: none; } }
.kp-board__card { container: kpcard / inline-size; }

/* Зоны итога — полоса внизу окна, только во время переноса (узлы появляются ветвлением).
   Стоят в `body` (портал React), поэтому правила НЕ под `.kp-page`. Сама полоса мышь не ловит —
   ловят только три зоны: между ними карточку можно вести к нижним карточкам колонок.
   Цвета — тона ярлыков стадий `kp-stage--won/--postponed/--lost`. */
.kp-board__zones {
  /* Выше кнопки помощника «?» (`help-hub.css`, z-index 2401, правый нижний угол): иначе она
     накрывала правый край «Проиграна», и бросок туда не принимался. Полоса живёт только во время
     переноса — помощник в это время не нужен. */
  position: fixed; bottom: 16px; z-index: 2450;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px;
  padding: 0 12px; box-sizing: border-box; pointer-events: none;
}
.kp-board__zone {
  pointer-events: auto;
  display: flex; align-items: center; justify-content: center; gap: 10px;
  height: 72px; border-radius: var(--radius); border: 2px dashed currentColor;
  font-size: var(--sr-text-sm, 14px); font-weight: 600;
  box-shadow: 0 6px 20px rgba(0, 0, 0, .12);
  transition: transform .12s ease, box-shadow .12s ease;
}
.kp-board__zone--won       { background: #d1fae5; color: #065f46; }
.kp-board__zone--postponed { background: #f3f4f6; color: #4b5563; }
.kp-board__zone--lost      { background: #fee2e2; color: #991b1b; }
.kp-board__zone.is-over { border-style: solid; transform: translateY(-3px); box-shadow: 0 10px 28px rgba(0, 0, 0, .2); }
.kp-board__zone-count { font-weight: 500; font-variant-numeric: tabular-nums; opacity: .8; }

/* ════════════════════════════════════════════════════════════════════════════════════════════
 * [2026-09-14][CLX][СЕГОДНЯ] Плашка «Сегодня» над таблицей и доской (`TodayPlate.jsx`).
 * Открыта целиком первый раз за день, потом — одна строка со счётом. Список ограничен по высоте:
 * двадцать дел не должны выталкивать таблицу за нижний край.
 * ════════════════════════════════════════════════════════════════════════════════════════════ */
.kp-today {
  flex: 0 0 auto; margin: 8px 12px 0;
  border: 1px solid var(--border-subtle, var(--c-border)); border-radius: var(--radius);
  background: var(--surface); font-size: var(--sr-text-sm);
}
.kp-page--board .kp-today { margin-bottom: 0; }
.kp-today[data-state="closed"] { display: flex; align-items: center; gap: 10px; padding: 0; }
.kp-today__bar { display: flex; align-items: center; gap: 10px; flex: 1; min-height: 38px; padding: 4px 12px; }
.kp-today[data-state="closed"] > .kp-today__title,
.kp-today[data-state="closed"] > .kp-today__muted { padding: 10px 0 10px 12px; }
.kp-today__title { font-weight: 600; }
.kp-today__count {
  min-width: 22px; height: 20px; padding: 0 6px; border-radius: 10px; box-sizing: border-box;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--bg-secondary, #f6f6f5); font-size: var(--sr-text-xs); font-weight: 600; font-variant-numeric: tabular-nums;
}
.kp-today__count.is-overdue { background: #fee2e2; color: #991b1b; }
.kp-today__sum { font-size: var(--sr-text-xs); }
.kp-today__overdue { color: #B23A2E; font-weight: 600; }
.kp-today__due { color: #8A6A1F; font-weight: 600; }
.kp-today__muted { color: var(--text-muted); font-size: var(--sr-text-xs); }
.kp-today__toggle {
  margin-left: auto; border: 0; background: none; padding: 2px 0;
  font: inherit; font-size: var(--sr-text-xs); color: var(--text-secondary);
  text-decoration: underline; text-underline-offset: 2px; cursor: pointer;
}
.kp-today__toggle:hover { color: var(--accent); }
.kp-today__list {
  list-style: none; margin: 0; padding: 4px 6px 6px; max-height: 188px; overflow-y: auto;
  border-top: 1px solid var(--border-subtle, var(--c-border));
}
.kp-today__item {
  display: flex; align-items: baseline; gap: 12px; width: 100%; padding: 6px;
  border: 0; border-radius: var(--radius-sm); background: none; text-align: left;
  font: inherit; font-size: var(--sr-text-sm); color: var(--text); cursor: pointer;
}
.kp-today__item:hover { background: var(--bg-secondary, #f6f6f5); }
.kp-today__item:focus-visible { outline: 2px solid var(--c-primary); outline-offset: -2px; }
.kp-today__when { flex: 0 0 124px; font-size: var(--sr-text-xs); font-weight: 600; white-space: nowrap; }
.kp-today__item.is-overdue .kp-today__when { color: #B23A2E; }
.kp-today__item.is-today .kp-today__when { color: #8A6A1F; }
.kp-today__client { flex: 0 1 220px; min-width: 0; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kp-today__text { flex: 1 1 auto; min-width: 0; color: var(--text-secondary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kp-today__manager, .kp-today__date { flex: 0 0 auto; color: var(--text-muted); font-size: var(--sr-text-xs); white-space: nowrap; }

/* ════════════════════════════════════════════════════════════════════════════════════════════
 * [2026-09-14][CLX][ДОСКА-V2] Панель отбора: быстрые кнопки, «Стадия» по колонкам, «Мои виды».
 * ════════════════════════════════════════════════════════════════════════════════════════════ */
.kp-page__side .kp-qf__quick { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
.kp-page__side .kp-qf__quick .kp-qf__qbtn--attention { grid-column: 1 / -1; }
.kp-page__side .kp-qf__qbtn {
  padding: 8px 10px; font-size: var(--sr-text-sm); font-weight: 500;
  white-space: nowrap; min-width: 0; overflow: hidden; text-overflow: ellipsis;
}
.kp-page__side .kp-qf__qbtn.is-hot { color: #B23A2E; border-color: currentColor; }
.kp-page__side .kp-qf__qbtn.is-on { background: var(--accent); border-color: var(--accent); color: var(--text-on-accent); }
.kp-page__side .kp-qf__quick .kp-due { padding-left: 8px; padding-right: 8px; }
.kp-page__side .kp-qf__quick .cat-sr__btn--ghost { justify-self: start; }
/* `.quotes-status-tabs` у раздела — переходный класс для шага обучения; его общее правило
   (`components.css`: флекс с переносом) раскладку раздела не задаёт. */
.kp-page__side .kp-qf__stages.quotes-status-tabs { display: block; }
/* 🪤 Панель — флекс-контейнер: раздел с длинными строками без переноса («Другой регион, доставка ТК
   не подходит») растягивался по самой длинной строке до 300 точек, и числа у стадий уезжали за
   край панели (поймано снимком стенда 14.09). Разделу разрешено быть уже своего содержимого. */
.kp-page__side .kp-qf__stages, .kp-page__side .kp-qf__views { min-width: 0; max-width: 100%; }
.kp-qf__lane + .kp-qf__lane { margin-top: 4px; }
.kp-qf__lane--lane + .kp-qf__lane--zone {
  margin-top: 10px; padding-top: 8px; border-top: 1px solid var(--border-subtle, var(--c-border));
}
.kp-qf__lane-head .cat-sr__brand-name { font-weight: 600; }
.kp-qf__lane-head--won .cat-sr__brand-name { color: #065f46; }
.kp-qf__lane-head--lost .cat-sr__brand-name { color: #991b1b; }
.kp-qf__lane-head--postponed .cat-sr__brand-name { color: #4b5563; }
.kp-qf__lane-stages { padding-left: 18px; }
.kp-qf__overdue {
  margin-left: auto; margin-right: 6px; min-width: 18px; padding: 0 5px; border-radius: 9px;
  background: #fee2e2; color: #991b1b; font-size: var(--sr-text-xs); font-weight: 600;
  text-align: center; font-variant-numeric: tabular-nums;
}
.kp-qf__view-list { list-style: none; margin: 0 0 8px; padding: 0; display: flex; flex-direction: column; gap: 2px; }
.kp-qf__view { display: flex; align-items: center; gap: 4px; }
.kp-qf__view-apply {
  flex: 1; min-width: 0; padding: 5px 8px; border: 1px solid transparent; border-radius: var(--radius-sm);
  background: none; text-align: left; font: inherit; font-size: var(--sr-text-sm); color: var(--text);
  cursor: pointer; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.kp-qf__view-apply:hover { background: var(--bg-secondary, #f6f6f5); color: var(--accent); }
.kp-qf__view-x {
  flex: none; width: 22px; height: 22px; border: 0; border-radius: var(--radius-sm); background: none;
  color: var(--text-muted); font-size: 16px; line-height: 1; cursor: pointer;
}
.kp-qf__view-x:hover { color: #B23A2E; background: var(--bg-secondary, #f6f6f5); }
.kp-qf__view-new { display: flex; flex-direction: column; gap: 6px; }
.kp-page__side .kp-qf__view-name { width: 100%; box-sizing: border-box; padding-right: 10px; }
.kp-qf__hint { color: var(--text-muted); font-size: var(--sr-text-xs); line-height: 1.4; margin-bottom: 8px; }
.kp-qf__view-err { color: #B23A2E; font-size: var(--sr-text-xs); margin-top: 4px; }

/* Таблица: дата связи окрашена по вниманию сервера — тот же признак, что у карточки доски. */
.kp-qgrid .kp-contact[data-attention="today"] { color: #8A6A1F; font-weight: 600; }
.kp-qgrid .kp-contact[data-attention="overdue"] { color: #B23A2E; font-weight: 600; }

/* ════════════════════════════════════════════════════════════════════════════════════════════
 * [2026-09-14][CLX][ОТМЕТКИ] Окно отметок сделки (`MarkDialog.jsx`).
 * ════════════════════════════════════════════════════════════════════════════════════════════ */
.modal.kp-mark-dlg { width: 600px; max-width: calc(100vw - 32px); }
.kp-mark-dlg__list { max-height: 260px; overflow-y: auto; }
.kp-mark-dlg__item { padding: 8px 0; border-bottom: 1px solid var(--border-subtle, var(--c-border)); }
.kp-mark-dlg__item:last-child { border-bottom: 0; }
.kp-mark-dlg__head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.kp-mark-dlg__kind { font-weight: 600; }
.kp-mark-dlg__date, .kp-mark-dlg__amount { color: var(--text-secondary); font-variant-numeric: tabular-nums; }
.kp-mark-dlg__cancel {
  margin-left: auto; padding: 0; border: 0; background: none;
  font: inherit; font-size: var(--text-xs); color: var(--text-muted); text-decoration: underline; cursor: pointer;
}
.kp-mark-dlg__cancel:hover { color: #B23A2E; }
.kp-mark-dlg__item.is-cancelled .kp-mark-dlg__kind,
.kp-mark-dlg__item.is-cancelled .kp-mark-dlg__date,
.kp-mark-dlg__item.is-cancelled .kp-mark-dlg__amount { color: var(--text-muted); text-decoration: line-through; }
.kp-mark-dlg__confirm {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 6px; padding: 8px 10px;
  border-radius: var(--radius-sm); background: var(--error-light, #F9EDEC); font-size: var(--text-sm);
}
.kp-mark-dlg__form { margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--border-subtle, var(--c-border)); }
.kp-mark-dlg__form .kp-stage-dlg__gtitle { padding-left: 0; margin-bottom: 6px; }
.kp-mark-dlg__row { display: flex; gap: 12px; flex-wrap: wrap; }
.kp-mark-dlg__row .kp-ct__field { flex: 1 1 180px; }

/* ════════════════════════════════════════════════════════════════════════════════════════════
 * [2026-09-14][CLX][Б24-СВЯЗЬ] Шаг «Сделка в Битриксе» в окне перед выгрузкой (`B24LinkStep.jsx`).
 * ════════════════════════════════════════════════════════════════════════════════════════════ */
.kp-b24-step { margin-top: 14px; padding-top: 10px; border-top: 1px solid var(--border-subtle, var(--c-border)); }
.kp-b24-step__deals { list-style: none; margin: 6px 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.kp-b24-step__deal {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "t b" "m b";
  gap: 0 10px; align-items: center; padding: 6px 8px;
  border: 1px solid var(--border-subtle, var(--c-border)); border-radius: var(--radius-sm);
}
.kp-b24-step__deal-title { grid-area: t; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kp-b24-step__deal-meta { grid-area: m; color: var(--text-muted); font-size: var(--text-xs); }
.kp-b24-step__deal .btn { grid-area: b; }
.kp-b24-step__acts { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 8px; }
.kp-b24-step__err { margin-top: 6px; color: #B23A2E; font-size: var(--text-sm); }
.kp-b24-step__done { color: #065f46; font-size: var(--text-sm); }

/* ════════════════════════════════════════════════════════════════════════════════════════════
 * [2026-09-13][CLX][ПРИЧЁСКА] Карточка КП (`#/kp-r/<id>`) — одно полотно, как у списка и каталога.
 *
 * Слово Александра 13.09: «надо максимально качественно причесать дизайн разделов». До правки
 * карточка была стопкой из четырёх отдельных плашек (рамка, скругление 6 px, поле 24 px, зазоры
 * 16–20 px) на бежевом фоне с рамкой страницы 24/20 px — заметно «воздушнее» списка, где полотно
 * одно и части разделены волосяной чертой.
 *
 * Что сделано: блоки НЕ переставлены и не пересобраны — у тех же `.detail-card` сняты рамка,
 * скругление и зазоры, каждый отбит снизу волосяной чертой; поле внутри — 16 px по краям, как у
 * полосы «Найдено» списка (текст начинается на той же вертикали, что счёт найденного в списке).
 * Шапка карточки — полоса высотой 52 точки, как верхняя полоса списка и каталога.
 *
 * Весь блок ограничен классом адреса (`app.js` → `.content--kp-card`): `.detail-card` — общий класс
 * портала, в проектах и калькуляторе его вид прежний.
 * ════════════════════════════════════════════════════════════════════════════════════════════ */
.kp-cond-card { margin-bottom: var(--space-5); }

#page-content.content--kp-card { background: var(--surface); }
#page-content.content--kp-card > .kp-react-root { min-height: 100%; background: var(--surface); }

.content--kp-card .kp-head {
  min-height: 52px; margin: 0;
  padding: var(--sr-space-2, 8px) var(--space-4);
  border-bottom: 1px solid var(--border-subtle, var(--c-border));
  gap: var(--space-2) var(--space-4);
}
/* Полоса шапки — одна средняя линия: у ссылки «← Список КП» и подписи «Стадия» остались нижние поля
   их прежних мест (16 и 4 точки), и они стояли на 8 и 2 точки выше номера и ярлыка стадии. */
.content--kp-card .kp-head .back-link,
.content--kp-card .kp-head .calc-field__label { margin: 0; }
.content--kp-card .kp-family {
  margin: 0; padding: var(--space-2) var(--space-4);
  border-bottom: 1px solid var(--border-subtle, var(--c-border));
}
.content--kp-card .kp-flash {
  margin: var(--space-3) var(--space-4);
}
.content--kp-card .detail-card {
  margin: 0;
  padding: var(--space-4);
  border: 0;
  border-bottom: 1px solid var(--border-subtle, var(--c-border));
  border-radius: 0;
  background: var(--surface);
}
.content--kp-card .detail-card:last-child { border-bottom: 0; }
.content--kp-card .detail-section__title { margin-bottom: var(--space-3); }
.content--kp-card .kp-work__photo { margin-top: var(--space-4); }

/* [2026-09-16][CLX][ОСТАТОК-В-КП] Метка «на складе завода» в строке КП и окно разбора. */
.kp-item__stock { border: 1px solid #b9d8c0; background: #eef7f0; color: #2e6b3e; border-radius: 10px;
  padding: 1px 8px; font-size: 12px; line-height: 18px; cursor: pointer; white-space: nowrap; }
.kp-item__stock:hover { background: #ddefe1; }
.kp-stock-modal { max-width: 640px; width: 92vw; }
.kp-stock-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.kp-stock-table th, .kp-stock-table td { padding: 6px 8px; border-bottom: 1px solid var(--border, #e5e5e5); text-align: left; }
.kp-stock-table th { font-weight: 600; color: var(--text-secondary, #666); }
.kp-stock-note { margin-top: 10px; font-size: 12px; color: var(--text-secondary, #666); }

/* ── [2026-09-18][CLX][ТЕСТОВЫЕ-КП] Отметка «тестовое КП» (замечание Г2) ─────────────────────────
   Полоса действий над таблицей, окно подтверждения по чужим КП и плашка уведомлений владельцу.
   Цвета — только токенами палитры (`client/css/themes.css`); вид окна задаёт общее окно портала
   (`frontend-src/shared/ui.css`), здесь — только СОДЕРЖИМОЕ раздела КП. */

.kp-testbar {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin: 0 0 10px; padding: 8px 12px;
  background: var(--accent-subtle); border: 1px solid var(--accent-light);
  border-radius: var(--radius); font-size: var(--text-sm);
}
.kp-testbar__count { font-weight: 600; margin-right: 4px; }

.kp-testdlg__list {
  margin: 10px 0; padding: 0 0 0 18px; max-height: 180px; overflow-y: auto;
  font-size: var(--text-sm); line-height: 1.6;
}
.kp-testdlg__label { display: block; margin-top: 12px; font-size: var(--text-xs); color: var(--text-muted); }
.kp-testdlg__input {
  width: 100%; margin-top: 4px; padding: 8px 10px; resize: vertical;
  font: inherit; color: var(--text);
  background: var(--bg-input); border: 1px solid var(--border); border-radius: var(--radius);
}
.kp-testdlg__input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* Плашка уведомлений: не окно. Окно перекрывает работу и закрывается рефлексом — плашка ждёт. */
.kp-notices { display: flex; flex-direction: column; gap: 6px; margin-bottom: 10px; }
.kp-notices__row {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 8px 12px; font-size: var(--text-sm);
  background: var(--info-light); border: 1px solid var(--info); border-radius: var(--radius);
}
/* [2026-09-21][CLX][КП-V2] «Тесная связь» клиента (та же категория) — заметнее обычной */
.kp-notices__row--tight { border-width: 2px; font-weight: 500; }
.kp-notices__text { flex: 1; min-width: 200px; }
.kp-notices__why { display: block; color: var(--text-secondary); font-style: italic; }

/* Метка учебного КП в колонке номера — там, где у настоящего КП стоит номер. */
.kp-qgrid__test {
  margin-left: 6px; padding: 1px 6px; border-radius: var(--radius-full);
  background: var(--warning-light); color: var(--text);
  font-size: var(--text-xs); font-weight: 600; white-space: nowrap;
}

/* [2026-09-21][CLX][КП-V2] Окно просмотра PDF (§22 п.4): почти во весь экран, страницы рисует pdf.js
   в canvas столбиком, прокрутка — у тела окна; кнопки масштаба — в шапке. */
.modal.kp-preview { width: min(1100px, calc(100vw - 40px)); height: 92vh; max-height: 92vh; }
.kp-preview .modal__body { overflow: auto; background: var(--c-bg); }
.kp-preview__pages { display: flex; flex-direction: column; align-items: center; gap: var(--space-3); padding: 16px; min-width: min-content; }
.kp-preview__page { display: block; background: #fff; box-shadow: 0 1px 4px rgba(0, 0, 0, .18); }
.kp-preview__tools { display: flex; align-items: center; gap: var(--space-2); }
.kp-preview__tools .btn svg { display: block; }
.kp-preview__zoom { min-width: 76px; text-align: center; font-variant-numeric: tabular-nums; }
.kp-preview__nopdf { padding: var(--space-4, 20px); }

/* ══════════════════════════════════════════════════════════════════════════════════════════════
   [2026-09-21][CLX][КП-V2] Дорожка R1: экран «одна серия» (`frontend-src/kp/v2/*`, открывается по `?v2=1`).
   Все правила — под `.kp2`, прежняя карточка КП (`.kp-head`, `.kp-brief`, `.kp-work`…) не задета.
   Вид — с одобренного прототипа (`client/kp-v2-proto/proto.css`): один шрифт портала, два веса, три тона
   текста; «надо заполнить» — оранжевый из токена `--warning`, не тревожный красный (§1).
   ══════════════════════════════════════════════════════════════════════════════════════════════ */
.kp2, .kp2-headbar, .kp2-floor {
  --kp2-need: var(--warning, #C4912A);
  --kp2-need-bg: var(--warning-light, #FBF3E4);
  --kp2-need-text: #8A6414;          /* контраст на --kp2-need-bg ≥ 4.5 (прототип) */
  --kp2-ok: var(--success, #6B8F71);
  --kp2-ok-bg: var(--success-light, #EDF3EE);
  --kp2-ok-text: #4F6E55;
  --kp2-ink: var(--text, #2C2420);
  --kp2-ink-2: var(--text-secondary, #6B5E54);
  --kp2-ink-3: var(--text-muted, #9C8E82);
  --kp2-line: var(--border, #E4DDD4);
  --kp2-card: var(--surface, #FFFFFF);
  --kp2-acc: var(--accent, #B87333);
  --kp2-acc-bg: var(--accent-light, #F5E6D3);
  font-family: var(--font-ui, 'DM Sans', 'Segoe UI', sans-serif); font-size: 13px; line-height: 18px; color: var(--kp2-ink);
}
/* [2026-09-23][CLX][КП-ШАПКА] Токены — общие у экрана и у его строки в полосе портала (`.kp2-headbar`, вне `.kp2`).
   [2026-09-23][CLX][КП-ШАПКА-A] + нижний этаж `.kp2-floor`; сама шапка — `frontend-src/kp/v2/head.css`. */
.kp2 {
  display: flex; flex-direction: column; gap: 12px; min-width: 0;
  /* [2026-09-22][CLX][КП-V2] Поле по краям. С 13.09 страница КП идёт без рамки (`.content--edge`,
     padding 0) — прежняя карточка несла поля сама (`.kp-head` 16 px), а экран v2 не нёс никаких:
     шапка «‹ Список КП» и карточки стояли вплотную к меню (замечание Александра 22.09).
     16 px — как у полосы «Найдено» списка КП, одинаково слева и справа. */
  padding: 12px 16px 24px;
  font-family: var(--font-ui, 'DM Sans', 'Segoe UI', sans-serif); font-size: 13px; line-height: 18px; color: var(--kp2-ink);
}
.kp2 h1, .kp2 h2, .kp2-headbar h1 { margin: 0; font-size: inherit; font-weight: inherit; }
.kp2-spacer { flex: 1 1 auto; }
/* [2026-09-21][CLX][КП-V2] загрузка/ошибка экрана v2 — отступ классом (сторож ui-one-place §6) */
.kp2-state { padding: 40px; }

/* Пилюли — один вид в двух тонах. */
.kp2-pill { flex: none; display: inline-flex; align-items: center; height: 22px; padding: 0 8px; border-radius: 999px; font-size: 12px; line-height: 16px; white-space: nowrap; }
.kp2-pill--need { background: var(--kp2-need-bg); color: var(--kp2-need-text); box-shadow: inset 0 0 0 1px var(--kp2-need); }
.kp2-pill--ok { background: var(--kp2-ok-bg); color: var(--kp2-ok-text); }

/* Номер группы: цифра, пока в группе чего-то не хватает; галочка — когда готово. */
.kp2-gn { flex: none; width: 22px; height: 22px; border-radius: 50%; display: grid; place-items: center; font-size: 12px; font-weight: 600; background: var(--kp2-need); color: #fff; }
.kp2-gn.is-ok { background: var(--kp2-ok); }

/* Сетка ≈33/67 (было 40/60 §6.2; [2026-09-22][CLX][КП-V2] решение Александра 22.09: таблице товаров нужнее — на 1440
   с меню правая колонка 780 → 880 px, у формы клиента остаётся ≥ 360 px). */
.kp2-grid { display: grid; grid-template-columns: minmax(360px, 1fr) minmax(0, 2fr); gap: 12px; align-items: start; }
.kp2-col { display: flex; flex-direction: column; gap: 12px; min-width: 0; }

.kp2-card { background: var(--kp2-card); border: 1px solid var(--kp2-line); border-radius: 10px; min-width: 0; }
.kp2-card__h { display: flex; align-items: center; gap: 8px; width: 100%; min-height: 44px; padding: 10px 12px; border: 0; background: none; font: inherit; color: inherit; text-align: left; }
button.kp2-card__h { cursor: pointer; border-radius: 10px; }
button.kp2-card__h:hover h2 { color: var(--kp2-acc); }
.kp2-card__h h2 { flex: none; font-size: 15px; line-height: 20px; font-weight: 600; }
.kp2-card__sum { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--kp2-ink-2); }
.kp2-card__chev { flex: none; width: 16px; height: 16px; color: var(--kp2-ink-3); transition: transform .15s; }
.kp2-card__chev svg { width: 16px; height: 16px; display: block; }
.kp2-acc.is-open .kp2-card__chev { transform: rotate(180deg); }
.kp2-card__b { padding: 0 12px 12px; }
/* [2026-09-22][CLX][КП-V2] Было `overflow-x: auto` — для прежней таблицы (до R2). 🪤 overflow-x ≠ visible
   делает и overflow-y обрезающим: меню «Добавить» (ещё товар · аксессуар · из каталога) вылезает за
   карточку и срезалось её краем — на пустом КП видно одну первую строку меню (замечание Александра 22.09).
   Таблица R2 прокручивается вбок сама (`.kp2t-body { overflow: auto }`), здесь только не даём распирать колонку. */
.kp2-items { min-width: 0; }
/* Свёрнутый блок, в котором чего-то не хватает, — оранжевый (§15). */
.kp2-acc.is-need { border-color: var(--kp2-need); background: var(--kp2-need-bg); }
.kp2-acc.is-need .kp2-card__sum { color: var(--kp2-need-text); }

/* Поля. */
.kp2-client { display: flex; flex-direction: column; gap: 10px; }
.kp2-f2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px 10px; }
.kp2-fld { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.kp2-fld--wide { grid-column: 1 / -1; }
.kp2-fld__l { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; font-size: 12px; line-height: 16px; color: var(--kp2-ink-2); }
.kp2-fld__m { color: var(--kp2-need-text); font-weight: 600; }
.kp2-fld__m.is-ok { color: var(--kp2-ok-text); }
.kp2-fld__o { color: var(--kp2-ink-3); }
.kp2-fld .input, .kp2-fld .select, .kp2-client > .kp2-f2 .input { width: 100%; }
.kp2-fld.need .input, .kp2-fld.need .select { border-color: var(--kp2-need); background: var(--kp2-need-bg); }
.kp2-auto { padding: 0 6px; border-radius: 999px; background: var(--kp2-acc-bg); color: var(--kp2-ink-2); }
.kp2-ok { margin-left: 2px; }
.kp2-chk { display: inline-flex; align-items: center; gap: 4px; margin-left: auto; color: var(--kp2-ink-2); cursor: pointer; }
.kp2-note { font-size: 12px; line-height: 16px; color: var(--kp2-ink-2); }
.kp2-hint { color: var(--kp2-ink-2); display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.kp2-hint b { color: var(--kp2-ink); font-weight: 600; }

/* Переключатель — сегменты одной высоты. */
.kp2-seg { display: inline-flex; flex-wrap: wrap; border: 1px solid var(--kp2-line); border-radius: 6px; overflow: hidden; background: var(--bg-input, #FAF7F4); }
.kp2-seg--fill { display: flex; }
.kp2-seg--fill > button { flex: 1 1 0; }
.kp2-seg > button { height: 30px; padding: 0 12px; border: 0; border-right: 1px solid var(--kp2-line); background: none; font: inherit; color: var(--kp2-ink-2); cursor: pointer; white-space: nowrap; }
.kp2-seg > button:last-child { border-right: 0; }
.kp2-seg > button:hover { color: var(--kp2-ink); }
.kp2-seg > button.is-on { background: var(--kp2-acc-bg); color: var(--kp2-ink); font-weight: 600; }
.kp2-seg.need { border-color: var(--kp2-need); background: var(--kp2-need-bg); }
.kp2-seg.need > button { color: var(--kp2-need-text); }

.kp2-to { display: flex; align-items: center; gap: 10px; }
.kp2-to__l { flex: none; font-weight: 600; }
.kp2-to .kp2-seg { flex: 1 1 auto; }

/* Номер КП + «Подтвердить» — первая строка «Клиента» (§6 ответ 5). */
.kp2-num { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 8px 10px; border-radius: 8px; background: var(--bg-secondary, #F7F3EE); }
.kp2-num.need { background: var(--kp2-need-bg); box-shadow: inset 0 0 0 1px var(--kp2-need); }
.kp2-num__v { font-weight: 600; font-variant-numeric: tabular-nums; }
.kp2-num__d { font-weight: 400; color: var(--kp2-ink-2); }
.kp2-num__edit { flex: none; width: 26px; height: 26px; display: grid; place-items: center; border: 0; border-radius: 6px; background: none; color: var(--kp2-ink-3); cursor: pointer; }
.kp2-num__edit:hover, .kp2-num__edit:focus-visible { color: var(--kp2-ink); background: var(--kp2-card); }
.kp2-num__edit svg { width: 15px; height: 15px; }
.kp2-num__ok { color: var(--kp2-ok-text); font-weight: 600; }
.kp2-num .btn:disabled { opacity: .45; cursor: not-allowed; }
.kp2-num__note { flex: 1 0 100%; font-size: 12px; line-height: 16px; color: var(--kp2-ink-2); }
.kp2-num__note.is-need { color: var(--kp2-need-text); font-weight: 600; }

/* Партнёр. */
.kp2-chip { display: flex; align-items: center; gap: 8px; justify-content: space-between; padding: 6px 6px 6px 10px; border: 1px solid var(--kp2-line); border-radius: 6px; background: var(--bg-input, #FAF7F4); }
.kp2-chip small { color: var(--kp2-ink-2); font-size: 12px; }
.kp2-res { display: flex; flex-direction: column; border: 1px solid var(--kp2-line); border-radius: 6px; overflow: hidden; }
.kp2-res > button { display: block; padding: 6px 10px; border: 0; border-bottom: 1px solid var(--kp2-line); background: var(--kp2-card); font: inherit; text-align: left; cursor: pointer; }
.kp2-res > button:last-child { border-bottom: 0; }
.kp2-res > button:hover { background: var(--kp2-acc-bg); }
.kp2-res small { color: var(--kp2-ink-2); }
.kp2-ask { padding: 8px 10px; border-radius: 8px; border: 1px solid var(--kp2-line); display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; }
.kp2-ask.need { border-color: var(--kp2-need); background: var(--kp2-need-bg); }
.kp2-ask .kp-des__res { flex: 1 0 100%; }

.kp2-foot { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.kp2-foot__fam { display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; color: var(--kp2-ink-2); }

@media (max-width: 1100px) {
  .kp2-grid { grid-template-columns: minmax(0, 1fr); }
}
