/* Компоненты нового фронта. Оформление из Figma, значения — через tokens.css. */

/* --- Светлые острова на тёмной странице ---
   Страница тёмная (base.css), поэтому текст по умолчанию светлый. Блоки, где идёт работа с
   данными, остались светлыми — и обязаны вернуть себе тёмный текст, иначе получится «белое по
   белому» (ровно этот дефект ловили на встрече 21.07 в нижней части чата).
   Правило одно: поставил светлую подложку — верни --c-text. */
.card-main, .modal-box, .plan-row, .ac-box, .empty-state {
  color: var(--c-text);
}
.card-main .muted, .modal-box .muted, .plan-row .muted, .ac-box .muted {
  color: var(--c-text-muted);
}

/* --- Топбар ---
   Лежит прямо на тёмной странице: высота 78, лёгкое стекло, текст 14/22 (макет ВЭБ.РФ). */
.topbar-v2 {
  display: flex; align-items: center; justify-content: space-between;
  height: var(--h-header); padding: 0 var(--gutter); gap: var(--s-24);
  backdrop-filter: var(--bl-header); -webkit-backdrop-filter: var(--bl-header);
  color: var(--c-on-dark);
}
.brand-wordmark {
  color: var(--c-on-dark); font-weight: var(--fw-bold);
  letter-spacing: 4px; text-transform: uppercase; font-size: 20px; white-space: nowrap;
}
/* Шапка-пользователь: иконка · имя · организация · выход. Всё 14/22 по макету. */
.topbar-user {
  display: flex; align-items: center; gap: var(--s-8); color: var(--c-on-dark);
  font-size: var(--fs-body); line-height: var(--lh-header);
}
.tb-user-ico { display: inline-flex; }
.tb-name-stub { color: var(--c-on-dark-2); }   /* вход выключен — это режим, а не пользователь */
.tb-dot { color: var(--c-on-dark-2); }
.tb-org { color: var(--c-on-dark); }
.tb-logout {
  display: inline-flex; border: none; background: transparent; color: var(--c-on-dark);
  cursor: pointer; padding: 4px; line-height: 1; border-radius: var(--r-btn);
}
.tb-logout:hover { background: rgba(255, 255, 255, .12); }
.tb-admin {
  color: var(--c-on-dark); text-decoration: underline; font-size: 14px; white-space: nowrap;
}
.tb-admin:hover { opacity: .75; }
/* Плашка недоступности сервиса — показывается ТОЛЬКО когда он лежит (см. topbar.js). */
.tb-health {
  background: var(--c-status-block-bg); color: var(--c-status-block); border-radius: var(--r-pill);
  padding: 4px 12px; font-size: var(--fs-xsmall); white-space: nowrap; cursor: help;
}
/* Иконки — 24×24, красятся currentColor (см. components/icons.js). */
.ico { width: 24px; height: 24px; display: block; }

/* --- Сегмент-контрол --- */
.seg {
  display: inline-flex; align-items: center; gap: 2px;
  background: var(--c-seg-track); border: var(--bw) solid var(--c-border-seg);
  border-radius: var(--r-ctl); padding: 2px; height: var(--h-ctl);
}
.seg-btn {
  border: none; background: transparent; cursor: pointer;
  height: 40px; padding: 0 20px; border-radius: var(--r-pill);
  color: var(--c-text); font-size: var(--fs-body); line-height: var(--lh-body); white-space: nowrap;
}
.seg-btn.active { background: var(--c-navy); color: var(--c-on-primary); }

/* --- Поле поиска --- */
/* Поиск лежит на тёмной странице, а не в светлом блоке — значит стекло. */
.search {
  display: flex; align-items: center; flex: 1 1 auto; min-width: 320px;
  background: var(--c-field-dark); border: var(--bw) solid var(--c-glass-border-2);
  border-radius: var(--r-ctl); height: var(--h-ctl); padding: 10px 12px 10px 16px;
}
.search:focus-within { border-color: var(--c-glass-border-str); }
.search-input {
  border: none; outline: none; background: transparent; width: 100%;
  font-size: var(--fs-body); line-height: var(--lh-body); color: var(--c-on-dark);
}
.search-input::placeholder { color: var(--c-on-dark-2); }

/* --- Строка фильтров --- */
.filters { display: flex; align-items: center; gap: var(--s-8); margin-bottom: var(--s-24); }

/* --- Список позиций --- */
.list-head, .plan-row {
  display: grid; align-items: center; gap: var(--s-16);
  grid-template-columns: 56px 340px 1fr 140px 64px 160px 150px 24px;
}
.pr-no { color: var(--c-text-muted); }
.pr-amount { color: var(--c-text); text-align: right; white-space: nowrap; }
.list-head .cell-num { text-align: right; }
/* Шапка списка лежит на тёмной странице, а не на карточке. */
.list-head {
  padding: 0 26px 8px; color: var(--c-on-dark-2); font-weight: var(--fw-med); font-size: var(--fs-body);
}
.list { display: flex; flex-direction: column; gap: var(--gap-card); }
.plan-row {
  background: var(--c-card); border-radius: var(--r-card);
  padding: 24px 26px; cursor: pointer; transition: box-shadow .12s ease, transform .12s ease;
}
.plan-row:hover { box-shadow: 0 6px 24px rgba(27, 37, 77, .12); transform: translateY(-1px); }
.pr-ikz { color: var(--c-navy); font-weight: var(--fw-med); word-break: break-all; }
.pr-name { color: var(--c-text); }
.pr-okpd2 { color: var(--c-text-muted); }
.pr-year { color: var(--c-text-muted); }
.pr-warn { color: var(--c-status-warn); font-size: var(--fs-xsmall); }
.pr-arrow { color: var(--c-navy); text-align: right; }

/* --- Пустое состояние --- */
.empty-state {
  background: var(--c-card); color: var(--c-text); max-width: 900px;
}
.empty-state h2 { margin: 0 0 12px; color: var(--c-navy); font-family: var(--f-head); }
.empty-state p { margin: 0; color: var(--c-text-muted); }

/* --- Заглушка карточки --- */
.card-stub { background: var(--c-card); }
.back-link { color: var(--c-on-dark-2); cursor: pointer; display: inline-block; margin: 8px 0 16px; }
.back-link:hover { color: var(--c-on-dark); }

/* --- Карточка позиции: шапка --- */
.pos-header { display: flex; align-items: center; gap: var(--s-16); flex-wrap: wrap; margin: 8px 0 24px; }
/* «Добавить позицию» — кнопка есть в ЛЮБОМ состоянии карточки, прижата к правому краю шапки.
   Название переносится внутри своей колонки (flex:1 + min-width:0), а не спихивает кнопку на
   следующую строку — иначе у длинных наименований она отрывалась от шапки. */
.pos-header > div:first-child { flex: 1 1 auto; min-width: 0; }
.btn-add { flex: 0 0 auto; margin-left: auto; }
/* Шапка позиции — на тёмной странице. Надзаголовок приглушён, имя позиции 40/100% bold (макет). */
.pos-sub { color: var(--c-on-dark-2); font-size: var(--fs-xsmall); text-transform: uppercase; letter-spacing: 1px; }
.pos-ikz { font-family: var(--f-head); font-weight: var(--fw-bold); font-size: var(--fs-3xl); line-height: 1.15; color: var(--c-on-dark); word-break: break-word; }
/* Реквизиты позиции плана под названием: ИКЗ · сумма · год, разделители приглушены (макет). */
.pos-meta {
  display: flex; flex-wrap: wrap; gap: var(--s-8); align-items: baseline; margin-top: var(--s-16);
  color: var(--c-on-dark); font-size: var(--fs-body); line-height: var(--lh-body);
}
.pm-dot { opacity: .5; }

/* --- Строка позиции (макет 758:16506) ---
   ПРОЗРАЧНАЯ: лежит прямо на чёрном фоне страницы и отделена от предыдущей позиции волоском —
   это заголовок, а не карточка. Плашки под ней быть не должно: белые блоки начинаются ниже
   (правка Дениса 22.07). Раскрытие — шевроном, независимо от соседних позиций.
   Счётчик зелёный ТОЛЬКО когда пройдено всё; пока не всё — акцентный, но не тревожный. */
.pos-row {
  display: grid; grid-template-columns: minmax(0, 1fr) auto 24px; align-items: start;
  gap: var(--s-24); padding: var(--s-32) 0 var(--s-24);
  border-top: var(--bw) solid rgba(255, 255, 255, .15);
  color: var(--c-on-dark); cursor: pointer; user-select: none;
}
.pos-row:focus-visible { outline: var(--bw-125) solid var(--c-on-dark-2); outline-offset: 4px; }
.pos-row:hover .pr-caret { color: var(--c-on-dark); }
.pr-main { min-width: 0; }
.pr-title {
  font-family: var(--f-head); font-weight: var(--fw-bold); font-size: var(--fs-xl);
  line-height: 1.15; color: var(--c-on-dark); overflow-wrap: anywhere; margin-top: 6px;
}
.pr-checks { text-align: right; white-space: nowrap; }
.pr-checks-label { color: var(--c-on-dark-2); font-size: var(--fs-md); line-height: var(--lh-flat); }
.pr-checks-val {
  font-weight: var(--fw-bold); font-size: var(--fs-xl); line-height: 1.15; color: var(--c-accent);
  margin-top: 6px;
}
.pos-row .pos-sub { text-transform: none; letter-spacing: 0; font-size: var(--fs-md); }
.pr-checks.is-done .pr-checks-val { color: var(--c-status-ok-on-dark); }
/* Шеврон один на оба состояния — раскрытый разворачивается поворотом (см. chevron() в positionCard). */
.pr-caret {
  display: flex; align-items: center; justify-content: center; width: 24px; height: 24px;
  color: var(--c-on-dark-2); transition: transform .15s ease, color .12s ease;
}
.pos-row.is-open .pr-caret { transform: rotate(180deg); }
/* Блоки раскрытой позиции — под её строкой, с воздухом до следующей. */
.pos-item { margin: 0 0 var(--s-24); }

/* --- ЕДИНЫЙ КОНТРАКТ БЕЛОГО БЛОКА (макет 758:16506, решение ревью 22.07) ---
   «Привести отображение карточек и характеристик к единообразию: единый отступ, шрифты, радиус
   скругления». До этого каждый блок нёс свои числа (24/32, 8/32/20, 8/32/24, 20/24) и свой
   нижний зазор (16 или 8), поэтому одинаковые по смыслу секции стояли на разной высоте и с
   разной рамкой. Геометрия теперь ОДНА и живёт в токенах; отдельным блокам ниже разрешено
   менять только подложку и содержимое, но не поля и не радиус. */
.summary-card, .checks-panel, .char-summary, .trade-names, .interaction-card, .docs-bar,
.std-section, .std-confirm, .price-section, .facet-sec, .helper-note, .relax,
.ident-edit, .delivery-form, .add-char-form, .coll, .card-stub, .empty-state {
  border-radius: var(--r-card);
  padding: var(--p-card);
  margin-bottom: var(--gap-card);
}

/* --- Сводка --- */
.summary-card { background: var(--c-card); }
/* minmax(0,1fr), а не 1fr: у `auto`-трека минимум = min-content, и длинное неразрывное значение
   (код КТРУ, наименование) распирало грид шире карточки — отсюда горизонтальный скролл всей
   страницы при открытом чате (замечание встречи 20.07). То же во всех парах «лейбл — значение». */
.summary-row { display: grid; grid-template-columns: var(--col-label) minmax(0, 1fr); gap: var(--s-20); align-items: baseline; padding: var(--row-y) 0; }
.summary-row .s-label { color: var(--c-text-muted); }
.summary-row .s-val { color: var(--c-text); overflow-wrap: anywhere; }
/* Запрос цен по позиции — отделён от строк сводки чертой сверху, кнопка на всю ширину блока. */
.summary-price-req { margin-top: var(--s-16); padding-top: var(--s-16); border-top: var(--bw) solid var(--c-border-seg); }
.summary-price-req .btn { width: 100%; }
.summary-price-req .s-hint { margin-top: var(--s-8); font-size: 13px; }

/* --- Панель проверок (тёмная navy) --- */
.checks-panel {
  background: linear-gradient(160deg, var(--c-navy), var(--c-navy-deep));
  color: var(--c-on-primary);
}
.checks-panel h3 {
  margin: 0 0 var(--s-16); font-family: var(--f-head); font-weight: var(--fw-bold);
  font-size: var(--fs-lg); line-height: var(--lh-flat);
}
.check-row {
  display: grid; grid-template-columns: 24px minmax(0, 320px) minmax(0, 1fr); gap: var(--s-16); align-items: start;
  padding: 10px 0; border-top: 1px solid rgba(255, 255, 255, .08);
}
/* Узко (карточка рядом с чатом) — сообщение под заголовком, а не третьей колонкой в 80 px. */
@media (max-width: 1500px) {
  .check-row { grid-template-columns: 24px minmax(0, 1fr); }
  .check-row .check-msg { grid-column: 2; }
}
.check-row:first-of-type { border-top: none; }
.check-ico { line-height: var(--lh-body); }
.check-title { color: rgba(255, 255, 255, .92); overflow-wrap: anywhere; }
/* Было rgba(...,.68) — на navy это ~3.6:1, ниже AA для основного текста (замечание про контраст). */
.check-msg { color: rgba(255, 255, 255, .85); overflow-wrap: anywhere; }
.check-row.r-ok .check-ico { color: var(--c-status-ok); }
/* Пояснение красим тем же цветом, что и заголовок строки: жёлтая шапка с белым текстом читалась
   как два разных сообщения (дизайн-ревью 23.07). */
.check-row.r-warn .check-ico, .check-row.r-warn .check-title, .check-row.r-warn .check-msg { color: var(--c-status-warn); }
.check-row.r-block .check-ico, .check-row.r-block .check-title, .check-row.r-block .check-msg { color: var(--c-status-block); }
.check-row.r-unknown .check-ico { color: rgba(255, 255, 255, .5); }

/* --- Общие параметры --- */
/* Заголовок блока в макете один на все карточки: 20/100% bold, ЧЁРНЫЙ, на 32 от верха блока и
   на 16 над содержимым (1014:51209 → 1014:51212: 32 → 68). Было 24 navy у одних блоков и 18 navy
   у сворачивалок — третье расхождение ревью 22.07 («отличаются шрифты»). */
.section-title {
  font-family: var(--f-head); font-weight: var(--fw-bold); font-size: var(--fs-lg);
  line-height: var(--lh-flat); color: var(--c-text); margin: 0 0 var(--s-16);
}
/* Шаг строки по макету: строка 20 + 12 = 32. Колонка лейбла 234 (в макете 234 + 441 = 675) —
   было 280 с зазором 24, из-за чего между подписью и значением зияла дыра (замечание 21.07).
   Значение — обычный текст без рамки: рамка вокруг НЕредактируемого значения читалась как поле ввода. */
.param-row { display: grid; grid-template-columns: var(--col-label) minmax(0, 1fr); gap: var(--s-20); align-items: baseline; padding: var(--row-y) 0; }
.param-row .p-label { color: var(--c-text-muted); }
.param-val {
  min-height: var(--lh-body); display: flex; align-items: center; color: var(--c-text);
  overflow-wrap: anywhere;   /* длинное наименование переносим, а не распираем карточку */
}
/* Порог 1200, а не 1500: колонка подписи теперь 192 (была 234–320), и на типовых 1440 пара
   «подпись — значение» помещается в строку, как в макете. На 1500 сводка ломалась в столбик
   ровно на самом ходовом разрешении. */
@media (max-width: 1200px) {
  .param-row, .summary-row { grid-template-columns: minmax(0, 1fr); gap: var(--s-8); }
}

/* --- Сворачиваемый блок карточки (components/collapsible) ---
   Карточка по одной позиции должна помещаться на экран: наружу торчит заголовок + сводка,
   поля правки разворачиваются по клику (решение 20.07). */
.coll { background: var(--c-card); }
/* Шапка сворачивалки — та же строка заголовка, что и .section-title у несворачиваемых блоков:
   поля даёт сам блок, шеврон стоит СПРАВА (макет: Component 84/«3» на 716 из 766), а не слева.
   Из-за левого шеврона и своего padding 16/24 сворачиваемые секции стояли уже и ниже соседних —
   это и есть «карточки в развёрнутом и свёрнутом состояниях скомпонованы по-разному». */
.coll-head {
  display: flex; align-items: center; gap: var(--s-12); cursor: pointer;
  user-select: none;
}
.coll-head:hover .coll-title { color: var(--c-navy); }
.coll-head:focus-visible { outline: 2px solid var(--c-navy); outline-offset: 4px; border-radius: var(--r-xs); }
.coll-caret {
  margin-left: auto; width: 24px; height: 24px; flex: 0 0 auto;
  display: flex; align-items: center; justify-content: center;
  color: var(--c-text-muted); font-size: 14px; transition: color .12s;
}
.coll-head:hover .coll-caret { color: var(--c-text); }
.coll-title {
  font-family: var(--f-head); font-weight: var(--fw-bold); font-size: var(--fs-lg);
  line-height: var(--lh-flat); color: var(--c-text);
}
.coll-action { margin-left: auto; color: var(--c-text-muted); font-size: var(--fs-xsmall); white-space: nowrap; }
/* «Развернуть/Свернуть» рядом с шевроном — второй маркер одного и того же действия; в макете
   в шапке блока только шеврон. Состояние остаётся озвученным (aria-expanded на .coll-head). */
.coll-action { display: none; }
.coll-badge {
  border-radius: var(--r-pill); padding: 2px 10px; font-size: var(--fs-xsmall);
  font-weight: var(--fw-med); white-space: nowrap;
}
.coll-badge.warn { background: var(--c-status-warn-bg); color: var(--c-status-warn-ink); }
.coll-badge.block { background: var(--c-status-block-bg); color: var(--c-status-block); }
.coll-summary { padding-top: var(--s-16); color: var(--c-text); overflow-wrap: anywhere; }
.coll-body { padding-top: var(--s-16); }
/* Внутри блока секции уже имеют свои отступы — гасим верхний, иначе двойной воздух под заголовком. */
/* Заголовок в ТЕЛЕ сворачивалки дублирует её шапку («Место, срок поставки…», «НМЦК по
   коммерческим предложениям…», «Количество и единица измерения» — все шли дважды, второй раз
   более крупно, и читались как вложенная секция). Прячем только внутри блока: те же секции
   рисуются и standalone (режим выбора стандартов, ослабление выборки), там заголовок нужен. */
.coll-body > *:first-child > .section-title:first-child,
.coll-body > .section-title:first-child { display: none; }
/* Блок внутри сворачивалки — уже внутри белой карточки: свои поля и скругление он не рисует,
   иначе получается «карточка в карточке» с двойным отступом и вложенным радиусом 28. */
.coll-body .summary-card, .coll-body .char-summary,
.coll-body .trade-names, .coll-body .interaction-card, .coll-body .std-section,
.coll-body .std-confirm, .coll-body .price-section, .coll-body .facet-sec,
.coll-body .ident-edit, .coll-body .delivery-form, .coll-body .add-char-form,
.coll-summary .summary-card, .coll-summary .char-summary,
.coll-summary .trade-names, .coll-summary .price-section {
  padding: 0; border-radius: 0;
}
.coll-body > *:last-child, .coll-summary > *:last-child { margin-bottom: 0; }
/* Панель проверок — тёмная плашка на белом блоке, единственный вложенный блок со своей заливкой.
   Поля ей обнулять нельзя (текст лип бы к краю заливки), и радиус нужен вложенный: с padding:0 и
   radius:0 она растекалась до самых краёв карточки и срезалась её скруглениями. */
.coll-body .checks-panel, .coll-summary .checks-panel {
  padding: 20px 24px; border-radius: var(--r-inner);
}
/* Подзаголовок ГРУППЫ внутри блока — на ступень мельче заголовка блока: 16 bold, как «Источники
   цен» внутри «Контрактов и цен» в макете (1040:54201 против 1040:54200). Одним размером с
   заголовком блока группы «Необязательные (КТРУ)» / «Дополнительные (свои)» читались как
   самостоятельные секции. */
.coll-body .section-title { font-size: var(--fs-md); margin-top: var(--s-24); }
.coll-body > *:first-child .section-title:first-child,
.coll-body > .section-title:first-child { margin-top: 0; }

/* --- Свёрнутый блок характеристик: только значения, без контролов --- */
.char-summary { background: var(--c-card); }
.cs-row {
  display: grid; grid-template-columns: var(--col-label) minmax(0, 1fr); gap: var(--s-20);
  padding: var(--row-y) 0; border-top: 1px solid #eef1f8; align-items: baseline;
}
.cs-row:first-child { border-top: none; }
.cs-name { color: var(--c-text-muted); overflow-wrap: anywhere; }
.cs-name .req { color: var(--c-status-block); margin-left: 2px; }
.cs-val { color: var(--c-text-strong); font-weight: var(--fw-med); overflow-wrap: anywhere; }
/* Незаполненная обязательная — видно и в свёрнутом виде, иначе сворачивание прячет работу. */
.cs-row.cs-empty .cs-val { color: var(--c-status-block); font-weight: var(--fw-bold); }
/* Сверхкаталожная без подтверждённого обоснования — блокирует сборку документов, поэтому красным
   и видно в свёрнутом блоке (замечание 20.07). */
.cs-warn {
  display: inline-block; margin-left: var(--s-8); padding: 1px 8px; border-radius: var(--r-pill);
  background: var(--c-status-block-bg); color: var(--c-status-block);
  font-size: var(--fs-xsmall); font-weight: var(--fw-med);
}
/* Незаполненные существенные условия поставки — их отсутствие видно в сводке блока. */
.cs-missing { color: var(--c-status-warn-ink); font-size: var(--fs-xsmall); margin-top: 4px; }
.char-need {
  background: var(--c-status-block-bg); color: var(--c-status-block); border-radius: var(--r-pill);
  padding: 2px 10px; font-size: var(--fs-xsmall); font-weight: var(--fw-med); white-space: nowrap;
}
.char-toggle { margin-left: auto; white-space: nowrap; }
@media (max-width: 1200px) { .cs-row { grid-template-columns: minmax(0, 1fr); gap: 2px; } }

/* --- Заголовок секции с действием (напр. «✎» правки идентификации) --- */
.section-head { display: flex; align-items: center; gap: var(--s-8); justify-content: flex-end; }
.section-head:empty { display: none; }
.section-head .section-title { margin-bottom: var(--s-16); }
.icon-btn {
  border: none; background: transparent; cursor: pointer; color: var(--c-navy);
  border-radius: var(--r-btn); padding: 4px 8px; font-size: 16px; line-height: 1;
}
.icon-btn:hover:not(:disabled) { background: rgba(27, 37, 77, .08); }
.icon-btn:disabled { opacity: .35; cursor: default; }

/* Формы правки (идентификация, условия поставки, добавление характеристики) — общая сетка.
   Вертикальный ритм полей = 15: в макете «Вёрстка блоков» (1252:93761) строки идут с шагом 39 =
   контрол 24 + зазор 15 (Group 5104…5107 внутри блока стоят на y 0/39/78/117). Раньше был gap 24
   (шаг ~48) — по этому спейсинг-этюду блоки выходили воздушнее макета. .f-row свой padding гасит
   (ниже), поэтому зазор строк — ровно этот flex-gap. Кнопка действий отбивается отдельно
   (.form-actions margin-top), иначе на 15 она липла бы к последнему полю. */
.ident-edit, .delivery-form, .add-char-form {
  display: flex; flex-direction: column; gap: 15px;
  background: var(--c-card);
}
.ident-edit .f-row, .delivery-form .f-row, .add-char-form .f-row { padding: 0; }
/* Поля форм карточки — ПОДЧЁРКИВАНИЕ, а не рамка (замечание 21.07: «вместо подчёркивания
   обрамление», и расстояния слишком большие). Коробка вокруг каждого поля превращала плотную
   таблицу «характеристика — значение» в сетку клеток и съедала вертикаль: три поля в строке
   «от – до – ЕИ» читались как три отдельных контрола вместо одного диапазона.
   Эти формы живут только в светлых блоках карточки, поэтому правило общее, без скоупа. */
.ident-edit input, .ident-edit select,
.delivery-form input, .delivery-form select,
.add-char-form input, .add-char-form select, .qty-form input, .char-ctl input, .char-ctl select {
  border: none; border-bottom: var(--bw) solid var(--c-border-input); border-radius: 0;
  height: 28px; padding: 0 2px 4px; font-size: var(--fs-body);
  background: transparent; color: var(--c-text-strong);
  transition: border-color .12s; min-width: 0;
}
.ident-edit input:hover, .delivery-form input:hover, .add-char-form input:hover,
.qty-form input:hover, .char-ctl input:hover, .char-ctl select:hover {
  border-bottom-color: var(--c-border-input-hover);
}
.ident-edit input:focus, .delivery-form input:focus, .add-char-form input:focus,
.qty-form input:focus, .char-ctl input:focus, .char-ctl select:focus {
  border-bottom-color: var(--c-navy); border-bottom-width: var(--bw-125); outline: none;
}
/* Кнопка блока — СПРАВА внизу (макет «Вёрстка блоков» 1252:93761, Component 114): главная кнопка
   каждого блока прижата к правому краю, второстепенная (Отмена/Добавить) — ghost слева от неё.
   Раньше «Сохранить» стояла слева и мелкой (btn-sm) — это и есть расхождение спейсинг-ревью. */
.form-actions { display: flex; gap: var(--s-8); justify-content: flex-end; margin-top: var(--s-16); margin-bottom: var(--s-16); }

/* --- Динамический контрол значения (components/dynField) ---
   Макет 758:16506: значение — это сам текст (bold 14/20), подчёркнутый ровно по своей ширине, а
   единица измерения стоит рядом отдельным контролом («35 дней», «100 штук», «80 °C»). Ширину
   считает JS по содержимому и пишет inline — здесь только оформление.
   Ширину НЕ трогаем: любое width/flex-grow отсюда переспорило бы посчитанное значение, поэтому
   явный flex:0 0 auto — иначе поле в flex-строке растянулось бы на всю колонку. */
input[data-dyn], select[data-dyn] {
  flex: 0 0 auto;
  border: none; border-bottom: var(--bw) solid var(--c-border-input); border-radius: 0;
  height: 24px; padding: 0 4px 3px; background: transparent;
  font-family: inherit; font-size: var(--fs-body); line-height: var(--lh-body);
  color: var(--c-text-strong);
}
input[data-dyn="value"] { font-weight: var(--fw-bold); }
input[data-dyn="unit"], select[data-dyn="unit"] { font-weight: var(--fw-med); color: var(--c-text); }
/* Плейсхолдер тем же жирным читался как ЗАПОЛНЕННОЕ значение (пустой «Вид НКМИ» выглядел как
   вписанный) — подсказка обязана быть легче и тише самого значения. */
input[data-dyn]::placeholder { font-weight: var(--fw-reg); color: var(--c-text-muted); }
input[data-dyn]:hover, select[data-dyn]:hover { border-bottom-color: var(--c-border-input-hover); }
input[data-dyn]:focus, select[data-dyn]:focus { border-bottom-color: var(--c-navy); border-bottom-width: var(--bw-125); outline: none; }
/* Стрелки счётчика у числовых полей ломают измеренную ширину (браузер добавляет свои ~17px) —
   значение съезжало бы под подчёркивание соседнего контрола. */
input[data-dyn][type="number"] { -moz-appearance: textfield; appearance: textfield; }
[data-dyn][type="number"]::-webkit-outer-spin-button,
[data-dyn][type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
/* Список (варианты каталога) — тот же подчёркнутый контрол, стрелку рисуем сами: системная у
   <select> занимает непредсказуемую ширину, и посчитанная под текст ширина резала бы значение. */
select[data-dyn] {
  -webkit-appearance: none; appearance: none; cursor: pointer;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
                    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: right 8px top 9px, right 3px top 9px;
  background-size: 5px 5px, 5px 5px; background-repeat: no-repeat;
}
/* Зеркало для измерения ширины: вне потока, но с реальным шрифтом поля. */
#dyn-mirror {
  position: absolute; left: -9999px; top: 0; visibility: hidden;
  white-space: pre; pointer-events: none;
}

/* --- Количество ---
   Стопка строк «подпись — поле», как у остальных форм карточки (правка 23.07). Раньше здесь была
   строка из трёх контролов (значение, единица, «Сохранить») — единственная такая на карточке. */
.qty-form { display: flex; flex-direction: column; gap: 15px; margin-bottom: var(--s-8); }


.qty-help { padding: 8px 0; font-size: 14px; }
.qty-help.ok { color: var(--c-status-ok); }
.qty-help.bad { color: var(--c-status-warn); }

/* --- Характеристики --- */
.char-group { display: flex; flex-direction: column; gap: 4px; margin-bottom: var(--s-16); }
.char-group > .muted { padding: 8px 0; }
.char-row {
  display: grid; grid-template-columns: var(--col-label) minmax(0, 1fr); gap: var(--s-20); align-items: center;
  padding: var(--row-y) 0;
}
.char-name { color: var(--c-text-strong); }
.char-name .req { color: var(--c-status-block); margin-left: 2px; }
.char-badge {
  font-size: var(--fs-xsmall); background: #eef1f8; color: var(--c-navy);
  border-radius: var(--r-pill); padding: 2px 8px; margin-left: 6px;
}
.char-ctl { display: flex; align-items: center; gap: var(--s-8); min-width: 0; }


.char-unit-pick { color: var(--c-status-warn); font-size: 14px; }
/* Подсказка каталога и обоснование — во второй колонке, под контролом. */
.char-allowed, .char-justif { grid-column: 2; font-size: 14px; }
.char-row .char-allowed { padding-bottom: 4px; }

/* Диапазон «от–до» с живой проверкой границ по справочнику КТРУ. */
.cp-range-wrap { min-width: 0; }
.cp-range { display: flex; align-items: center; gap: var(--s-8); }
.cp-range input { min-width: 0; }
.cp-dash { color: var(--c-text-muted); }
.cp-range-err { color: var(--c-status-block); font-size: 13px; padding-top: 4px; }
.char-ctl input.bad, .add-char-form input.bad {
  border-bottom-color: var(--c-status-block); border-bottom-width: var(--bw-125); background: transparent;
}

/* Выбор варианта из каталога: список + подпись про уже сохранённый набор значений. */
.cp-pick { min-width: 0; }
.cp-cur { font-size: 13px; padding-top: 4px; }

/* Наборы вариантов из каталога (чекбоксы/пилюли) — форма «набор значений» в добавлении характеристики. */
.cp-variants { display: flex; flex-wrap: wrap; gap: var(--s-8); flex: 1 1 auto; }
.cp-variant {
  display: inline-flex; align-items: center; gap: 6px; background: var(--c-card);
  border: var(--bw) solid var(--c-border-input); border-radius: var(--r-pill); padding: 6px 12px;
  cursor: pointer; font-size: 14px;
}
.cp-variant input { accent-color: var(--c-navy); }

/* Необязательные характеристики каталога — чекбоксами. */
.oc-item {
  display: flex; align-items: baseline; gap: var(--s-8); padding: 8px 12px; cursor: pointer;
  background: var(--c-card); border-radius: var(--r-ctl);
}
.oc-item input { accent-color: var(--c-navy); }
.oc-name { color: var(--c-text-strong); }
.oc-hint { font-size: 13px; margin-left: auto; text-align: right; }
/* Включённая необязательная — полная строка со значением; чекбокс у имени её и снимает. */
.oc-cb { accent-color: var(--c-navy); margin-right: 8px; }

/* Обоснование доп. характеристики (✦ AiJustify из макета). */
.char-justif {
  background: var(--c-card); border-radius: var(--r-ctl); padding: 12px 16px; margin: 4px 0 8px;
  border-left: 3px solid var(--c-navy);
}
.char-justif.confirmed { border-left-color: var(--c-status-ok); }
.cj-label { color: var(--c-text-muted); font-size: 13px; margin-bottom: 6px; }
.cj-text {
  width: 100%; border: var(--bw) solid var(--c-border-input); border-radius: var(--r-ctl);
  padding: 10px 14px; font-family: inherit; font-size: 14px; color: var(--c-text-strong); resize: vertical;
}
.cj-bar { display: flex; gap: var(--s-8); margin-top: var(--s-8); }

/* Добавление своей характеристики. */
.add-char { margin-top: var(--s-12); }
.add-char-acts { display: flex; gap: var(--s-8); }
.add-char-val { display: flex; gap: var(--s-8); flex-wrap: wrap; }

.add-char-forbidden {
  background: var(--c-status-block-bg); color: var(--c-status-block); border-radius: var(--r-ctl);
  padding: 12px 16px; font-size: 14px;
}
/* Бейдж даты обязательного применения КТРУ (ПП № 145) — в заголовке секции. */
.pp145 {
  font-size: var(--fs-xsmall); border-radius: var(--r-pill); padding: 3px 10px; margin-left: var(--s-12);
  font-weight: var(--fw-reg); vertical-align: middle; white-space: nowrap;
}
/* Текстом на светлой подложке — тёмная «чернильная» версия: сам --c-status-warn (#d98a00) на белом
   даёт ~2.9:1 и не проходит AA. Как иконка/рамка он остаётся. */
.pp145-now { background: var(--c-status-warn-bg); color: var(--c-status-warn-ink); }
.pp145-later { background: #eef1f8; color: var(--c-text-muted); }

/* --- Торговые наименования (реестр МИ, справочно) --- */
.trade-names { background: var(--c-card); }
.tn-head { display: flex; align-items: center; gap: var(--s-12); }
.tn-head .section-title { margin: 0; }
.tn-total { font-size: 14px; margin-top: 4px; }
.tn-toggle { margin-left: auto; }
.tn-note { font-size: 13px; margin-bottom: var(--s-12); }
.tn-list { display: flex; flex-direction: column; gap: var(--s-8); }
.tn-item { border-top: 1px solid #eef1f8; padding: var(--row-y) 0; }
.tn-name { color: var(--c-text-strong); }
.tn-meta { color: var(--c-text-muted); font-size: 13px; }
.tn-codes { display: flex; flex-wrap: wrap; gap: var(--s-8); margin-top: 6px; }
.tn-code { font-size: var(--fs-xsmall); background: #f2f4fa; color: var(--c-text-muted); border-radius: var(--r-pill); padding: 2px 8px; }
.tn-code-vid { background: var(--c-navy); color: var(--c-on-primary); }

/* --- Кнопки ---
   Геометрия из макета (Component 111/112): h49, радиус 16, паддинг 12/32/12/24, иконка+текст в
   строку через 8. Главное действие — оранжевый градиент бренда, второстепенное — белая кнопка с
   волоском. Тёмно-синих кнопок больше нет: «кнопки сделать рыжими как в дизайне все»
   (Доработка_дизайна.md, §Общее). */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s-8);
  border: var(--bw) solid rgba(0, 0, 0, .15); border-radius: var(--r-btn-lg);
  height: var(--h-btn); padding: 12px 32px 12px 24px; cursor: pointer;
  background: var(--c-card); color: var(--c-text);
  font-family: var(--f-base); font-size: var(--fs-body); font-weight: var(--fw-med);
}
.btn:hover:not(:disabled) { background: var(--c-input-bg-hover); }
.btn:disabled { opacity: .5; cursor: default; }
.btn-primary { background: var(--g-accent); color: var(--c-on-primary); border-color: transparent; }
/* Градиент нельзя «подсветить» сменой цвета — осветляем фильтром, чтобы стопы остались на местах. */
.btn-primary:hover:not(:disabled) { background: var(--g-accent); filter: brightness(1.08); }
.btn-primary:disabled { opacity: .5; cursor: default; }
.btn-ghost { background: transparent; color: var(--c-text); }
.btn-ghost:hover:not(:disabled) { background: rgba(0, 0, 0, .04); }
/* Мелкая кнопка внутри плотных блоков (строка характеристики, панель разведки): пропорции те же,
   но ростом с поле ввода — иначе строка таблицы разъезжается под кнопку в 49px. */
.btn-sm { height: var(--h-ctl); padding: 0 16px; border-radius: var(--r-ctl); gap: 6px; }

/* Кнопки НА ТЁМНОМ (чат): белая плашка второстепенной кнопки там читается как чужеродная —
   в макете это стекло с белым текстом (Component 68 «Далее»). Оранжевая остаётся оранжевой. */
.chat-panel .btn:not(.btn-primary) {
  background: var(--c-glass-1); border-color: var(--c-glass-border-1); color: var(--c-on-dark);
  backdrop-filter: var(--bl-glass); -webkit-backdrop-filter: var(--bl-glass);
}
.chat-panel .btn:not(.btn-primary):hover:not(:disabled) { background: var(--c-glass-2); border-color: var(--c-glass-border-2); }
.btn-danger { background: transparent; color: var(--c-status-block); border: var(--bw) solid var(--c-status-block); }
.btn-danger:hover { background: var(--c-status-block); color: var(--c-on-primary); }

/* Подвал позиции: исключение позиции — действие второго плана, поэтому справа и «тихой» кнопкой. */
.card-foot { display: flex; justify-content: flex-end; margin-top: var(--s-12); }

/* Состояния полей ввода (Figma «Состояния» 441:38763): default → hover/active меняют подложку
   и бордер. Одним правилом на все текстовые контролы — чтобы состояния не расходились по экранам. */
.cp-search, .cp-okei, .cp-qtyval, .q-item input, .q-item select, .search-input {
  transition: background-color .12s, border-color .12s;
}
/* ⚠ Светлая подсветка hover/focus — ТОЛЬКО для полей на светлых блоках. .search-input сюда не
   входит: поиск лежит на тёмной странице, и эта подсветка красила его в #f4f5fe, то есть поле
   становилось белым под курсором, а текст в нём (белый на тёмном) пропадал. Правило стоит ниже
   объявления .search-input и молча его перебивало. */
.cp-search:hover, .cp-okei:hover, .cp-qtyval:hover, .q-item input:hover, .q-item select:hover,
.cp-search:focus, .cp-okei:focus, .cp-qtyval:focus, .q-item input:focus, .q-item select:focus {
  background: var(--c-input-bg-hover); border-color: var(--c-border-input-hover); outline: none;
}
/* Поиск на тёмном: подсветка тоже тёмная, фон поля не трогаем — он у контейнера .search. */
.search-input:hover, .search-input:focus { background: transparent; outline: none; }

/* --- Поля ввода в СВЕТЛЫХ блоках карточки: подчёркивание, а не рамка ---
   Замечание 21.07: в блоках «вместо подчёркивания обрамление» и слишком большие расстояния.
   Коробка вокруг каждого поля дробила плотную таблицу «характеристика — значение» на клетки;
   подчёркивание оставляет строку строкой и экономит вертикаль. Рамки сохраняем только там, где
   контрол реально объёмный (textarea, зона перетаскивания). */
.card-main .cp-search,
.card-main .cp-okei,
.card-main .cp-qtyval,
.card-main .q-item input,
.card-main .q-item select,
.card-main .char-val input,
.card-main .char-val select {
  background: transparent; border: none; border-bottom: var(--bw) solid var(--c-border-input);
  border-radius: 0; height: 28px; padding: 0 2px 4px;
}
.card-main .cp-search:hover, .card-main .cp-okei:hover, .card-main .cp-qtyval:hover,
.card-main .q-item input:hover, .card-main .q-item select:hover,
.card-main .char-val input:hover, .card-main .char-val select:hover {
  background: transparent; border-bottom-color: var(--c-border-input-hover);
}
.card-main .cp-search:focus, .card-main .cp-okei:focus, .card-main .cp-qtyval:focus,
.card-main .q-item input:focus, .card-main .q-item select:focus,
.card-main .char-val input:focus, .card-main .char-val select:focus {
  background: transparent; border-bottom-color: var(--c-navy); border-bottom-width: var(--bw-125);
}
/* Строки уточнений: шаг 32, без разделительной линейки на каждой строке. */
.card-main .q-item { padding: var(--row-y) 0; border-top: none; }

/* Стартовый блок «нет проработки» больше не живёт в теле карточки: создание позиции ведёт
   чат-мастер справа (.chat-panel > .cp-start), см. замечания к тесту 17.07. */

/* --- Каталог-пикер КТРУ --- */
.catalog-picker { display: flex; flex-direction: column; gap: var(--s-12); }
.cp-search, .cp-okei, .cp-qtyval {
  border: var(--bw) solid var(--c-border-input); border-radius: var(--r-ctl); height: var(--h-ctl);
  padding: 0 14px; font-size: var(--fs-body); background: var(--c-card); color: var(--c-text-strong);
}
/* Выбранная позиция и её собственные количество/ЕИ — одним блоком (макет 1139:87699):
   чип с крестиком, под ним два поля. Блоки идут стопкой, между ними зазор больше, чем между
   полями внутри, — иначе три позиции читаются как одна лестница из шести одинаковых строк. */
.cp-picked { display: flex; flex-direction: column; gap: var(--s-16); }
.cp-pick { display: flex; flex-direction: column; gap: var(--s-8); }
.cp-chip { display: flex; align-items: flex-start; gap: var(--s-8); background: #eef1f8; color: var(--c-navy);
  border-radius: var(--r-ctl); padding: 12px 16px; font-size: 14px; }
/* Крестик прижат к правому краю чипа и не сжимается — имя позиции занимает две-три строки. */
.chip-x { margin-left: auto; border: none; background: transparent; cursor: pointer;
  color: var(--c-navy); flex: 0 0 auto; line-height: 1; }
.cp-qtyval, .cp-okei { width: auto; }
.catalog-picker input { min-width: 0; }

/* --- Автокомплит (position:fixed на body) --- */
.ac-box { position: fixed; z-index: 1000; background: var(--c-card); border: var(--bw) solid var(--c-border-input);
  border-radius: var(--r-ctl); box-shadow: 0 8px 28px rgba(27,37,77,.16); max-height: 320px; overflow-y: auto; }
.ac-item { padding: 10px 14px; cursor: pointer; display: flex; flex-direction: column; gap: 4px; }
.ac-item:hover { background: #f2f4fa; }
.ac-main { display: flex; align-items: center; gap: 8px; }
.ac-freq { margin-left: auto; color: var(--c-text-muted); font-size: 12px; white-space: nowrap; }
.ac-freq-empty { color: var(--c-status-warn); }
.ac-empty { padding: 10px 14px; color: var(--c-text-muted); }
/* Различающие характеристики одноимённых КТРУ (объём, коннектор…) — под названием */
.ac-keychars { display: flex; flex-wrap: wrap; gap: 4px 10px; font-size: var(--fs-xsmall); }
.ac-kc { color: var(--c-text-muted); white-space: nowrap; }
.ac-kc b { color: var(--c-text); font-weight: var(--fw-med); }

/* Автокомплит, открытый ИЗ ЧАТА, — на тёмном стекле (класс ставит features/autocomplete.js).
   Тот же список из блоков карточки остаётся светлым. */
.ac-box.on-dark {
  background: #10182b; border-color: var(--c-glass-border-2); color: var(--c-on-dark);
  box-shadow: none;
  backdrop-filter: var(--bl-input); -webkit-backdrop-filter: var(--bl-input);
}
.ac-box.on-dark .ac-item:hover { background: rgba(255, 255, 255, .08); }
.ac-box.on-dark .ac-freq,
.ac-box.on-dark .ac-empty,
.ac-box.on-dark .ac-kc { color: var(--c-on-dark-2); }
.ac-box.on-dark .ac-kc b { color: var(--c-on-dark); }

/* --- Подбор КТРУ по характеристикам из документа --- */
.ktru-suggest { margin-top: var(--s-8); }
.ktru-suggest-list { display: flex; flex-direction: column; gap: 4px; margin-top: var(--s-8); }
.ktru-suggest-item {
  border: var(--bw) solid var(--c-border-seg); border-radius: var(--r-ctl); padding: 10px 12px;
  cursor: pointer; font-size: 13px;
}
.ktru-suggest-item:hover { border-color: var(--c-navy); background: #f5f6fb; }
.ktru-suggest-item.sel { border-color: var(--c-navy); background: #eef1f8; }
.ks-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s-8); }
.ks-code { color: var(--c-navy); font-weight: var(--fw-med); }
.ks-name { color: var(--c-text); }
/* Счёт совпавших характеристик — факт, поэтому по умолчанию нейтральный. Зелёным становится
   только когда сошлись ВСЕ обязательные и нет конфликтов значений, то есть кандидат действительно готов. */
.ks-badge { margin-left: auto; background: var(--c-status-info-bg); color: var(--c-status-info-ink); border-radius: var(--r-pill); padding: 2px 8px; font-size: var(--fs-xsmall); white-space: nowrap; }
.ks-badge.is-complete { background: var(--c-status-ok-bg); color: #16603c; }
.ks-badge.has-conflict { background: var(--c-status-warn-bg); color: var(--c-status-warn-ink); }
.ks-keyvals, .ks-reason { color: var(--c-text-muted); margin-top: 4px; }
.ks-empty { color: var(--c-text-muted); font-size: 13px; padding: 6px 0; }

/* --- Виджеты уточнений (pending) --- */
.interaction-card { background: var(--c-card); }
.q-block { display: flex; flex-direction: column; gap: var(--s-12); }
.q-focus { display: flex; gap: 10px; align-items: baseline; }
.q-focus-num { color: var(--c-text-muted); font-size: 12px; text-transform: uppercase; letter-spacing: 1px; }
.q-focus-name { font-weight: var(--fw-med); color: var(--c-navy); }
.q-text { color: var(--c-text-strong); font-weight: var(--fw-med); }
.q-help { color: var(--c-text-muted); font-size: 14px; }
.q-item { display: flex; flex-direction: column; gap: 6px; padding: 10px 0; border-top: 1px solid #eef1f8; }
.q-item input, .q-item select {
  border: var(--bw) solid var(--c-border-input); border-radius: var(--r-ctl); height: var(--h-ctl);
  padding: 0 14px; font-size: var(--fs-body); background: var(--c-card); color: var(--c-text-strong);
}
.q-item.sev-critical .q-text::after { content: " • обязательно"; color: var(--c-status-block); font-weight: 400; font-size: 12px; }
.q-actions { display: flex; gap: var(--s-8); margin-top: var(--s-12); }

/* --- Раскладка карточки: заголовок и карточка слева, чат-мастер справа ---
   Чата нет (позиция создана после всех уточнений) — карточка занимает всю ширину.
   Заголовок позиции — часть ЛЕВОЙ колонки (.card-col), а не отдельный блок над раскладкой:
   в макете чат начинается на одной линии с ним (см. positionCard.js). Зазор колонок 40 — по
   макету: карточка кончается на 820, чат начинается на 860. */
.card-layout { display: grid; grid-template-columns: 1fr; gap: var(--s-24); align-items: start; }
.card-layout.with-chat { grid-template-columns: minmax(0, 1fr) var(--w-chat); column-gap: var(--s-40); }
.card-col { min-width: 0; }
/* Верхний отступ заголовка гасим: в колонке он сдвигал бы вниз только левый столбец, и чат
   переставал бы совпадать с линией выравнивания. Отбивку от «К списку позиций» даёт back-link. */
.card-col > .pos-header { margin-top: 0; }
.card-main { min-width: 0; }
@media (max-width: 1280px) { .card-layout.with-chat { grid-template-columns: 1fr; } }

/* --- Чат-панель (мастер создания позиции) --- */
/* Чат — тёмное стекло по макету 1139:87364: диагональная засветка вместо заливки белым, поэтому
   панель прозрачная и берёт цвет от фона страницы (ревью 23.07). Шапки-плашки с названием в
   макете НЕТ — панель начинается сразу с текста; убрана вместе с надписью «Проработка закупки».
   Тени нет: высоту даёт уровень стекла и бордер. */
.chat-panel {
  position: sticky; top: 24px; display: flex; flex-direction: column; max-height: calc(100vh - 48px);
  background: var(--c-glass-panel); border: var(--bw) solid var(--c-glass-border-1);
  border-radius: var(--r-card); overflow: hidden; color: var(--c-on-dark);
  backdrop-filter: var(--bl-glass); -webkit-backdrop-filter: var(--bl-glass);
}
.chat-panel .muted { color: var(--c-on-dark-2); }
/* Ряд действий над лентой: без заголовка и без линейки — в нём живёт только «Очистить».
   Пустым не рисуется (chatPanel.js добавляет его лишь когда есть что чистить). */
.cp-head { display: flex; align-items: center; gap: var(--s-8);
  padding: var(--p-chat-panel) var(--p-chat-panel) 0; color: var(--c-on-dark); }
.cp-clear {
  margin-left: auto; border: 1px solid rgba(255, 255, 255, .45); background: transparent;
  color: var(--c-on-primary); cursor: pointer; font-size: var(--fs-xsmall);
  padding: 4px 10px; border-radius: var(--r-pill); white-space: nowrap;
}
.cp-clear:hover { background: rgba(255, 255, 255, .14); }
/* Крестик стоит после «Очистить» — прижимать к правому краю должен он, иначе кнопки слипаются. */
.cp-clear + .cp-close { margin-left: var(--s-8); }
.cp-close { margin-left: auto; border: none; background: transparent; color: var(--c-on-primary);
  cursor: pointer; font-size: 16px; line-height: 1; padding: 4px; }
.cp-body { flex: 1 1 auto; overflow-y: auto; padding: var(--p-chat-panel); }
/* Поле панели уже задано .cp-body; ряд «Очистить» стоит над ним и свой верхний отступ отдаёт. */
.cp-head + .cp-body { padding-top: var(--s-12); }
.cp-start .muted { margin: 0 0 20px; }
/* Композер внутри панели — не плавающий: он часть диалога, а не оверлей над карточкой.
   Собственных боковых границ у него нет — он лежит в панели и закругляется её нижними углами. */
.chat-panel .chat-composer {
  position: static; width: auto; box-shadow: none;
  border: none; border-top: var(--bw) solid var(--c-glass-border-1); border-radius: 0;
}
.chat-panel .chat-log { margin: 0 0 12px; }
.chat-panel .msg { max-width: 100%; }
.chat-panel .interaction-card { padding: 0; margin: 0; }
/* В узкой панели кол-во и ЕИ встают друг под друга: в строку они сжимались до нечитаемых обрубков. */
.chat-panel .cp-pick { align-items: stretch; }
/* Чип выбранной позиции в чате — по макету 1139:87699: стекло контролов, радиус 16, тот же
   вертикальный ритм, что у полей под ним. */
.chat-panel .cp-chip {
  border-radius: var(--r-chat-ctl); padding: var(--p-chat-ctl); font-size: var(--fs-body);
  line-height: var(--lh-body);
}

/* --- Контролы ВНУТРИ чата: тёмное стекло ---
   Правило Дениса 21.07: дропдаун и прочие контролы наследуют контекст — в чате тёмная подложка,
   в блоках карточки светлая. Поэтому здесь переопределяем только то, что живёт в чате;
   те же классы в .card-main остаются светлыми.

   Геометрия и заливка — из макета 1139:87388 (ревью 23.07 «контролы более аккуратные»):
   радиус 16 вместо 12, поле 16/24 вместо высоты 40 (контрол становится 49 и перестаёт душить
   текст), волосок 10% вместо 15% и та же диагональная засветка, что у панели, — вместо заливки
   белым на 15%, из-за которой поля читались как светлые плашки. Зазор между полями 8. */
.chat-panel .cp-search,
.chat-panel .cp-okei,
.chat-panel .cp-qtyval,
.chat-panel .q-item input,
.chat-panel .q-item select {
  height: auto; padding: var(--p-chat-ctl); border-radius: var(--r-chat-ctl);
  background: var(--c-glass-ctl); border-color: var(--c-glass-border-1); color: var(--c-on-dark);
  backdrop-filter: var(--bl-glass); -webkit-backdrop-filter: var(--bl-glass);
  transition: background-image .12s, border-color .12s;
}
/* Плейсхолдер в макете — белый в половину силы, а не отдельный серый цвет. */
.chat-panel .cp-search::placeholder,
.chat-panel .cp-okei::placeholder,
.chat-panel .cp-qtyval::placeholder,
.chat-panel .q-item input::placeholder { color: var(--c-on-dark); opacity: .5; }
.chat-panel .cp-search:hover, .chat-panel .cp-okei:hover, .chat-panel .cp-qtyval:hover,
.chat-panel .q-item input:hover, .chat-panel .q-item select:hover {
  background: var(--c-glass-ctl-hi);
}
.chat-panel .cp-search:focus, .chat-panel .cp-okei:focus, .chat-panel .cp-qtyval:focus,
.chat-panel .q-item input:focus, .chat-panel .q-item select:focus {
  background: var(--c-glass-ctl-hi); border-color: var(--c-glass-border-2); outline: none;
}
.chat-panel .catalog-picker { gap: var(--s-8); }
/* Стрелки-крутилки числового поля рисует ОС БЕЛОЙ плашкой — на тёмном стекле она читалась как
   посторонний прямоугольник в углу поля (в макете 1139:87699 её нет). Количество набирают с
   клавиатуры; шаг стрелками для тысяч штук бесполезен. */
.chat-panel .cp-qtyval::-webkit-outer-spin-button,
.chat-panel .cp-qtyval::-webkit-inner-spin-button,
.chat-panel .q-item input[type=number]::-webkit-outer-spin-button,
.chat-panel .q-item input[type=number]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.chat-panel .cp-qtyval, .chat-panel .q-item input[type=number] { -moz-appearance: textfield; appearance: textfield; }

/* Нативный <option> рисует ОС, и на прозрачном фоне он остаётся системным — задаём явный тёмный,
   иначе в раскрытом списке белый текст ложится на белое. */
.chat-panel .cp-okei option,
.chat-panel .q-item select option { background: #10182b; color: var(--c-on-dark); }

.chat-panel .cp-chip { background: var(--c-glass-2); color: var(--c-on-dark); }
.chat-panel .chip-x { color: var(--c-on-dark-2); }
.chat-panel .chip-x:hover { color: var(--c-on-dark); }
.chat-panel .cp-dash { color: var(--c-on-dark-2); }
.chat-panel .cp-variant input { accent-color: var(--c-accent); }

/* Текстовые роли и составные блоки внутри чата — на тёмном. */
.chat-panel .interaction-card { background: none; color: var(--c-on-dark); }
.chat-panel .q-text { color: var(--c-on-dark); }
.chat-panel .q-help,
.chat-panel .q-focus-num { color: var(--c-on-dark-2); }
.chat-panel .q-focus-name { color: var(--c-on-dark); }
.chat-panel .q-item { border-top-color: var(--c-glass-border-1); }

/* Главное действие чата — АКЦЕНТНОЕ (макет 1139:87542, ревью 23.07). Раньше здесь стояло стекло,
   и «Создать позиции» ничем не отличалось от полей над ней: единственное действие панели читалось
   как ещё один контрол. Градиент — общий --g-accent, он же на кнопках карточки.
   Ширина во всю панель и радиус 16 — как в макете. */
.chat-panel .btn-primary {
  width: 100%; border-radius: var(--r-chat-ctl); border-color: transparent;
  background: var(--g-accent); color: var(--c-on-primary);
}
.chat-panel .btn-primary:hover:not(:disabled) { filter: brightness(1.08); }
/* Плюс на кнопке — 12 в боксе 24, как в макете: полноразмерная иконка спорит по весу с текстом. */
.chat-panel .btn-primary .ico { width: 12px; height: 12px; }
.chat-panel .btn-ghost { color: var(--c-on-dark-2); }
.chat-panel .btn-ghost:hover { background: rgba(255, 255, 255, .1); color: var(--c-on-dark); }

/* Зона перетаскивания КП в чате — оранжевый пунктир по макету (999:47270): рамка цвета акцента,
   подложка — тот же градиент в 10%. Это единственное место, где акцентом красится не кнопка:
   зона и есть приглашение к действию. */
.chat-panel .kp-drop {
  border: 1px dashed var(--c-accent-to); border-radius: var(--r-btn-lg);
  background: var(--g-accent); color: var(--c-accent);
  padding: 19px 36px;
}
.chat-panel .kp-drop::before {   /* гасим градиент до 10%, не трогая цвет текста */
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  background: rgba(0, 0, 0, .9); pointer-events: none;
}
.chat-panel .kp-drop { position: relative; overflow: hidden; }
.chat-panel .kp-drop > * { position: relative; z-index: 1; }
.chat-panel .kp-drop:hover, .chat-panel .kp-drop.over { border-color: var(--c-accent-from); }
.chat-panel .kp-drop:hover::before, .chat-panel .kp-drop.over::before { background: rgba(0, 0, 0, .8); }
.chat-panel .kp-drop-title { color: var(--c-accent); font-weight: var(--fw-med); }
.chat-panel .kp-drop-hint { color: var(--c-on-dark-2); }

/* --- Подбор КТРУ в чате: карточки-кандидаты и варианты выбора ---
   Эти блоки рисуются и в карточке (светло), и в чате (тёмно), а стили были только светлые —
   в чате они выпадали из общего вида. Тёмный вариант скоупим по .chat-panel. */
.chat-panel .ktru-suggest-item {
  background: var(--c-glass-1); border-color: var(--c-glass-border-1); color: var(--c-on-dark);
}
.chat-panel .ktru-suggest-item:hover {
  background: var(--c-glass-2); border-color: var(--c-glass-border-2);
}
.chat-panel .ktru-suggest-item.sel {
  background: var(--c-glass-2); border-color: var(--c-glass-border-str);
}
.chat-panel .ks-code { color: var(--c-on-dark); }
.chat-panel .ks-name { color: var(--c-on-dark); }
.chat-panel .ks-keyvals,
.chat-panel .ks-reason,
.chat-panel .ks-empty { color: var(--c-on-dark-2); }

.chat-panel .pick-option {
  background: var(--c-glass-1); border-color: var(--c-glass-border-1); color: var(--c-on-dark);
}
.chat-panel .pick-option:hover {
  background: var(--c-glass-2); border-color: var(--c-glass-border-2);
}
.chat-panel .pick-name,
.chat-panel .pick-diff,
.chat-panel .pick-trade { color: var(--c-on-dark); }
.chat-panel .pick-code,
.chat-panel .pick-makers,
.chat-panel .pick-why { color: var(--c-on-dark-2); }
.chat-panel .pick-badge {
  background: var(--c-glass-2); border: var(--bw) solid var(--c-glass-border-2); color: var(--c-on-dark);
}
/* Статусные цвета на тёмном: светлые подложки нечитаемы, красим текстом. */
.chat-panel .pick-chars { color: #9db4ff; }
.chat-panel .pick-chars.is-empty { color: #ffc98a; }
.chat-panel .ks-badge { background: var(--c-glass-2); color: var(--c-on-dark); }
.chat-panel .ks-badge.is-complete { background: var(--c-status-ok-glass); color: #b9f5d2; }
.chat-panel .ks-badge.has-conflict { background: var(--c-status-warn-glass); color: #ffd9a3; }

/* Плашки ленты по kind — на тёмном тонированным стеклом, а не светлой заливкой. */
.chat-panel .msg.k-warn {
  background: var(--c-status-warn-glass); border-color: var(--c-glass-border-2); color: #ffd9a3;
}
.chat-panel .msg.k-answer_rejected {
  background: var(--c-status-block-glass); border-color: var(--c-glass-border-2); color: #ffc0ae;
}

/* --- Зона перетаскивания КП (только там, где КП можно приложить) ---
   Макет 1139:88095: пунктир и текст АКЦЕНТНЫЕ, подложка тёплая и почти прозрачная. Прежний
   светлый вариант (серый пунктир на светло-сером) достался от карточки и в тёмной панели читался
   как выключенный блок — при том, что это приглашение к действию. */
.kp-drop {
  margin-top: var(--s-12); padding: 24px 16px; text-align: center; cursor: pointer;
  border: 1px dashed var(--c-accent); border-radius: var(--r-chat-ctl);
  background: rgba(255, 122, 40, .06); transition: border-color .12s, background-color .12s;
}
.kp-drop:hover, .kp-drop.over { border-color: var(--c-accent-to); background: rgba(255, 122, 40, .14); }
.kp-drop-title { color: var(--c-accent); font-weight: var(--fw-med); }
/* Подсказка про форматы — тем же акцентом в половину силы: в макете под зоной второй строки нет,
   но перечень расширений здесь единственное место, где он вообще сказан. */
.chat-panel .kp-drop-hint { color: var(--c-accent); opacity: .7; font-size: var(--fs-xsmall); margin-top: 4px; }
.kp-drop-hint { font-size: var(--fs-xsmall); margin-top: 4px; }
.cp-resume { margin-top: var(--s-12); }
.cp-add { margin-top: var(--s-8); }
/* Композер выключен (идёт прогон / документы собраны) — видно, что ввод сейчас не примут. */
.chat-composer.is-off { opacity: .55; }
.cc-icon:disabled, .cc-send:disabled { cursor: not-allowed; opacity: .5; }
/* Документы, убранные в подвал кнопкой «Продолжить работу над позициями». */
.docs-stashed { margin-top: var(--s-24); padding-top: var(--s-16); border-top: 1px solid rgba(27,37,77,.12); }

/* --- Чат-лог --- */
/* Бабл ассистента — стекло L1 во всю ширину колонки; бабл пользователя — стекло L2, прижат
   вправо и шире контента не растягивается. Радиус 20, текст 16/20 (макет). */
.chat-log { display: flex; flex-direction: column; gap: var(--gap-msg); margin: 16px 0 96px; }
/* pre-line — реплики бывают МНОГОСТРОЧНЫМИ: выбор позиций и ответы по позиции приходят списком
   (макет 1139:87837), и без него всё склеивалось в один абзац. Переносы длинных слов при этом
   остаются обычными: pre-line сохраняет только явные \n. */
.msg {
  max-width: 720px; padding: 20px 24px; border-radius: var(--r-inner); white-space: pre-line;
  background: var(--c-glass-1); border: var(--bw) solid var(--c-glass-border-1);
  color: var(--c-on-dark); font-size: var(--fs-md); line-height: var(--lh-body);
  backdrop-filter: var(--bl-glass); -webkit-backdrop-filter: var(--bl-glass);
}
.msg.assistant { align-self: stretch; }
.msg.system { align-self: center; color: var(--c-on-dark-2); background: none; border: none; backdrop-filter: none; }
.msg.user {
  align-self: flex-end; background: var(--c-glass-2); border-color: var(--c-glass-border-2);
  color: var(--c-on-dark);
}
/* Ожидание — БЕЛАЯ плашка (макет 999:48052): и в чате, и поверх страницы лоадер выглядит
   одинаково, поэтому «идёт работа» читается независимо от того, где человек сейчас смотрит. */
.msg.proc {
  align-self: stretch; display: flex; align-items: center; gap: 11px;
  background: #ffffff; border-color: transparent; color: var(--c-text);
  border-radius: var(--r-loader); padding: 20px 24px; font-size: var(--fs-body); line-height: 22px;
}
.spinner { width: 16px; height: 16px; border: 2px solid rgba(0,0,0,.15); border-top-color: var(--c-text);
  border-radius: 50%; display: inline-block; flex: 0 0 auto; animation: spin .8s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

/* --- Полоса ввода чата (макет 1139:87413) ---
   Две строки: поле во всю ширину сверху, иконки под ним (приложить слева, отправить справа).
   Стекло здесь ПЛОТНЕЕ панели (блюр 23 против 5) — полоса лежит поверх ленты, и текст под ней
   не должен читаться. */
.page.has-composer { padding-bottom: 120px; }
.chat-composer {
  position: fixed; right: 40px; bottom: 32px; z-index: 900;
  display: flex; flex-direction: column; gap: 13px; width: min(560px, calc(100vw - 80px));
  padding: 19px var(--p-chat-panel) 25px;
  background: var(--c-glass-bar); border: var(--bw) solid var(--c-glass-border-1);
  border-radius: var(--r-ctl);
  backdrop-filter: var(--bl-input); -webkit-backdrop-filter: var(--bl-input);
  transition: background-image .12s;
}
/* Набранный текст подсвечивает полосу — второе состояние компонента в макете (1139:87450). */
.chat-composer.has-text, .chat-composer:focus-within { background: var(--c-glass-bar-hi); }
.cc-row { display: flex; align-items: center; justify-content: space-between; }
.cc-icon {
  display: inline-flex; border: none; background: transparent; color: var(--c-on-dark);
  cursor: pointer; line-height: 0; padding: 0;
}
.cc-icon:hover { opacity: .7; }
/* Стрелка отправки: контурный квадрат, пока отправлять нечего, и акцентный — когда есть текст. */
.cc-send {
  display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px;
  padding: 0; cursor: pointer; border-radius: var(--r-btn);
  border: var(--bw) solid rgba(255, 255, 255, .4); background: transparent;
  color: var(--c-on-dark-muted); transition: background-image .12s, color .12s, border-color .12s;
}
.cc-send .ico { width: 14px; height: 14px; }
.cc-send.is-ready {
  background: var(--g-accent); border-color: transparent; color: var(--c-on-primary);
}
.cc-send.is-ready:hover { filter: brightness(1.08); }
/* overflow-y:auto без стилизации рисовал СВЕТЛЫЙ системный скроллбар — он и выглядел как
   «белый квадрат перед стрелкой». Поле растёт по высоте (см. chatComposer.js), поэтому полоса
   нужна только на пределе 120px. */
.cc-input { width: 100%; border: none; outline: none; background: transparent; resize: none;
  color: var(--c-on-dark); font-size: var(--fs-body); line-height: var(--lh-body); max-height: 120px;
  overflow-y: auto; scrollbar-width: thin; scrollbar-color: rgba(255,255,255,.3) transparent; }
.cc-input::-webkit-scrollbar { width: 6px; }
.cc-input::-webkit-scrollbar-track { background: transparent; }
.cc-input::-webkit-scrollbar-thumb { background: rgba(255,255,255,.25); border-radius: 3px; }
/* Плейсхолдер полосы ввода в макете — БЕЛЫЙ в полную силу, а не приглушённый: это приглашение
   написать, а не подпись. */
.cc-input::placeholder { color: var(--c-on-dark); opacity: 1; }

/* --- Плашка «чего ждёт ассистент» (карточка создана, чат ушёл) --- */
.helper-note {
  background: var(--c-card); border-left: 3px solid var(--c-status-warn);
}
.hn-title { color: var(--c-text-strong); font-weight: var(--fw-med); }
.hn-list { margin: var(--s-8) 0; padding-left: 20px; color: var(--c-text); }
.hn-list li { padding: 2px 0; }
.hn-hint { font-size: 13px; margin-bottom: var(--s-8); }

/* --- Полоса документов (итог по закупке) --- */
.docs-bar {
  background: var(--c-card); display: flex; flex-direction: column; gap: var(--s-12);
  align-items: flex-start;   /* иначе колоночный флекс растягивает кнопку во всю ширину полосы */
}
.docs-msg { color: var(--c-text-strong); font-weight: var(--fw-med); }
/* Указатель на непройденные проверки: полоса стоит сверху, а проверки — внизу по позициям, и без
   этой строки «Документы сформированы» читается как «всё хорошо» (встреча 20.07). */
.docs-checks-note {
  align-self: stretch; border-radius: var(--r-ctl); padding: 10px 14px;
  font-weight: var(--fw-med); border-left: 4px solid transparent;
}
.docs-checks-note.warn { background: var(--c-status-warn-bg); color: var(--c-status-warn-ink); border-left-color: var(--c-status-warn); }
.docs-checks-note.block { background: var(--c-status-block-bg); color: var(--c-status-block); border-left-color: var(--c-status-block); }
.docs-links { display: flex; flex-wrap: wrap; gap: var(--s-8); align-items: center; }
.docs-links .btn { display: inline-flex; align-items: center; text-decoration: none; }

/* --- Кнопка «Скачать документы» со списком (макет 1014:53210 + 1014:53211) --- */
.docs-dd { position: relative; }
.docs-dd-btn .ico { width: 24px; height: 24px; }
/* Тёмный контейнер и зазор 1px между белыми строками — так стопка читается как один список,
   а не как три отдельные плашки. Скругления только по краям стопки. */
.docs-dd-list {
  display: flex; flex-direction: column; gap: 1px; overflow: hidden;
  background: #040b17; border: var(--bw) solid #000; border-radius: var(--r-btn-lg);
}
/* Как выпадающий список — поверх карточки; в чате та же стопка лежит в потоке ленты. */
.docs-dd-list.is-dropdown {
  position: absolute; top: calc(100% + 8px); left: 0; z-index: 60;
  width: 452px; max-width: min(452px, calc(100vw - 48px));
  box-shadow: 0 16px 48px rgba(0, 0, 0, .45);
}
.docs-dd-list[hidden] { display: none; }
.docs-dd-item {
  display: flex; flex-direction: column; gap: var(--s-16); justify-content: center;
  padding: 16px 16px 16px 24px; background: #ffffff; color: var(--c-text); text-decoration: none;
  border: var(--bw) solid rgba(255, 255, 255, .1);
}
.docs-dd-item:first-child { border-radius: var(--r-btn-lg) var(--r-btn-lg) 0 0; }
.docs-dd-item:last-child { border-radius: 0 0 var(--r-btn-lg) var(--r-btn-lg); }
.docs-dd-item:hover { opacity: .8; }
/* Документы В ЧАТЕ — та же белая стопка (макет 1139:88095, ревью 23.07): одна карточка, строки
   разделены светлым волоском, у каждой иконка файла, имя и формат под ним. Утренние плитки-чипы
   23.07 макету не соответствовали и отменены. Отличие от выпадающего списка только в разделителе:
   там стопка лежит на светлой карточке и её края тёмные, здесь — на тёмной панели, и тёмные
   промежутки резали белый прямоугольник на три отдельных куска. */
.docs-dd-list.is-chat { gap: 0; background: #ffffff; border-color: transparent; }
.is-chat .docs-dd-item { gap: var(--s-8); border: none; }
.is-chat .docs-dd-item + .docs-dd-item { border-top: 1px solid rgba(27, 37, 77, .12); }
.is-chat .dd-name > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cp-docs { display: flex; flex-direction: column; gap: 9px; margin-bottom: var(--gap-msg); }
.cp-docs-title { color: var(--c-on-dark); font-weight: var(--fw-bold); line-height: 22px; }
.dd-name { display: flex; align-items: center; gap: var(--s-8); font-weight: var(--fw-med); }
.dd-name .ico { width: 24px; height: 24px; opacity: .5; flex: 0 0 auto; }
.dd-meta { font-size: var(--fs-xsmall); line-height: 14px; opacity: .5; }
/* Блокирующее состояние — подложкой, а не только текстом: это стоп, а не подсказка. */
.docs-block { background: var(--c-status-block-bg); }
.docs-block .docs-msg { color: var(--c-status-block); }

/* --- Ослабление выборки (pending=relaxation) --- */
.relax {
  background: var(--c-status-warn-bg); margin-top: var(--s-24);
}
.relax-title { margin: 0 0 8px; font-family: var(--f-head); font-size: 18px; color: var(--c-text-strong); }
.relax .offer { color: var(--c-text); }
.relax-actions { display: flex; flex-wrap: wrap; gap: var(--s-8); margin-top: var(--s-12); }

/* --- Нормативные ссылки (ГОСТ/СанПиН) --- */
.std-section { background: var(--c-card); }
.std-group { margin-top: var(--s-12); }
.std-group .g-title { color: var(--c-text-muted); font-size: var(--fs-xsmall); text-transform: uppercase; letter-spacing: 1px; margin-bottom: 6px; }
.std-item { display: flex; align-items: flex-start; gap: var(--s-8); padding: 6px 0; color: var(--c-text); }
.std-item input { margin-top: 3px; accent-color: var(--c-navy); }
.std-confirm {
  background: var(--c-card);
  display: flex; flex-direction: column; gap: var(--s-12); align-items: flex-start;
}

/* --- Ценообразование (наша сводка в стиле дизайна; 3D-плашек из макета нет — решение Дениса) --- */
.price-section { background: var(--c-card); }
.price-reference { background: #f7f8fc; }        /* справочный источник — тише авторитетного */
/* Метрики цены (макет 1158:89114): четыре колонки простым текстом, ЗНАЧЕНИЕ над подписью, обе
   строки 14/20 — на белом блоке в макете нет ни одной заливки, кроме статусного баннера.
   Колонки в макете идут по сетке ~160 от левого поля блока; у нас блок шире 766, поэтому равные
   доли — так первая колонка остаётся на левом поле, а остальные не разъезжаются от ширины текста. */
.price-grid {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--s-16); margin: var(--s-24) 0;
}
.price-kpi { min-width: 0; }
.price-kpi .v { font-weight: var(--fw-bold); font-size: var(--fs-body); line-height: var(--lh-body);
  color: var(--c-text-strong); overflow-wrap: anywhere; }
.price-kpi .k { font-size: var(--fs-body); line-height: var(--lh-body); color: var(--c-text); }
/* Справочный блок (цены «для сравнения») тише авторитетного — он не про решение по НМЦК. */
.price-reference .price-kpi .v, .price-reference .price-kpi .k { color: var(--c-text-muted); }
@media (max-width: 900px) { .price-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* Сообщения по цене (объяснение, расхождение с КП, неоднородность выборки) — «Component 99»
   макета (1158:89136, сверка 23.07): полоса 1px слева цветом статуса, заливка ГРАДИЕНТОМ от 10–20%
   этого цвета к прозрачному, поле 24/16, текст 14/20, без скругления. Была сплошная плашка с
   радиусом 12 — на белом блоке она читалась как отдельная карточка, а не как пометка к нему. */
.v-msg {
  padding: 16px 24px; margin: var(--s-12) 0; font-size: var(--fs-body); line-height: var(--lh-body);
  color: var(--c-text); border-left: var(--bw) solid rgba(0, 0, 0, .35);
  background: linear-gradient(90deg, rgba(0, 0, 0, .06) 0%, rgba(0, 0, 0, 0) 60%);
}
.v-msg.warn-msg {
  color: var(--c-text); border-left-color: var(--c-status-warn);
  background: linear-gradient(90deg, rgba(217, 138, 0, .18) 0%, rgba(217, 138, 0, 0) 60%);
}
.v-msg.ok-msg {
  color: var(--c-text); border-left-color: var(--c-status-ok);
  background: linear-gradient(90deg, rgba(42, 157, 99, .18) 0%, rgba(42, 157, 99, 0) 60%);
}
/* Нейтральный факт — не зелёный (см. --c-status-info в tokens.css). */
.v-msg.info-msg {
  color: var(--c-text); border-left-color: var(--c-status-info);
  background: linear-gradient(90deg, rgba(58, 91, 191, .14) 0%, rgba(58, 91, 191, 0) 60%);
}
/* Приглушённая пометка — это подпись, а не баннер: ни полосы, ни заливки, ни поля. */
.v-msg.muted { background: none; border-left: none; color: var(--c-text-muted); padding: 4px 0; }
.kp-bad { margin-top: 6px; display: flex; flex-direction: column; gap: 2px; }
.src-delta { color: var(--c-status-block); }

/* Таблицы контрактов (ТОП-3, разведка, позиции контракта). */
.contracts { overflow-x: auto; margin: var(--s-8) 0; }
.contracts table { width: 100%; border-collapse: collapse; font-size: 14px; table-layout: auto; }
/* nowrap оставляем только там, где перенос вредит (номера, суммы, даты) — наименование переносится.
   Раньше nowrap стоял на ВСЕХ ячейках, и длинный предмет контракта гнал горизонтальный скролл. */
/* Поля ячейки — по вертикали, слева НОЛЬ: первая колонка таблицы обязана стоять на левом поле
   блока, как заголовок и все прочие строки (макет 1158:89114). С padding 10 она уезжала на 10 px
   правее всего остального в блоке. */
.contracts th, .contracts td { border-bottom: 1px solid #eef1f8; padding: 8px 16px 8px 0; text-align: left; }
.contracts th:last-child, .contracts td:last-child { padding-right: 0; }
.contracts .cell-name { white-space: normal; overflow-wrap: anywhere; min-width: 220px; }
/* Товарный знак — своей строкой под наименованием, а не в хвосте той же (встреча 20.07). */
.cell-tm { display: block; color: var(--c-text-muted); font-size: var(--fs-xsmall); margin-top: 2px; }
/* Числа — моноширинные цифры, но выравнивание ЛЕВОЕ, под своим заголовком (макет 1158:89114,
   сверка 23.07). Правый край смотрелся столбиком только внутри колонки: заголовки-то левые, и
   «Кол-во: 1» уезжало от слова «Кол-во» на всю ширину колонки. */
.contracts .cell-num { white-space: nowrap; font-variant-numeric: tabular-nums; }
.contracts .cell-date { white-space: nowrap; font-variant-numeric: tabular-nums; }
/* Заголовок колонки — тот же 14, что и данные (в макете размер один, разница только в цвете). */
.contracts th { color: var(--c-text-muted); font-weight: var(--fw-med); font-size: var(--fs-body); }
.contracts tr.row-drill { cursor: pointer; }
.contracts tr.row-drill:hover td { background: #f2f4fa; }
.ex-remarks { white-space: normal; }
.ex-remark { font-size: var(--fs-xsmall); border-radius: var(--r-pill); padding: 2px 8px; background: #eef1f8; color: var(--c-text-muted); }
.ex-remark.ex-warn { background: var(--c-status-warn-bg); color: var(--c-status-warn-ink); }
.ex-remark.ex-block { background: var(--c-status-block-bg); color: var(--c-status-block); }

/* НДС и выбор источника обоснования. */
.src-switch { border-top: 1px solid #eef1f8; padding-top: var(--s-12); margin-top: var(--s-12); }
.src-title { color: var(--c-text-strong); font-weight: var(--fw-med); margin-bottom: var(--s-8); }
.vat-input-row { display: flex; align-items: center; gap: var(--s-8); }
/* Оформление ставки НДС задаёт динамический контрол (components/dynField): это такое же значение с
   единицей рядом, как «100 штук» в макете, — своей рамки у него быть не должно. */
.src-row { display: flex; flex-wrap: wrap; gap: var(--s-8); }
.src-opt {
  border: var(--bw) solid var(--c-border-input); background: var(--c-card); border-radius: var(--r-ctl);
  padding: 12px 16px; cursor: pointer; text-align: left; min-width: 200px;
}
.src-opt:hover { border-color: var(--c-navy); }
.src-opt.cur { background: var(--c-navy); color: var(--c-on-primary); border-color: var(--c-navy); cursor: default; }
.src-name { font-size: 13px; opacity: .8; }
.src-nmck { font-family: var(--f-head); font-weight: var(--fw-bold); font-size: 20px; margin: 2px 0; }
.src-sub { font-size: 13px; opacity: .8; }
.btn-link {
  border: none; background: transparent; color: var(--c-navy); cursor: pointer;
  text-decoration: underline; padding: 4px 0; font-size: 14px;
}
.src-auto { display: block; margin-top: var(--s-8); }

/* Выбор контрактов — кнопка со счётчиком (окно рисует .ctp ниже); разведка осталась раскрывашкой. */
.contract-select, .explore { border-top: 1px solid #eef1f8; padding-top: var(--s-12); margin-top: var(--s-12); }
.explore summary { cursor: pointer; color: var(--c-navy); font-weight: var(--fw-med); padding: 4px 0; }
.contract-select { display: flex; align-items: center; gap: var(--s-12); flex-wrap: wrap; }
.ctp-count { font-size: var(--fs-body); }

/* --- Окно подбора контрактов (макет 1014:51292) ---
   Колонки те же, что в списке источников цен: реестр · цена · кол-во · регион · дата, слева
   галка «в расчёт», справа глаз — провал в карточку. */
.ctp { display: flex; flex-direction: column; }
.ctp-row {
  display: grid; align-items: center; gap: var(--s-16);
  grid-template-columns: 20px minmax(160px, 1.4fr) 110px 90px minmax(120px, 1fr) 110px 24px;
  padding: 6px 0; cursor: pointer;
}
.ctp-head { color: var(--c-text-muted); cursor: default; padding-bottom: var(--s-8); }
.ctp-list { display: flex; flex-direction: column; }
.ctp-row:hover:not(.ctp-head) { background: var(--c-card-sunken); }
/* Чекбокс — акцентом: он и есть решение «идёт в расчёт». */
.ctp-row input[type=checkbox] { width: 20px; height: 20px; accent-color: var(--c-accent-to); cursor: pointer; }
/* «Не в расчёте» по умолчанию (не вошёл в тройку вокруг медианы) — строка приглушена, но читаема. */
.ctp-row.outlier { color: var(--c-text-muted); }
.ctp-num { text-align: right; font-variant-numeric: tabular-nums; }
.ctp-date, .ctp-reestr { font-variant-numeric: tabular-nums; }
.ctp-drill { border: none; background: transparent; color: var(--c-text-muted); cursor: pointer; padding: 0; line-height: 0; }
.ctp-drill:hover:not(:disabled) { color: var(--c-text); }
.ctp-drill:disabled { opacity: .3; cursor: default; }
.ctp-foot { display: flex; align-items: center; gap: var(--s-16); margin-top: var(--s-16); }
.ctp-pages { display: flex; gap: 4px; }
.ctp-page {
  border: none; background: transparent; color: var(--c-text-muted); cursor: pointer;
  min-width: 24px; height: 24px; border-radius: var(--r-xs); font-size: var(--fs-body);
}
.ctp-page:hover { color: var(--c-text); }
.ctp-page.is-on { color: var(--c-text); font-weight: var(--fw-bold); }

/* --- Карточка контракта (макет 999:50328 / 999:51005) ---
   Прокручиваемое окно без коробок: секции разделены волоском, строки — label слева, значение
   справа. Рамки вокруг каждой секции дробили карточку на карточки. */
.cd-back { border: none; background: transparent; color: var(--c-text-muted); cursor: pointer; padding: 0 0 var(--s-16); font-size: var(--fs-body); }
.cd-back:hover { color: var(--c-text); }
.cd-verdict {
  border-radius: var(--r-ctl); padding: 14px 18px; margin-bottom: var(--s-24);
  border-left: 4px solid transparent; line-height: var(--lh-body);
}
.cd-verdict.ok { background: var(--c-status-ok-bg); color: var(--c-text); border-left-color: var(--c-status-ok); }
.cd-verdict.warn { background: var(--c-status-warn-bg); color: var(--c-status-warn-ink); border-left-color: var(--c-status-warn); }
.cdetail .notice-sec { border: none; border-radius: 0; padding: var(--s-24) 0 0; margin: 0 0 var(--s-24); border-top: var(--bw) solid var(--c-divider); }
.cdetail .notice-sec:first-of-type { border-top: none; padding-top: 0; }
.cdetail .notice-sec-title { color: var(--c-text-strong); font-size: var(--fs-md); font-weight: var(--fw-bold); margin-bottom: var(--s-12); }
.cdetail .nf-value { font-weight: var(--fw-med); color: var(--c-text-strong); }
.ex-bar { display: flex; flex-wrap: wrap; gap: var(--s-12); align-items: center; margin: var(--s-12) 0; }
.ex-sources { display: flex; flex-wrap: wrap; gap: var(--s-12); }
.ex-chk { display: inline-flex; align-items: center; gap: 6px; cursor: pointer; font-size: 14px; }
.ex-chk input { accent-color: var(--c-navy); }
.ex-geo { display: flex; align-items: center; gap: var(--s-8); }
.ex-geo select, .ex-query input {
  height: 36px; border: var(--bw) solid var(--c-border-input); border-radius: var(--r-ctl);
  padding: 0 12px; background: var(--c-card); color: var(--c-text-strong); font-size: 14px;
}
.ex-query { flex: 1 1 320px; }
.ex-query input { width: 100%; }
.ex-actions { display: flex; gap: var(--s-8); margin-left: auto; }
.ex-result { margin-top: var(--s-12); }

/* --- What-if подбор (E4) --- */
.facet-sec { background: var(--c-card); }
.facet-summary { margin-bottom: var(--s-12); font-size: 14px; }
.facet-intro { font-size: 14px; line-height: 20px; color: var(--c-text); max-width: 680px; margin-bottom: var(--s-12); }
.facet-lead { font-size: 14px; color: var(--c-text-muted); margin: var(--s-16) 0 4px; }
/* Воронка «по коду → сопоставимо»: ширина полосы = доля от пула по коду, поэтому отсев виден
   до чтения цифр — два числа раньше назывались одним словом и сливались (замечание 21.07). */
.facet-funnel { margin: var(--s-12) 0 var(--s-16); }
.ff-step + .ff-step { margin-top: var(--s-12); }
.ff-bar { height: 8px; border-radius: var(--r-pill); background: #c9d2ea; min-width: 8px; }
.ff-step.narrow.ok .ff-bar { background: var(--c-status-ok); }
.ff-step.narrow.bad .ff-bar { background: var(--c-status-warn); }
.ff-cap { display: flex; align-items: baseline; gap: var(--s-8); margin-top: 6px; }
.ff-num { font-size: 22px; font-weight: var(--fw-med); color: var(--c-text-strong); font-variant-numeric: tabular-nums; }
.ff-title { font-size: 14px; color: var(--c-text-strong); }
.ff-note { font-size: 13px; line-height: 18px; color: var(--c-text-muted); max-width: 620px; margin-top: 2px; }
.ff-verdict { font-size: 14px; line-height: 20px; border-radius: var(--r-ctl); padding: 10px 14px; margin-top: var(--s-12); }
.ff-verdict.ok { background: var(--c-status-ok-bg); color: #16603c; }
.ff-verdict.bad { background: var(--c-status-warn-bg); color: var(--c-status-warn-ink); }
.facet-char, .facet-qty { border-top: 1px solid #eef1f8; padding: var(--s-12) 0; }
.facet-char-head { display: flex; align-items: center; gap: var(--s-8); }
.facet-name { color: var(--c-text-strong); font-weight: var(--fw-med); }
.facet-cur { font-size: 13px; margin-top: 4px; }
.badge { font-size: var(--fs-xsmall); border-radius: var(--r-pill); padding: 2px 10px; }
.badge-ok { background: var(--c-status-ok-bg); color: #16603c; }
.badge-bad { background: var(--c-status-warn-bg); color: var(--c-status-warn-ink); }
.badge-muted { background: #eef1f8; color: var(--c-text-muted); }
.facet-suggest { background: var(--c-status-warn-bg); border-radius: var(--r-ctl); padding: 10px 14px; margin-top: var(--s-8); font-size: 14px; }
/* Кнопка — своей строкой: инлайном она вклинивалась в середину предложения и рвала текст. */
.facet-suggest button { display: block; margin-top: var(--s-8); }
/* Чарт вариантов характеристики — тёмная панель (Figma «Состояния» 441:38763):
   строки «значение → бар → число контрактов», «Применить» на наведении. */
.facet-panel {
  background: linear-gradient(160deg, var(--c-navy), var(--c-navy-deep));
  border-radius: var(--r-inner); padding: 16px 20px; margin-top: var(--s-8);
}
.fp-head { display: flex; align-items: flex-start; gap: var(--s-8); margin-bottom: var(--s-12); }
.fp-title { color: var(--c-on-primary); font-size: 14px; line-height: 18px; max-width: 480px; }
.fp-hint { color: rgba(255, 255, 255, .6); font-size: 13px; margin-top: 2px; }
.facet-chart-holder { margin-top: var(--s-8); }
.facet-chart-holder .facet-panel { margin-top: 0; }
.fp-close {
  margin-left: auto; border: none; background: transparent; color: rgba(255, 255, 255, .7);
  cursor: pointer; padding: 2px 6px; line-height: 1;
}
.fp-close:hover { color: var(--c-on-primary); }
.fp-bars { display: flex; flex-direction: column; gap: 4px; }
/* Место под «Применить» резервирует САМА строка (padding-right), а кнопка лежит поверх абсолютом.
   Иначе flex-shrink ужимал бар под кнопку, и разные доли рисовались одинаковой длиной — бар врал. */
.fp-row { display: flex; align-items: center; position: relative; border-radius: var(--r-btn); padding: 2px 100px 2px 2px; }
.fp-row:hover { background: rgba(255, 255, 255, .08); }
.fp-bar {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-8);
  flex: 0 0 auto;                    /* ширина = доля от максимума, ужимать нельзя */
  background: var(--c-card); border-radius: 4px; padding: 4px 10px; min-width: 0;
  font-size: 13px; color: var(--c-text-strong); white-space: nowrap;
}
.fp-row.cur .fp-bar { background: #d7dcf2; box-shadow: inset 0 0 0 1px var(--c-navy); }
.fp-lab { overflow: hidden; text-overflow: ellipsis; }
.fp-cnt { color: var(--c-text-muted); font-variant-numeric: tabular-nums; }
/* «Применить» — только на наведении строки (в макете так же): иначе кнопка у каждой строки
   превращает чарт в частокол. Клавиатурный фокус тоже показывает — иначе действие недостижимо. */
.fp-apply {
  position: absolute; right: 8px; top: 50%; transform: translateY(-50%);
  border: none; background: transparent; color: var(--c-on-primary); cursor: pointer;
  font-size: 13px; padding: 2px 8px; border-radius: var(--r-btn); opacity: 0; transition: opacity .12s;
}
.fp-row:hover .fp-apply, .fp-apply:focus-visible { opacity: 1; }
.fp-apply:hover { background: rgba(255, 255, 255, .16); }
/* Гистограмма количества: значение → бар → частота (Histogram из макета). */
.facet-hist { display: flex; flex-direction: column; gap: 4px; margin-top: var(--s-8); }
.facet-bar-row { display: grid; grid-template-columns: 140px 1fr 48px; gap: var(--s-8); align-items: center; font-size: 13px; }
.facet-bar-lab { color: var(--c-text-muted); }
.facet-bar { background: #eef1f8; border-radius: var(--r-pill); height: 10px; overflow: hidden; }
.facet-bar-fill { background: var(--c-navy); height: 100%; }
.facet-bar-cnt { color: var(--c-text); text-align: right; }

/* --- Модалка --- */
/* Подложка нейтрально-чёрная, а не синяя: на тёмной странице синий полупрозрачный слой мутил
   и фон, и чат, вместо того чтобы просто их приглушить. */
.modal-back {
  position: fixed; inset: 0; z-index: 1200; background: rgba(0, 0, 0, .6);
  backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
  display: flex; align-items: center; justify-content: center; padding: 24px;
}
.modal-wide { width: min(1200px, 100%) !important; }   /* карточка контракта: таблицы позиций/неустоек */
.modal-box {
  background: var(--c-card); border-radius: var(--r-loader); width: min(760px, 100%);
  max-height: calc(100vh - 48px); display: flex; flex-direction: column; overflow: hidden;
  box-shadow: 0 24px 64px rgba(0, 0, 0, .5);
}
/* Шапка светлая с разделителем: navy-плашка осталась бы единственным таким элементом —
   у чата и топбара хром уже стеклянный. */
/* Волоска под шапкой нет (макет 1014:51494): заголовок, подзаголовок и содержимое читаются как
   один блок, а линия резала их на «шапку» и «форму». */
.modal-head {
  display: flex; align-items: center; gap: var(--s-8); padding: 32px 32px 0; color: var(--c-text);
}
.modal-title { font-family: var(--f-head); font-weight: var(--fw-bold); font-size: var(--fs-xl); }
.modal-sub { color: var(--c-text-muted); margin-bottom: var(--s-24); }
.modal-x { margin-left: auto; border: none; background: transparent; color: var(--c-text-muted); cursor: pointer; padding: 4px; line-height: 1; }
.modal-x:hover { color: var(--c-text); }
.modal-body { flex: 1 1 auto; overflow-y: auto; padding: var(--s-16) 32px; }
.modal-foot { display: flex; justify-content: flex-end; gap: var(--s-8); padding: var(--s-16) 32px 32px; }
/* Диалог подтверждения — узкий, текст сообщения читаемым абзацем. */
.modal-confirm { width: min(440px, 100%); }
.confirm-msg { color: var(--c-text); font-size: var(--fs-body); line-height: 1.5; }

/* Анкета в модалке: лейбл слева, контрол справа; булев флаг — чекбокс перед лейблом. */
.form-grid { display: flex; flex-direction: column; gap: var(--s-12); }
/* Та же сетка «подпись — значение», что и у характеристик: форма условий поставки стоит в одном
   столбце с ними, иначе значения в соседних блоках карточки не выравниваются. */
.f-row { display: grid; grid-template-columns: var(--col-label) minmax(0, 1fr); gap: var(--s-20); align-items: center; padding: var(--row-y) 0; }
.f-row.bool { grid-template-columns: 20px 1fr; }
.f-row label { color: var(--c-text-strong); }
/* Рамка-коробка вокруг поля — ТОЛЬКО в модалке (.form-grid). Класс .f-row переиспользуют и формы
   КАРТОЧКИ (доставка, идентификация, добавление характеристики), а там дизайн требует ПОДЧЁРКИВАНИЯ
   (см. правило «Поля форм карточки» выше). Раньше это правило было без скоупа и, стоя ниже и с той
   же специфичностью, перебивало подчёркивание карточных форм — контролы доставки/дат становились
   коробками (замечание про «не применён дизайн»). */
.form-grid .f-row input, .form-grid .f-row select {
  border: var(--bw) solid var(--c-border-input); border-radius: var(--r-ctl); height: var(--h-ctl);
  padding: 0 14px; font-size: var(--fs-body); background: var(--c-card); color: var(--c-text-strong);
}
.form-grid .f-row.bool input { height: auto; accent-color: var(--c-navy); }
/* Подсказка под полем стоит в СТОЛБЦЕ ЗНАЧЕНИЙ — там же, где поле, к которому она относится.
   Было жёстко 296 px (ни одна колонка формы там не начинается): подсказка «Вид по каталогу КТРУ»
   висела правее значений и читалась как отдельная строка ни к чему (сверка 23.07). */
.f-hint { color: var(--c-text-muted); font-size: var(--fs-body);
  padding-left: calc(var(--col-label) + var(--s-20)); }
/* Вычисляемый параметр в форме (ОКПД2 — выводится из кода КТРУ): стоит в общем столбце значений,
   но подчёркивания не имеет — подчёркивание в карточке означает «сюда можно писать». */
.f-static { color: var(--c-text-strong); font-weight: var(--fw-med); padding: 0 4px; overflow-wrap: anywhere; }

/* --- Предпросмотр извещения --- */
.notice-note { color: var(--c-text-muted); margin-bottom: var(--s-12); }
.notice-sec { border: var(--bw) solid var(--c-border-seg); border-radius: var(--r-ctl); padding: 16px; margin-bottom: var(--s-12); }
.notice-sec.agent { border-color: var(--c-navy); }
.notice-sec-title { font-weight: var(--fw-med); color: var(--c-navy); margin-bottom: var(--s-8); }
.notice-tag {
  font-size: var(--fs-xsmall); text-transform: uppercase; letter-spacing: 1px;
  background: #eef1f8; color: var(--c-text-muted); border-radius: var(--r-pill); padding: 2px 8px;
}
.notice-tag.agent { background: var(--c-navy); color: var(--c-on-primary); }
.notice-field { display: grid; grid-template-columns: 240px minmax(0, 1fr); gap: var(--s-12); padding: 4px 0; }
.nf-label { color: var(--c-text-muted); }
.nf-value { color: var(--c-text); overflow-wrap: anywhere; }
/* Таблица извещения шире модалки — скроллим ЕЁ, а не всю страницу (как в .contracts). */
.notice-sec { min-width: 0; overflow-x: auto; }
.notice-table { width: 100%; border-collapse: collapse; margin-top: var(--s-8); font-size: 14px; }
.notice-table th, .notice-table td { border: var(--bw) solid var(--c-border-seg); padding: 6px 8px; text-align: left; }
.notice-table th { background: var(--c-seg-track); color: var(--c-text-strong); font-weight: var(--fw-med); }

/* --- Блокирующий лоадер (долгое действие: LLM, поиск контрактов, сборка документов) ---
   Подложка полупрозрачная: прогресс идёт сообщениями в чат, и прятать их нельзя — видно, на чём
   стоит дело. Клики она при этом перехватывает: второе действие по сессии сервер всё равно
   отклонит (409), честнее не пустить, чем показать ошибку. */
.busy-overlay {
  position: fixed; inset: 0; z-index: 1250; display: flex; align-items: flex-start;
  justify-content: center; padding-top: 18vh; background: rgba(0, 0, 0, .45);
  backdrop-filter: blur(2px); cursor: progress;
}
.busy-overlay[hidden] { display: none; }
/* Белая плашка с блюром — та же, что у строки ожидания в чате (макет 999:48410). */
.bo-box {
  display: flex; align-items: center; gap: 11px;
  background: #ffffff; color: var(--c-text); border-radius: var(--r-loader);
  padding: var(--s-32); max-width: min(560px, calc(100vw - 48px));
  backdrop-filter: blur(22px); -webkit-backdrop-filter: blur(22px);
  box-shadow: 0 16px 48px rgba(0, 0, 0, .25);
}
.bo-spinner { flex: 0 0 auto; }
.bo-msg { font-size: var(--fs-body); line-height: 22px; }
/* Скролл НЕ блокируем: прогон идёт минутами, и читать в это время карточку и лог — законно.
   Запрещаем только действия, а их запрещает сама подложка (перехватывает клики). */

/* --- Тост --- */
.toast { position: fixed; left: 50%; bottom: 96px; transform: translateX(-50%) translateY(10px);
  background: var(--c-navy); color: var(--c-on-primary); padding: 12px 18px; border-radius: var(--r-ctl);
  opacity: 0; pointer-events: none; transition: opacity .2s, transform .2s; z-index: 1100; }
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

/* --- Шаги подбора в чате: вид НКМИ и позиция каталога (Э5) --- */
/* Кандидаты — не список ссылок, а карточки выбора: у каждой есть чем отличается от соседей,
   обоснование и число характеристик. Без этого выбор из одноимённых позиций делается вслепую. */
.pick-list { display: flex; flex-direction: column; gap: 8px; }
.pick-option { display: flex; flex-direction: column; gap: 2px; text-align: left; width: 100%;
  padding: 10px 12px; border: var(--bw) solid var(--c-border-input); border-radius: var(--r-ctl);
  background: var(--c-card); cursor: pointer; transition: background .15s, border-color .15s; }
.pick-option:hover { background: var(--c-input-bg-hover); border-color: var(--c-border-input-hover); }
.pick-name { font-weight: var(--fw-med); color: var(--c-text-strong);
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.pick-code { color: var(--c-text-muted); font-size: var(--fs-xsmall); }
/* Торговые наименования — то, по чему человек узнаёт своё изделие, когда кода не знает. */
.pick-trade { font-size: var(--fs-xsmall); color: var(--c-text); }
/* Производители: всего и из них российских — вход в разговор про нацрежим ПП 1875. */
.pick-makers { font-size: var(--fs-xsmall); color: var(--c-text-muted); }
/* Чем позиция отличается от соседних — главное поле, когда наименования совпадают. */
.pick-diff { font-size: var(--fs-xsmall); color: var(--c-text-strong); }
.pick-why { font-size: var(--fs-xsmall); color: var(--c-text-muted); font-style: italic; }
/* «характеристик в справочнике: 5» — факт, а не «всё готово»: нейтральный цвет, не зелёный. */
.pick-chars { font-size: var(--fs-xsmall); color: var(--c-status-info); }
.pick-chars.is-empty { color: var(--c-status-warn-ink); }
.pick-badge { font-size: var(--fs-xsmall); font-weight: var(--fw-reg); padding: 1px 8px;
  border-radius: var(--r-pill); background: var(--c-navy); color: var(--c-on-primary); }
.pick-requery, .pick-manual { display: flex; gap: 8px; margin-top: 4px; align-items: center; }
/* Раньше здесь была только раскладка — сами поля оставались браузерными, то есть белыми
   (и в тёмном чате это било в глаза сильнее всего). */
.pick-requery input, .pick-manual input {
  flex: 1; min-width: 0; height: 28px; padding: 0 2px 4px; font-size: var(--fs-body);
  background: transparent; color: var(--c-text-strong);
  border: none; border-bottom: var(--bw) solid var(--c-border-input); border-radius: 0;
}
.pick-requery input:focus, .pick-manual input:focus {
  outline: none; border-bottom-color: var(--c-navy); border-bottom-width: var(--bw-125);
}
.chat-panel .pick-requery input, .chat-panel .pick-manual input {
  color: var(--c-on-dark); border-bottom-color: var(--c-glass-border-2);
}
.chat-panel .pick-requery input::placeholder, .chat-panel .pick-manual input::placeholder {
  color: var(--c-on-dark-2);
}
.chat-panel .pick-requery input:focus, .chat-panel .pick-manual input:focus {
  border-bottom-color: var(--c-glass-border-str);
}

/* --- Разметка сообщений ленты по kind --- */
/* Бэк размечал сообщения давно, лента их не различала: предупреждение выглядело обычной репликой. */
.msg.k-warn { border-left: 3px solid var(--c-status-warn); background: var(--c-status-warn-bg);
  color: var(--c-status-warn-ink); }
.msg.k-answer_rejected { border-left: 3px solid var(--c-status-block);
  background: var(--c-status-block-bg); }
